# # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher # --- linux-2.4.25/Documentation/Configure.help~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/Documentation/Configure.help 2004-03-31 17:15:11.000000000 +0200 @@ -4526,6 +4526,24 @@ building a kernel for install/rescue disks or your system is very limited in memory. +Kernel Execute-In-Place from ROM +CONFIG_XIP_KERNEL + Execute-In-Place allows the kernel to run directly from + non-volatile storage, such as flash. This saves RAM space since + the text section of the kernel is not loaded from flash to + RAM. Read-write sections, such as the data section and stack, + are still copied to RAM. The XIP kernel is not compressed since it + has to run directly from flash, so it will take more space to store + it. The flash address where the kernel is linked to run from and + is stored is board dependent. Therefore, if you say Y, you must + know the proper physical address where to store the kernel image. + + Also note that the make target becomes "make xipImage" rather than + "make zImage" or "make Image". The final kernel binary to put in + ROM memory will be arch/arm/boot/xipImage. + + If unsure, say N. + # Choice: kcore Kernel core (/proc/kcore) format CONFIG_KCORE_ELF @@ -13386,6 +13404,30 @@ If you don't know what this all is, saying Y is a safe choice. +Workaround for XScale cache errata +CONFIG_XSCALE_CACHE_ERRATA + There are couple errata that say that the cache may get confused + whether some cache lines are dirty or not, resulting in some memory + corruptions. The workaround (using the cache only in write through + mode) is performance impairing, and the bug _might_ just not be + that visible or critical to you depending on many esoteric + hardware factors. + + Not using the workaround makes Linux unreliable. If you're used + to some other OSes which requires to be rebooted once in a while + then this won't look so bad to you. On the other hand you may + stress test the system for hours without seeing any effect of this + bug. + + So this is configurable. Let's hope a future core revision will tell + this was just a bad dream. But in the mean time the risk and + trade-off is yours to decide. + + This should apply to all PXA250 up to rev B2 (erratum #120) and + possibly other current XScale cores as well. + + If you don't know what to answer, say Y. + Support CD-ROM drives that are not SCSI or IDE/ATAPI CONFIG_CD_NO_IDESCSI If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y @@ -16568,6 +16610,40 @@ If unsure, say N. +Use linear addressing for cramfs +CONFIG_CRAMFS_LINEAR + This option tells the cramfs driver to load data directly from a linear + adressed memory range (usually non volatile memory like flash) instead + of going through the block device layer. This saves some memory since + no intermediate buffering is necessary. + + This is also a prerequisite for XIP of binaries stored on the filesystem. + + The location of the cramfs image in memory is board dependent. Therefore, + if you say Y, you must know the proper physical address where to store + the cramfs image and specify it using the physaddr=0x******** mount + option (for example: "mount -t cramfs -o physaddr=0x100000 none /mnt"). + + If unsure, say N. + +Support XIP on linear cramfs +CONFIG_CRAMFS_LINEAR_XIP + You must say Y to this option if you want to be able to run applications + directly from non-volatile memory. XIP applications are marked by + setting the sticky bit (ie, "chmod +t "). A cramfs file system + then needs to be created using mkcramfs (with XIP cramfs support + in it). Applications marked for XIP execution will not be compressed + since they have to run directly from flash. + +Root file system on linear cramfs +CONFIG_ROOT_CRAMFS_LINEAR + Say Y if you have enabled linear cramfs, and you want to be able to use + the linear cramfs image as a root file system. To actually have the + kernel mount this cramfs image as a root file system, you must also pass + the command line parameter "root=/dev/null rootflags=physaddr=0x********" + to the kernel (replace 0x******** with the physical address location + of the linear cramfs image to boot with). + CMS file system support CONFIG_CMS_FS Read only support for CMS minidisk file systems found on IBM --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/Documentation/arm/XScale/PXA/USB-client 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,38 @@ +Date: Wed, 05 Jun 2002 13:38:53 -0700 +From: Frank Becker +To: Nicolas Pitre +Subject: [PATCH] PXA-USB + +Hi Nicolas, + +one more patch... + +This patch adds minimal USB client (UDC) support. + +Some notes: +It adds just enough to get usb-eth working. I.e. +endpoints 0-2, no dma. Performance isn't stellar +partially due to UDC bug workarounds... +(~350K @ 100Mhz, ~550K @ 200Mhz). + +Endpoint 1&2 have changed direction compared to +the SA, so the host side requires a change to +usbnet.c to flip endpoints (in:2/out:1 -> in:1/out:2). + +usb-eth and usb-char for PXA are almost identical +to the SA versions, so they could probably be merged at +one point. I made some minor changes to the eth driver +to grab the usb resources at open, rather than at init +and allow eth&char to be loaded at the same time. + +Stuart Lynne was working on his own USB client driver +(and he was getting higher throughput than my driver). +Assuming you guys have something in the oven for USB +as well, there should be good selection for best of +breed :) + +Cheers, +Frank. +-- +Frank Becker - Intrinsyc Software, Inc. - http://www.intrinsyc.com/ +Need a break? http://criticalmass.sf.net/ --- linux-2.4.25/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -1,11 +1,13 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 25 -EXTRAVERSION =-vrs2 +EXTRAVERSION =-vrs2-pxa1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +ARCH := arm + KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -19,7 +21,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE = arm-linux- # # Include the make variables (CC, etc...) @@ -168,6 +170,7 @@ DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o +DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmcdrivers.o DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o --- linux-2.4.25/arch/arm/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/arch/arm/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -13,10 +13,11 @@ CFLAGS +=-Uarm -fno-common -pipe ifeq ($(CONFIG_FRAME_POINTER),y) -CFLAGS :=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog) +CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) +CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog endif -CFLAGS :=$(CFLAGS:-O2=-Os) +#CFLAGS :=$(CFLAGS:-O2=-Os) ifeq ($(CONFIG_DEBUG_INFO),y) CFLAGS +=-g @@ -38,6 +39,8 @@ arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5 +#arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -mcpu=xscale +arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mcpu=xscale # This selects how we optimise for the processor. tune-y := @@ -49,6 +52,8 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 +tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale +#tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm @@ -127,6 +132,10 @@ MACHINE = sa1100 endif +ifeq ($(CONFIG_ARCH_PXA),y) +MACHINE = pxa +endif + ifeq ($(CONFIG_ARCH_L7200),y) MACHINE = l7200 endif @@ -164,6 +173,17 @@ MACHINE = omaha endif +ifeq ($(CONFIG_XIP_KERNEL),y) + DATAADDR := $(TEXTADDR) + # Replace phys addr with virt addr while keeping offset from base. + # Virt base addr also defined in include/asm-arm/arch-*/hardware.h + TEXTADDR = $(shell echo 0x`echo $(CONFIG_XIP_PHYS_ADDR)|sed -e's/^0x//'` |\ + awk --non-decimal-data '/[:xdigit:]/ \ + {printf("0x%x\n",and($$0,0x001fffff)+0xe8000000)}' ) + LDSCRIPT = arch/arm/vmlinux-armv-xip.lds.in + export DATAADDR +endif + export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS # Only set INCDIR if its not already defined above @@ -269,7 +289,7 @@ arch/arm/kernel arch/arm/mm arch/arm/lib: dummy $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@) -bzImage zImage zinstall Image bootpImage install: vmlinux +bzImage zImage zinstall Image xipImage bootpImage install: vmlinux @$(MAKEBOOT) $@ CLEAN_FILES += \ --- linux-2.4.25/arch/arm/boot/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200 +++ linux-2.4.25/arch/arm/boot/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -113,6 +113,10 @@ endif endif +ifeq ($(CONFIG_ARCH_PXA),y) +ZRELADDR = 0xa0008000 +endif + ifeq ($(CONFIG_ARCH_ANAKIN),y) ZRELADDR = 0x20008000 endif @@ -140,6 +144,14 @@ zImage: compressed/vmlinux $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ +ifeq ($(CONFIG_XIP_KERNEL),y) +xipImage: $(CONFIGURE) $(SYSTEM) + $(OBJCOPY) -S -O binary -R .data $(SYSTEM) vmlinux-text.bin + $(OBJCOPY) -S -O binary -R .init -R .text -R __ex_table -R __ksymtab $(SYSTEM) vmlinux-data.bin + cat vmlinux-text.bin vmlinux-data.bin > $@ + $(RM) -f vmlinux-text.bin vmlinux-data.bin +endif + bootpImage: bootp/bootp $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ @@ -160,7 +172,7 @@ sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" clean: - $(RM) Image zImage bootpImage + $(RM) Image xipImage zImage bootpImage @$(MAKE) -C compressed clean @$(MAKE) -C bootp clean --- linux-2.4.25/arch/arm/boot/compressed/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200 +++ linux-2.4.25/arch/arm/boot/compressed/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -71,6 +71,10 @@ OBJS += head-sa1100.o endif +ifeq ($(CONFIG_CPU_XSCALE),y) +OBJS += head-xscale.o +endif + SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/boot/compressed/head-xscale.S 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,50 @@ +/* + * linux/arch/arm/boot/compressed/head-xscale.S + * + * XScale specific tweaks. This is merged into head.S by the linker. + * + */ + +#include +#include +#include + + .section ".start", #alloc, #execinstr + +__XScale_start: + + @ Preserve r8/r7 i.e. kernel entry values + + @ Data cache might be active. + @ Be sure to flush kernel binary out of the cache, + @ whatever state it is, before it is turned off. + @ This is done by fetching through currently executed + @ memory to be sure we hit the same cache. + bic r2, pc, #0x1f + add r3, r2, #0x10000 @ 64 kb is quite enough... +1: ldr r0, [r2], #32 + teq r2, r3 + bne 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches + + @ disabling MMU and caches + mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #0x05 @ clear DC, MMU + bic r0, r0, #0x1000 @ clear Icache + mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_ARCH_LUBBOCK + mov r7, #MACH_TYPE_LUBBOCK +#endif + +#ifdef CONFIG_ARCH_PXA_IDP + mov r7, #MACH_TYPE_PXA_IDP +#endif + +#ifdef CONFIG_ARCH_TRIZEPS2 + mov r7, #(MACH_TYPE_TRIZEPS2 & 0xFF00) + add r7, r7, #(MACH_TYPE_TRIZEPS2 & 0xFF) +#endif + + --- linux-2.4.25/arch/arm/boot/compressed/head.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/arch/arm/boot/compressed/head.S 2004-03-31 17:15:11.000000000 +0200 @@ -351,7 +351,11 @@ orr r1, r1, #3 << 10 add r2, r3, #16384 1: cmp r1, r8 @ if virt > start of RAM +#ifdef CONFIG_XSCALE_CACHE_ERRATA + orrhs r1, r1, #0x08 @ set cacheable, not bufferable +#else orrhs r1, r1, #0x0c @ set cacheable, bufferable +#endif cmp r1, r9 @ if virt > end of RAM bichs r1, r1, #0x0c @ clear cacheable, bufferable str r1, [r0], #4 @ 1:1 mapping @@ -364,7 +368,11 @@ * so there is no map overlap problem for up to 1 MB compressed kernel. * If the execution is in RAM then we would only be duplicating the above. */ +#ifdef CONFIG_XSCALE_CACHE_ERRATA + mov r1, #0x1a +#else mov r1, #0x1e +#endif orr r1, r1, #3 << 10 mov r2, pc, lsr #20 orr r1, r1, r2, lsl #20 --- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/arch/arm/config.in 2004-03-31 17:15:11.000000000 +0200 @@ -38,6 +38,7 @@ Cirrus-CL-PS7500FE CONFIG_ARCH_CLPS7500 \ CLPS711x/EP721x-based CONFIG_ARCH_CLPS711X \ Co-EBSA285 CONFIG_ARCH_CO285 \ + PXA250/210-based CONFIG_ARCH_PXA \ EBSA-110 CONFIG_ARCH_EBSA110 \ Excalibur-ARM CONFIG_ARCH_CAMELOT \ FootBridge CONFIG_ARCH_FOOTBRIDGE \ @@ -148,6 +149,47 @@ endmenu mainmenu_option next_comment +comment 'Intel PXA250/210 Implementations' +dep_bool ' Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA +dep_bool ' Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA +dep_bool ' Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA +dep_bool ' Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA + +if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then + define_bool CONFIG_PXA_CERF y + + choice 'CerfBoard Style' \ + "PDA CONFIG_PXA_CERF_PDA \ + BOARD CONFIG_PXA_CERF_BOARD" PDA + + choice 'CerfBoard RAM Available' \ + "128MB CONFIG_PXA_CERF_RAM_128MB \ + 64MB CONFIG_PXA_CERF_RAM_64MB \ + 32MB CONFIG_PXA_CERF_RAM_32MB \ + 16MB CONFIG_PXA_CERF_RAM_16MB" 64MB + + choice 'CerfBoard Flash Available' \ + "64MB CONFIG_PXA_CERF_FLASH_64MB \ + 32MB CONFIG_PXA_CERF_FLASH_32MB \ + 16MB CONFIG_PXA_CERF_FLASH_16MB \ + 8MB CONFIG_PXA_CERF_FLASH_8MB" 32MB +fi + +if [ "$CONFIG_ARCH_LUBBOCK" = "y" ]; then + define_bool CONFIG_SA1111 y +fi + +if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then + define_bool CONFIG_TRIZEPS2 y +fi + +dep_tristate 'PXA USB function support' CONFIG_PXA_USB $CONFIG_ARCH_PXA +dep_tristate ' Support for PXA USB network link function' CONFIG_PXA_USB_NETLINK $CONFIG_PXA_USB +dep_tristate ' Support for PXA USB character device emulation' CONFIG_PXA_USB_CHAR $CONFIG_PXA_USB + +endmenu + +mainmenu_option next_comment comment 'CLPS711X/EP721X Implementations' dep_bool ' AUTCPU12' CONFIG_ARCH_AUTCPU12 $CONFIG_ARCH_CLPS711X dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X @@ -385,6 +427,12 @@ define_bool CONFIG_CPU_SA1100 n fi +if [ "$CONFIG_ARCH_PXA" = "y" ]; then + define_bool CONFIG_CPU_32v5 y + define_bool CONFIG_CPU_XSCALE y + bool 'Workaround for XScale cache errata (see help)' CONFIG_XSCALE_CACHE_ERRATA +fi + # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. @@ -493,6 +541,7 @@ hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0 if [ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PXA" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL fi @@ -501,8 +550,10 @@ bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG if [ "$CONFIG_HOTPLUG" = "y" ]; then source drivers/pcmcia/Config.in + source drivers/mmc/Config.in else define_bool CONFIG_PCMCIA n + define_bool CONFIG_MMC n fi if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; then if [ "$CONFIG_PCMCIA" != "n" ]; then @@ -513,6 +564,14 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL + +if [ "$CONFIG_ARCH_PXA" = "y" ]; then + dep_bool 'Kernel Execute-In-Place from ROM (EXPERIMENTAL)' CONFIG_XIP_KERNEL $CONFIG_EXPERIMENTAL + if [ "$CONFIG_XIP_KERNEL" = "y" ]; then + hex ' Kernel .text physical address' CONFIG_XIP_PHYS_ADDR 0 + fi +fi + comment 'At least one math emulation must be selected' tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE if [ "$CONFIG_FPE_NWFPE" != "n" ]; then @@ -538,6 +597,9 @@ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_LUBBOCK" = "y" -o \ + "$CONFIG_ARCH_PXA_IDP" = "y" -o \ + "$CONFIG_ARCH_PXA_CERF" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" -o \ "$CONFIG_ARCH_P720T" = "y" -o \ @@ -549,8 +611,12 @@ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_LUBBOCK" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_P720T" = "y" -o \ + "$CONFIG_ARCH_LUBBOCK" = "y" -o \ + "$CONFIG_ARCH_PXA_CERF" = "y" -o \ + "$CONFIG_ARCH_PXA_IDP" = "y" -o \ "$CONFIG_ARCH_OMAHA" = "y" ]; then bool ' Timer LED' CONFIG_LEDS_TIMER bool ' CPU usage LED' CONFIG_LEDS_CPU @@ -684,6 +750,7 @@ if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PXA" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ "$CONFIG_ARCH_TBOX" = "y" -o \ "$CONFIG_ARCH_CLPS7500" = "y" -o \ @@ -705,6 +772,7 @@ "$CONFIG_ARCH_TBOX" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_PXA" = "y" -o \ "$CONFIG_PCI" = "y" ]; then mainmenu_option next_comment comment 'Sound' --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/cerfboard_pxa 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,857 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_ARCH_PXA_CERF=y +CONFIG_PXA_CERF=y +# CONFIG_PXA_CERF_PDA is not set +CONFIG_PXA_CERF_BOARD=y +# CONFIG_PXA_CERF_RAM_128MB is not set +CONFIG_PXA_CERF_RAM_64MB=y +# CONFIG_PXA_CERF_RAM_32MB is not set +# CONFIG_PXA_CERF_RAM_16MB is not set +# CONFIG_PXA_CERF_FLASH_64MB is not set +CONFIG_PXA_CERF_FLASH_32MB=y +# CONFIG_PXA_CERF_FLASH_16MB is not set +# CONFIG_PXA_CERF_FLASH_8MB is not set +CONFIG_PXA_USB=y +CONFIG_PXA_USB_NETLINK=y +CONFIG_PXA_USB_CHAR=m + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +CONFIG_XSCALE_CACHE_ERRATA=y +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CPU_FREQ=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc" +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +# CONFIG_MTD_CFI_B2 is not set +CONFIG_MTD_CFI_B4=y +# CONFIG_MTD_CFI_B8 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_LUBBOCK is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +CONFIG_MTD_PXA_CERF=y +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_AIRONET4500_CS=m + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_PXA_ALGO=y +CONFIG_I2C_PXA_ADAP=y +# CONFIG_I2C_CHARDEV is not set +# CONFIG_I2C_PROC is not set +# CONFIG_I2C_DS1307 is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_21285_WATCHDOG is not set +# CONFIG_977_WATCHDOG is not set +# CONFIG_SA1100_WATCHDOG is not set +CONFIG_PXA_WATCHDOG=m +# CONFIG_OMAHA_WATCHDOG is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_PXA_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=y +CONFIG_PCMCIA_CHRDEV=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=y +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +CONFIG_NLS_CODEPAGE_863=m +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +# CONFIG_MCP_UCB1400_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/cerfpda_pxa 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,962 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_ARCH_PXA_CERF=y +CONFIG_PXA_CERF=y +CONFIG_PXA_CERF_PDA=y +# CONFIG_PXA_CERF_BOARD is not set +# CONFIG_PXA_CERF_RAM_128MB is not set +CONFIG_PXA_CERF_RAM_64MB=y +# CONFIG_PXA_CERF_RAM_32MB is not set +# CONFIG_PXA_CERF_RAM_16MB is not set +# CONFIG_PXA_CERF_FLASH_64MB is not set +CONFIG_PXA_CERF_FLASH_32MB=y +# CONFIG_PXA_CERF_FLASH_16MB is not set +# CONFIG_PXA_CERF_FLASH_8MB is not set +CONFIG_PXA_USB=y +CONFIG_PXA_USB_NETLINK=y +CONFIG_PXA_USB_CHAR=y + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +# CONFIG_XSCALE_CACHE_ERRATA is not set +# CONFIG_ARM_THUMB is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc" +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +# CONFIG_MTD_CFI_B2 is not set +CONFIG_MTD_CFI_B4=y +# CONFIG_MTD_CFI_B8 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_LUBBOCK is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +CONFIG_MTD_PXA_CERF=y +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_LOOP=m +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE 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 +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=y +CONFIG_IRLAN=y +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +CONFIG_IRDA_ULTRA=y +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +CONFIG_IRDA_DEBUG=y + +# +# Infrared-port device drivers +# +CONFIG_IRTTY_SIR=y +# CONFIG_IRPORT_SIR is not set +# CONFIG_DONGLE is not set +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +CONFIG_INPUT=y +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=y +CONFIG_PCMCIA_CHRDEV=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=m +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=y +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +CONFIG_NLS_CODEPAGE_863=m +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_SA1100 is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_8BPP is not set +CONFIG_FB_PXA_16BPP=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +CONFIG_SOUND_PXA_AC97=y +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +CONFIG_MCP_UCB1400_TS=y + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +# CONFIG_USB_OHCI is not set +# CONFIG_USB_OHCI_SA1111 is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_RIO500 is not set + +# +# Bluetooth support +# +CONFIG_BLUEZ=y +CONFIG_BLUEZ_L2CAP=y + +# +# Bluetooth device drivers +# +# CONFIG_BLUEZ_HCIUSB is not set +CONFIG_BLUEZ_HCIUART=y +CONFIG_BLUEZ_HCIVHCI=y + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/csb226 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,615 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_HACKKIT is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Board +# +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_ARCH_INNOKOM is not set +CONFIG_ARCH_CSB226=y +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_CERF is not set +# CONFIG_PXA_USB is not set +# CONFIG_PXA_USB_NETLINK is not set +# CONFIG_PXA_USB_CHAR is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +CONFIG_XSCALE_CACHE_ERRATA=y +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_CPU_FREQ is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +# CONFIG_MMC is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_XIP_KERNEL is not set +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="console=ttyS0,19200" +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARM_HWTIMER=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +CONFIG_ARM_CIRRUS=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE 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 +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_PXA_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_EXT2_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +# CONFIG_MCP_UCB1400_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SLAB=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_WAITQ=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/innokom 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,699 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200DK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_HACKKIT is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Board +# +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_ARCH_INNOKOM=y +# CONFIG_ARCH_CSB226 is not set +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_CERF is not set +# CONFIG_PXA_USB is not set +# CONFIG_PXA_USB_NETLINK is not set +# CONFIG_PXA_USB_CHAR is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +CONFIG_XSCALE_CACHE_ERRATA=y +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_CPU_FREQ is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +# CONFIG_MMC is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_XIP_KERNEL is not set +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=/dev/nfs mem=32M ip=dhcp console=ttyS0,19200" +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARM_HWTIMER=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_LUBBOCK is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_FORTUNET is not set +CONFIG_MTD_INNOKOM=y +CONFIG_MTD_INNOKOM_16MB=y +# CONFIG_MTD_INNOKOM_64MB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_CEIVA is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91X=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_PXA_ALGO=y +CONFIG_I2C_PXA_ADAP=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y +# CONFIG_I2C_DS1307 is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_PXA_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_EXT2_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +# CONFIG_MCP_UCB1400_TS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SLAB=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_WAITQ=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/lubbock 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,971 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_AT91RM9200 is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSAGC is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_ADSBITSYPLUS is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_H3600_SLEEVE is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_HACKKIT is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_SA1100_SSP is not set + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set + +# +# Intel PXA250/210 Implementations +# +CONFIG_ARCH_LUBBOCK=y +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_ARCH_PXA_CERF is not set +# CONFIG_ARCH_TRIZEPS2 is not set +CONFIG_SA1111=y +# CONFIG_PXA_USB is not set +# CONFIG_PXA_USB_NETLINK is not set +# CONFIG_PXA_USB_CHAR is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_GUIDEA07 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +# CONFIG_XSCALE_CACHE_ERRATA is not set +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set + +# +# Processor Features +# +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CPU_FREQ=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y + +# +# MMC device drivers +# +CONFIG_MMC=m +CONFIG_MMC_PXA=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_PARTITIONS=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_XIP_KERNEL is not set + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PM=y +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=32M" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +CONFIG_MTD_CFI_B2=y +CONFIG_MTD_CFI_B4=y +# CONFIG_MTD_CFI_B8 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_LUBBOCK=y +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_EPXA is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_CEIVA is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_STATS is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91X=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_BLK_DEV_ATARAID_SII is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +CONFIG_INPUT=y +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_MX1TS is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_AT91 is not set +# CONFIG_SERIAL_AT91_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set + +# +# Other L3 adapters +# +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +CONFIG_BUSMOUSE=y +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_LOGIBUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set + +# +# Joysticks +# +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_IPMI_PANIC_EVENT is not set +# CONFIG_IPMI_DEVICE_INTERFACE is not set +# CONFIG_IPMI_KCS is not set +# CONFIG_IPMI_WATCHDOG is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_SCx200_GPIO is not set +# CONFIG_AMD_PM768 is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_PXA_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_CRAMFS is not set +# CONFIG_CRAMFS_LINEAR is not set +# CONFIG_CRAMFS_LINEAR_XIP is not set +# CONFIG_ROOT_CRAMFS_LINEAR is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_DBMX1 is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_8BPP is not set +CONFIG_FB_PXA_16BPP=y +# CONFIG_FB_PXA_QVGA is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_ALI5455 is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +CONFIG_SOUND_PXA_AC97=y +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +CONFIG_MCP_UCB1400_TS=y + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/pxa_idp 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,933 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +CONFIG_ARCH_PXA_IDP=y +# CONFIG_ARCH_PXA_CERF is not set +CONFIG_PXA_USB=m +CONFIG_PXA_USB_NETLINK=m +CONFIG_PXA_USB_CHAR=m + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +# CONFIG_XSCALE_CACHE_ERRATA is not set +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PM=y +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=/dev/mtdblock2 init=/linuxrc console=ttyS0,115200" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +# CONFIG_MTD_CFI_B2 is not set +CONFIG_MTD_CFI_B4=y +# CONFIG_MTD_CFI_B8 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_LUBBOCK=y +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_PXA_CERF is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +CONFIG_ASI_MTD0_SIZE=40000 +CONFIG_ASI_MTD1_SIZE=100000 +CONFIG_ASI_MTD2_SIZE=1e00000 +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +# CONFIG_SMC9194 is not set +CONFIG_SMC91111=m +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +CONFIG_NET_POCKET=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +CONFIG_WAVELAN=m +# CONFIG_ARLAN is not set +CONFIG_AIRONET4500=y +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +CONFIG_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_AIRO_CS=m +CONFIG_NET_WIRELESS=y + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_AXNET is not set +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_AIRONET4500_CS=m + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=m +CONFIG_IRLAN=m +# CONFIG_IRNET is not set +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +CONFIG_IRDA_DEBUG=y + +# +# Infrared-port device drivers +# +CONFIG_IRTTY_SIR=m +# CONFIG_IRPORT_SIR is not set +# CONFIG_DONGLE is not set +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set +CONFIG_PXA_FIR=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +CONFIG_INPUT=y +CONFIG_INPUT_KEYBDEV=m +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +# CONFIG_IDP_KEYB is not set +CONFIG_MATRIX_KEYBOARD=y +# CONFIG_SA1111_PS2_KEYB is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +CONFIG_BUSMOUSE=y +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_LOGIBUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_INPUT_NS558 is not set +# CONFIG_INPUT_LIGHTNING is not set +# CONFIG_INPUT_PCIGAME is not set +# CONFIG_INPUT_CS461X is not set +# CONFIG_INPUT_EMU10K1 is not set +# CONFIG_INPUT_SERIO is not set +# CONFIG_INPUT_SERPORT is not set +# CONFIG_INPUT_ANALOG is not set +# CONFIG_INPUT_A3D is not set +# CONFIG_INPUT_ADI is not set +# CONFIG_INPUT_COBRA is not set +# CONFIG_INPUT_GF2K is not set +# CONFIG_INPUT_GRIP is not set +# CONFIG_INPUT_INTERACT is not set +# CONFIG_INPUT_TMDC is not set +# CONFIG_INPUT_SIDEWINDER is not set +# CONFIG_INPUT_IFORCE_USB is not set +# CONFIG_INPUT_IFORCE_232 is not set +# CONFIG_INPUT_WARRIOR is not set +# CONFIG_INPUT_MAGELLAN is not set +# CONFIG_INPUT_SPACEORB is not set +# CONFIG_INPUT_SPACEBALL is not set +# CONFIG_INPUT_STINGER is not set +# CONFIG_INPUT_DB9 is not set +# CONFIG_INPUT_GAMECON is not set +# CONFIG_INPUT_TURBOGRAFX is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_PXA_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +CONFIG_PCMCIA_SERIAL_CS=m + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EXT3_FS=m +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_CRAMFS=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +CONFIG_ZLIB_FS_INFLATE=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_SA1100 is not set +CONFIG_FB_PXA=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +CONFIG_SOUND_PXA_AC97=y +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP is not set +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +CONFIG_MCP_UCB1400_TS=m + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SLAB=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/def-configs/trizeps2 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,873 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +# CONFIG_GENERIC_BUST_SPINLOCK is not set +# CONFIG_GENERIC_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ANAKIN is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_OMAHA is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_MX1ADS is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_RISCSTATION is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set + +# +# Archimedes/A5000 Implementations +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set + +# +# Footbridge Implementations +# +# CONFIG_ARCH_CATS is not set +# CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +# CONFIG_ARCH_EBSA285_HOST is not set +# CONFIG_ARCH_NETWINDER is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ACCELENT is not set +# CONFIG_SA1100_ASSABET is not set +# CONFIG_ASSABET_NEPONSET is not set +# CONFIG_SA1100_ADSBITSY is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CEP is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_H3XXX is not set +# CONFIG_SA1100_EXTENEX1 is not set +# CONFIG_SA1100_FLEXANET is not set +# CONFIG_SA1100_FREEBIRD is not set +# CONFIG_SA1100_FRODO is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HUW_WEBPANEL is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_OMNIMETER is not set +# CONFIG_SA1100_PANGOLIN is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SIMPUTER is not set +# CONFIG_SA1100_PFS168 is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_USB is not set +# CONFIG_SA1100_USB_NETLINK is not set +# CONFIG_SA1100_USB_CHAR is not set +# CONFIG_H3600_SLEEVE is not set + +# +# Intel PXA250/210 Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_ARCH_PXA_CERF is not set +CONFIG_ARCH_TRIZEPS2=y +CONFIG_TRIZEPS2=y +CONFIG_PXA_USB=y +# CONFIG_PXA_USB_NETLINK is not set +# CONFIG_PXA_USB_CHAR is not set + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_AUTCPU12 is not set +# CONFIG_ARCH_CDB89712 is not set +# CONFIG_ARCH_CLEP7312 is not set +# CONFIG_ARCH_EDB7211 is not set +# CONFIG_ARCH_P720T is not set +# CONFIG_ARCH_FORTUNET is not set +# CONFIG_ARCH_EP7211 is not set +# CONFIG_ARCH_EP7212 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM610 is not set +# CONFIG_CPU_ARM710 is not set +# CONFIG_CPU_ARM720T is not set +# CONFIG_CPU_ARM920T is not set +# CONFIG_CPU_ARM922T is not set +# CONFIG_PLD is not set +# CONFIG_CPU_ARM926T is not set +# CONFIG_CPU_ARM1020 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_SA110 is not set +# CONFIG_CPU_SA1100 is not set +CONFIG_CPU_32v5=y +CONFIG_CPU_XSCALE=y +# CONFIG_XSCALE_CACHE_ERRATA is not set +# CONFIG_CPU_32v3 is not set +# CONFIG_CPU_32v4 is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_FASTFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=/dev/mtdblock3 rw console=ttyS0,38400 mem=32M noinitrd init=/linuxrc" +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_LUBBOCK is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_CDB89712 is not set +# CONFIG_MTD_SA1100 is not set +# CONFIG_MTD_DC21285 is not set +# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_FORTUNET is not set +# CONFIG_MTD_PXA_CERF is not set +# CONFIG_MTD_EPXA10DB is not set +# CONFIG_MTD_AUTCPU12 is not set +# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +CONFIG_MTD_TRIZEPS2=y +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# 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_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_ARM_CIRRUS is not set +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRAMCA is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +CONFIG_SMC9194=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set +# CONFIG_ARLAN is not set +# CONFIG_AIRONET4500 is not set +# CONFIG_AIRONET4500_NONCS is not set +# CONFIG_AIRONET4500_PROC is not set +# CONFIG_HERMES is not set +# CONFIG_PCMCIA_HERMES is not set +CONFIG_AIRO_CS=m +CONFIG_NET_WIRELESS=y + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +CONFIG_PCMCIA_3C574=m +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +CONFIG_NET_PCMCIA_RADIO=y +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_PCMCIA_NETWAVE is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_AIRONET4500_CS is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=m + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=m +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_CONSOLE is not set +# CONFIG_SERIAL_CLPS711X is not set +# CONFIG_SERIAL_CLPS711X_CONSOLE is not set +# CONFIG_SERIAL_21285 is not set +# CONFIG_SERIAL_21285_OLD is not set +# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_UART00 is not set +# CONFIG_SERIAL_UART00_CONSOLE is not set +# CONFIG_SERIAL_SA1100 is not set +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_OMAHA is not set +# CONFIG_SERIAL_OMAHA_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_PXA_ALGO=y +CONFIG_I2C_PXA_ADAP=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y +# CONFIG_I2C_DS1307 is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set +# CONFIG_L3_ALGOBIT is not set +# CONFIG_L3_BIT_SA1100_GPIO is not set +# CONFIG_L3_SA1111 is not set +# CONFIG_BIT_SA1100_GPIO is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_PXA_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +CONFIG_TRIZEPS2_TTLIO=m + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EXT3_FS=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=m +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYMAP=y +# CONFIG_VGA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_ACORN is not set +# CONFIG_FB_ANAKIN is not set +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_SA1100 is not set +CONFIG_FB_PXA=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +# CONFIG_FBCON_CFB8 is not set +CONFIG_FBCON_CFB16=y +# CONFIG_FBCON_CFB24 is not set +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_WAVEARTIST is not set +CONFIG_SOUND_PXA_AC97=y +# CONFIG_SOUND_TVMIXER is not set + +# +# Multimedia Capabilities Port drivers +# +CONFIG_MCP=y +# CONFIG_MCP_SA1100 is not set +# CONFIG_MCP_UCB1200 is not set +# CONFIG_MCP_UCB1200_AUDIO is not set +# CONFIG_MCP_UCB1200_TS is not set +CONFIG_MCP_UCB1400_TS=y +CONFIG_MCP_UCB1X00_TS_COMPAT=y + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_NO_PGT_CACHE is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set --- linux-2.4.25/arch/arm/kernel/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200 +++ linux-2.4.25/arch/arm/kernel/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -10,7 +10,7 @@ HEAD_OBJ = head-$(PROCESSOR).o ENTRY_OBJ = entry-$(PROCESSOR).o -AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) +AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) # This is depreciated. @@ -45,7 +45,7 @@ $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \ $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \ $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \ - $(CONFIG_ARCH_AT91RM9200) + $(CONFIG_ARCH_AT91RM9200) $(CONFIG_ARCH_PXA) ifneq ($(findstring y,$(no-irq-arch)),y) obj-y += irq-arch.o --- linux-2.4.25/arch/arm/kernel/debug-armv.S~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200 +++ linux-2.4.25/arch/arm/kernel/debug-armv.S 2004-03-31 17:15:11.000000000 +0200 @@ -221,6 +221,31 @@ bne 1001b .endm +#elif defined(CONFIG_ARCH_PXA) + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x40000000 @ physical + movne \rx, #io_p2v(0x40000000) @ virtual + orr \rx, \rx, #0x00100000 @ FFUART + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0] + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #0x14] + tst \rd, #(1 << 6) + beq 1002b + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x14] + tst \rd, #(1 << 5) + beq 1001b + .endm #elif defined(CONFIG_ARCH_CLPS7500) .macro addruart,rx mov \rx, #0xe0000000 --- linux-2.4.25/arch/arm/kernel/entry-armv.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/arch/arm/kernel/entry-armv.S 2004-03-31 17:15:11.000000000 +0200 @@ -615,6 +615,27 @@ .text .endm +#elif CONFIG_ARCH_PXA + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000 + add \base, \base, #0x00d00000 + ldr \irqstat, [\base, #0] @ ICIP + ldr \irqnr, [\base, #4] @ ICMR + ands \irqstat, \irqstat, \irqnr + beq 1001f + rsb \irqnr, \irqstat, #0 + and \irqstat, \irqstat, \irqnr + clz \irqnr, \irqstat + rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP) +1001: + .endm + + .macro irq_prio_table + .endm #else #error Unknown architecture #endif @@ -891,9 +912,17 @@ stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack mrs ip, cpsr str ip, [sp, #-4]! @ Save cpsr_SVC +#ifdef CONFIG_CPU_XSCALE + mra r4, r5, acc0 + stmfd sp!, {r4, r5} +#endif str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC ldr r2, [r1, #TSS_DOMAIN] +#ifdef CONFIG_CPU_XSCALE + ldmfd sp!, {r4, r5} + mar acc0, r4, r5 +#endif ldr ip, [sp], #4 mcr p15, 0, r2, c3, c0 @ Set domain register msr spsr, ip @ Save tasks CPSR into SPSR for this return --- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200 +++ linux-2.4.25/arch/arm/kernel/head-armv.S 2004-03-31 17:15:11.000000000 +0200 @@ -30,6 +30,7 @@ * * swapper_pg_dir, pgtbl and krnladr are all closely related. */ +#ifndef CONFIG_XIP_KERNEL #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 #endif @@ -41,6 +42,26 @@ adr \reg, stext sub \reg, \reg, #0x4000 .endm +#else +#if (DATAADDR & 0xffff) != 0x8000 +#error DATAADDR must start at 0xXXXX8000 +#endif + +#define PAGE_OFFSET 0xc0000000 +#ifdef CONFIG_ARCH_LUBBOCK +#define PHYS_OFFSET 0xa0000000 +#elif CONFIG_ARCH_OMAP +#define PHYS_OFFSET 0x10000000 +#endif + + .globl SYMBOL_NAME(swapper_pg_dir) + .equ SYMBOL_NAME(swapper_pg_dir), DATAADDR - 0x4000 + + .macro pgtbl, reg, rambase + ldr \reg, PGTBL + add \reg, \reg, #PHYS_OFFSET - PAGE_OFFSET + .endm +#endif /* * Since the page table is closely related to the kernel start address, we @@ -131,6 +152,32 @@ mov r1, #MACH_TYPE_L7200 #endif +#ifdef CONFIG_XIP_KERNEL + +#if defined(CONFIG_ARCH_LUBBOCK) + mov r1, #MACH_TYPE_LUBBOCK +#endif + + @ Data cache might be active. + @ Be sure to flush kernel binary out of the cache, + @ whatever state it is, before it is turned off. + @ This is done by fetching through currently executed + @ memory to be sure we hit the same cache. + bic r2, pc, #0x1f + add r3, r2, #0x10000 @ 64 kb is quite enough... +1: ldr r0, [r2], #32 + teq r2, r3 + bne 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches + + @ disabling MMU and caches + mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #0x05 @ clear DC, MMU + bic r0, r0, #0x1000 @ clear Icache + mcr p15, 0, r0, c1, c0, 0 +#endif + mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode msr cpsr_c, r0 @ and all irqs disabled bl __lookup_processor_type @@ -179,6 +226,17 @@ */ .align 5 __mmap_switched: +#ifdef CONFIG_XIP_KERNEL + ldr r3, ETEXT @ data section copy + ldr r4, SDATA + ldr r5, EDATA +1: + ldr r6, [r3], #4 + str r6, [r4], #4 + cmp r4, r5 + blo 1b +#endif + adr r3, __switch_data + 4 ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat @ sp = stack pointer @@ -233,6 +291,8 @@ teq r0, r2 bne 1b +#ifndef CONFIG_XIP_KERNEL + /* * Create identity mapping for first MB of kernel to * cater for the MMU enable. This identity mapping @@ -271,6 +331,43 @@ add r3, r8, r2 @ flags + rambase str r3, [r0] +#else /* CONFIG_XIP_KERNEL */ + + mov r3, pc, lsr #20 + mov r3, r3, lsl #20 @ phys kernel start + + add r0, r4, r3, lsr #18 + orr r3, r3, r8 + str r3, [r0] + + mov r0, #TEXTADDR & 0xff000000 + add r0, r0, #TEXTADDR & 0x00f00000 @ virt kernel start + add r0, r4, r0, lsr #18 + add r2, r3, #4 << 20 @ kernel + 4MB + +1: + str r3, [r0], #4 + add r3, r3, #1 << 20 + cmp r3, r2 + bne 1b + + bic r3, r4, #0x000ff000 @ ram start + add r0, r4, r3, lsr #18 + orr r3, r3, r8 + str r3, [r0], #4 + + add r0, r3, #PAGE_OFFSET - PHYS_OFFSET + add r0, r4, r0, lsr #18 + add r2, r3, #4 << 20 @ ram + 4MB + +1: + str r3, [r0], #4 + add r3, r3, #1 << 20 + cmp r3, r2 + bne 1b + +#endif /* CONFIG_XIP_KERNEL */ + bic r8, r8, #0x0c @ turn off cacheable @ and bufferable bits #ifdef CONFIG_DEBUG_LL @@ -433,3 +530,13 @@ mov pc, lr 2: ldmib r4, {r5, r6, r7} @ found, get results mov pc, lr + +#ifdef CONFIG_XIP_KERNEL + +PGTBL: .long SYMBOL_NAME(swapper_pg_dir) + +ETEXT: .long SYMBOL_NAME(_endtext) +SDATA: .long SYMBOL_NAME(_sdata) +EDATA: .long SYMBOL_NAME(__bss_start) + +#endif --- linux-2.4.25/arch/arm/kernel/setup.c~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200 +++ linux-2.4.25/arch/arm/kernel/setup.c 2004-03-31 17:15:11.000000000 +0200 @@ -55,6 +55,10 @@ extern void reboot_setup(char *str); extern int root_mountflags; extern int _stext, _text, _etext, _edata, _end; +#ifdef CONFIG_XIP_KERNEL +extern int _endtext, _sdata; +#endif + unsigned int processor_id; unsigned int __machine_arch_type; @@ -105,6 +109,109 @@ #define lp1 io_res[1] #define lp2 io_res[2] +#ifdef CONFIG_CPU_32 +static const char *cache_types[16] = { + "write-through", + "write-back", + "write-back", + "undefined 3", + "undefined 4", + "undefined 5", + "write-back", + "write-back", + "undefined 8", + "undefined 9", + "undefined 10", + "undefined 11", + "undefined 12", + "undefined 13", + "undefined 14", + "undefined 15", +}; + +static const char *cache_clean[16] = { + "not required", + "read-block", + "cp15 c7 ops", + "undefined 3", + "undefined 4", + "undefined 5", + "cp15 c7 ops", + "cp15 c7 ops", + "undefined 8", + "undefined 9", + "undefined 10", + "undefined 11", + "undefined 12", + "undefined 13", + "undefined 14", + "undefined 15", +}; + +static const char *cache_lockdown[16] = { + "not supported", + "not supported", + "not supported", + "undefined 3", + "undefined 4", + "undefined 5", + "format A", + "format B", + "undefined 8", + "undefined 9", + "undefined 10", + "undefined 11", + "undefined 12", + "undefined 13", + "undefined 14", + "undefined 15", +}; + +#define CACHE_TYPE(x) (((x) >> 25) & 15) +#define CACHE_S(x) ((x) & (1 << 24)) +#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */ +#define CACHE_ISIZE(x) ((x) & 4095) + +#define CACHE_SIZE(y) (((y) >> 6) & 7) +#define CACHE_ASSOC(y) (((y) >> 3) & 7) +#define CACHE_M(y) ((y) & (1 << 2)) +#define CACHE_LINE(y) ((y) & 3) + +static inline void dump_cache(const char *prefix, unsigned int cache) +{ + unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0); + + printk("%s size %dK associativity %d line length %d sets %d\n", + prefix, + mult << (8 + CACHE_SIZE(cache)), + (mult << CACHE_ASSOC(cache)) >> 1, + 8 << CACHE_LINE(cache), + 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) - + CACHE_LINE(cache))); +} + +static inline void dump_cpu_cache_id(void) +{ + unsigned int cache_info; + + asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info)); + + if (cache_info == processor_id) + return; + + printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]); + if (CACHE_S(cache_info)) { + dump_cache("CPU: I cache", CACHE_ISIZE(cache_info)); + dump_cache("CPU: D cache", CACHE_DSIZE(cache_info)); + } else { + dump_cache("CPU: cache", CACHE_ISIZE(cache_info)); + } +} + +#else +#define dump_cpu_cache_id() do { } while (0) +#endif + static void __init setup_processor(void) { extern struct proc_info_list __proc_info_begin, __proc_info_end; @@ -272,7 +379,11 @@ kernel_code.start = __virt_to_phys(init_mm.start_code); kernel_code.end = __virt_to_phys(init_mm.end_code - 1); +#ifndef CONFIG_XIP_KERNEL kernel_data.start = __virt_to_phys(init_mm.end_code); +#else + kernel_data.start = __virt_to_phys(init_mm.start_data); +#endif kernel_data.end = __virt_to_phys(init_mm.brk - 1); for (i = 0; i < mi->nr_banks; i++) { @@ -531,7 +642,12 @@ } init_mm.start_code = (unsigned long) &_text; +#ifndef CONFIG_XIP_KERNEL init_mm.end_code = (unsigned long) &_etext; +#else + init_mm.end_code = (unsigned long) &_endtext; + init_mm.start_data = (unsigned long) &_sdata; +#endif init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; @@ -568,6 +684,41 @@ NULL }; +static const char *proc_arch[16] = { + "undefined 0", + "4", + "4T", + "5", + "5T", + "5TE", + "undefined 6", + "undefined 7", + "undefined 8", + "undefined 9", + "undefined 10", + "undefined 11", + "undefined 12", + "undefined 13", + "undefined 14", + "undefined 15" +}; + +static void +c_show_cache(struct seq_file *m, const char *type, unsigned int cache) +{ + unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0); + + seq_printf(m, "%s size\t\t: %d\n" + "%s assoc\t\t: %d\n" + "%s line length\t: %d\n" + "%s sets\t\t: %d\n", + type, mult << (8 + CACHE_SIZE(cache)), + type, (mult << CACHE_ASSOC(cache)) >> 1, + type, 8 << CACHE_LINE(cache), + type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) - + CACHE_LINE(cache))); +} + static int c_show(struct seq_file *m, void *v) { int i; @@ -586,7 +737,60 @@ if (elf_hwcap & (1 << i)) seq_printf(m, "%s ", hwcap_str[i]); - seq_puts(m, "\n\n"); + seq_puts(m, "\n"); + + if ((processor_id & 0x0000f000) == 0x00000000) { + /* pre-ARM7 */ + seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4); + } else if ((processor_id & 0x0000f000) == 0x00007000) { + /* ARM7 */ + seq_printf(m, "CPU implementor\t: 0x%02x\n" + "CPU architecture: %s\n" + "CPU variant\t: 0x%02x\n" + "CPU part\t: 0x%03x\n", + processor_id >> 24, + processor_id & (1 << 23) ? "4T" : "3", + (processor_id >> 16) & 127, + (processor_id >> 4) & 0xfff); + } else { + /* post-ARM7 */ + seq_printf(m, "CPU implementor\t: 0x%02x\n" + "CPU architecture: %s\n" + "CPU variant\t: 0x%x\n" + "CPU part\t: 0x%03x\n", + processor_id >> 24, + proc_arch[(processor_id >> 16) & 15], + (processor_id >> 20) & 15, + (processor_id >> 4) & 0xfff); + } + seq_printf(m, "CPU revision\t: %d\n", processor_id & 15); + +#ifdef CONFIG_CPU_32 + { + unsigned int cache_info; + + asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info)); + if (cache_info != processor_id) { + seq_printf(m, "Cache type\t: %s\n" + "Cache clean\t: %s\n" + "Cache lockdown\t: %s\n" + "Cache unified\t: %s\n", + cache_types[CACHE_TYPE(cache_info)], + cache_clean[CACHE_TYPE(cache_info)], + cache_lockdown[CACHE_TYPE(cache_info)], + CACHE_S(cache_info) ? "harvard" : "unified"); + + if (CACHE_S(cache_info)) { + c_show_cache(m, "I", CACHE_ISIZE(cache_info)); + c_show_cache(m, "D", CACHE_DSIZE(cache_info)); + } else { + c_show_cache(m, "Cache", CACHE_ISIZE(cache_info)); + } + } + } +#endif + + seq_puts(m, "\n"); seq_printf(m, "Hardware\t: %s\n", machine_name); seq_printf(m, "Revision\t: %04x\n", system_rev); --- linux-2.4.25/arch/arm/lib/copy_page.S~2.4.25-vrs2-pxa1.patch 2001-03-07 04:44:35.000000000 +0100 +++ linux-2.4.25/arch/arm/lib/copy_page.S 2004-03-31 17:15:11.000000000 +0200 @@ -13,6 +13,8 @@ #include #include +#define COPY_COUNT (PAGE_SZ/64 PLD( -1 )) + .text .align 5 /* @@ -23,9 +25,13 @@ */ ENTRY(copy_page) stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 + PLD( pld [r1, #0] ) + PLD( pld [r1, #32] ) + mov r2, #COPY_COUNT @ 1 ldmia r1!, {r3, r4, ip, lr} @ 4+1 -1: stmia r0!, {r3, r4, ip, lr} @ 4 +1: PLD( pld [r1, #64] ) + PLD( pld [r1, #96] ) +2: stmia r0!, {r3, r4, ip, lr} @ 4 ldmia r1!, {r3, r4, ip, lr} @ 4+1 stmia r0!, {r3, r4, ip, lr} @ 4 ldmia r1!, {r3, r4, ip, lr} @ 4+1 @@ -33,6 +39,8 @@ ldmia r1!, {r3, r4, ip, lr} @ 4 subs r2, r2, #1 @ 1 stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 + ldmgtia r1!, {r3, r4, ip, lr} @ 4 + bgt 1b @ 1 + PLD( ldmeqia r1!, {r3, r4, ip, lr} ) + PLD( beq 2b ) LOADREGS(fd, sp!, {r4, pc}) @ 3 --- linux-2.4.25/arch/arm/lib/findbit.S~2.4.25-vrs2-pxa1.patch 2000-09-19 00:15:25.000000000 +0200 +++ linux-2.4.25/arch/arm/lib/findbit.S 2004-03-31 17:15:11.000000000 +0200 @@ -43,7 +43,15 @@ /* * One or more bits in the LSB of r3 are assumed to be set. */ -.found: tst r3, #0x0f +.found: +#if __LINUX_ARM_ARCH__ >= 5 + rsb r1, r3, #0 + and r3, r3, r1 + clz r3, r3 + rsb r3, r3, #31 + add r0, r2, r3 +#else + tst r3, #0x0f addeq r2, r2, #4 movne r3, r3, lsl #4 tst r3, #0x30 @@ -52,5 +60,6 @@ tst r3, #0x40 addeq r2, r2, #1 mov r0, r2 +#endif RETINSTR(mov,pc,lr) --- linux-2.4.25/arch/arm/lib/getuser.S~2.4.25-vrs2-pxa1.patch 2002-08-03 02:39:42.000000000 +0200 +++ linux-2.4.25/arch/arm/lib/getuser.S 2004-03-31 17:15:11.000000000 +0200 @@ -18,7 +18,7 @@ * Inputs: r0 contains the address * Outputs: r0 is the error code * r1, r2 contains the zero-extended value - * lr corrupted + * ip, lr corrupted * * No other registers must be altered. (see include/asm-arm/uaccess.h * for specific ASM register usage). @@ -42,14 +42,14 @@ .global __get_user_2 __get_user_2: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TSK_ADDR_LIMIT] - sub r2, r2, #2 - cmp r0, r2 + bic ip, sp, #0x1f00 + bic ip, ip, #0x00ff + ldr ip, [ip, #TSK_ADDR_LIMIT] + sub ip, ip, #2 + cmp r0, ip 2: ldrlsbt r1, [r0], #1 -3: ldrlsbt r2, [r0] - orrls r1, r1, r2, lsl #8 +3: ldrlsbt ip, [r0] + orrls r1, r1, ip, lsl #8 movls r0, #0 movls pc, lr b __get_user_bad --- linux-2.4.25/arch/arm/lib/memcpy.S~2.4.25-vrs2-pxa1.patch 2001-03-07 04:44:35.000000000 +0100 +++ linux-2.4.25/arch/arm/lib/memcpy.S 2004-03-31 17:15:11.000000000 +0200 @@ -8,6 +8,9 @@ * published by the Free Software Foundation. * * ASM optimised string functions + * + * Big Endian, prefetching and code factorization provided by Nicolas Pitre: + * Copyright (C) 2002-2003 MontaVista Software, Inc. */ #include #include @@ -27,15 +30,16 @@ /* * Prototype: void memcpy(void *to,const void *from,unsigned long n); - * ARM3: cant use memcopy here!!! */ ENTRY(memcpy) ENTRY(memmove) ENTER - cmp r1, r0 - bcc 19f + subs ip, r0, r1 + cmphi r2, ip + bhi 18f subs r2, r2, #4 blt 6f + PLD( pld [r1, #0] ) ands ip, r0, #3 bne 7f ands ip, r1, #3 @@ -43,29 +47,59 @@ 1: subs r2, r2, #8 blt 5f - subs r2, r2, #0x14 - blt 3f -2: ldmia r1!,{r3 - r9, ip} - stmia r0!,{r3 - r9, ip} + subs r2, r2, #20 + blt 4f + + PLD( subs r2, r2, #65 ) + PLD( blt 3f ) + PLD( pld [r1, #32] ) + + PLD( @ cache alignment ) + PLD( ands ip, r1, #31 ) + PLD( pld [r1, #64] ) + PLD( beq 2f ) + PLD( rsb ip, ip, #32 ) + PLD( cmp r2, ip ) + PLD( pld [r1, #96] ) + PLD( blt 2f ) + PLD( cmp ip, #16 ) + PLD( sub r2, r2, ip ) + PLD( ldmgeia r1!, {r3 - r6} ) + PLD( stmgeia r0!, {r3 - r6} ) + PLD( beq 2f ) + PLD( and ip, ip, #15 ) + PLD( cmp ip, #8 ) + PLD( ldr r3, [r1], #4 ) + PLD( ldrge r4, [r1], #4 ) + PLD( ldrgt r5, [r1], #4 ) + PLD( str r3, [r0], #4 ) + PLD( strge r4, [r0], #4 ) + PLD( strgt r5, [r0], #4 ) + +2: PLD( pld [r1, #96] ) +3: ldmia r1!, {r3 - r9, ip} subs r2, r2, #32 + stmia r0!, {r3 - r9, ip} bge 2b - cmn r2, #16 + PLD( cmn r2, #65 ) + PLD( bge 3b ) + PLD( add r2, r2, #65 ) +4: cmn r2, #16 ldmgeia r1!, {r3 - r6} + subge r2, r2, #16 stmgeia r0!, {r3 - r6} - subge r2, r2, #0x10 -3: adds r2, r2, #0x14 -4: ldmgeia r1!, {r3 - r5} + adds r2, r2, #20 + ldmgeia r1!, {r3 - r5} + subge r2, r2, #12 stmgeia r0!, {r3 - r5} - subges r2, r2, #12 - bge 4b 5: adds r2, r2, #8 blt 6f subs r2, r2, #4 ldrlt r3, [r1], #4 ldmgeia r1!, {r4, r5} + subge r2, r2, #4 strlt r3, [r0], #4 stmgeia r0!, {r4, r5} - subge r2, r2, #4 6: adds r2, r2, #4 EXITEQ @@ -92,122 +126,175 @@ beq 1b 8: bic r1, r1, #3 - ldr r7, [r1], #4 cmp ip, #2 - bgt 15f - beq 11f + ldr lr, [r1], #4 + bgt 17f + beq 16f + + + .macro forward_copy_shift pull push + cmp r2, #12 - blt 10f - sub r2, r2, #12 -9: mov r3, r7, lsr #8 - ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #24 - mov r4, r4, lsr #8 - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - mov r6, r6, lsr #8 - orr r6, r6, r7, lsl #24 + PLD( pld [r1, #0] ) + blt 14f + subs r2, r2, #28 + blt 12f + + PLD( subs r2, r2, #97 ) + PLD( blt 11f ) + PLD( pld [r1, #32] ) + + PLD( @ cache alignment ) + PLD( rsb ip, r1, #36 ) + PLD( pld [r1, #64] ) + PLD( ands ip, ip, #31 ) + PLD( pld [r1, #96] ) + PLD( beq 10f ) + PLD( cmp r2, ip ) + PLD( pld [r1, #128] ) + PLD( blt 10f ) + PLD( sub r2, r2, ip ) +9: PLD( mov r3, lr, pull #\pull ) + PLD( ldr lr, [r1], #4 ) + PLD( subs ip, ip, #4 ) + PLD( orr r3, r3, lr, push #\push ) + PLD( str r3, [r0], #4 ) + PLD( bgt 9b ) + +10: PLD( pld [r1, #128] ) +11: mov r3, lr, pull #\pull + ldmia r1!, {r4 - r9, ip, lr} + subs r2, r2, #32 + orr r3, r3, r4, push #\push + mov r4, r4, pull #\pull + orr r4, r4, r5, push #\push + mov r5, r5, pull #\pull + orr r5, r5, r6, push #\push + mov r6, r6, pull #\pull + orr r6, r6, r7, push #\push + mov r7, r7, pull #\pull + orr r7, r7, r8, push #\push + mov r8, r8, pull #\pull + orr r8, r8, r9, push #\push + mov r9, r9, pull #\pull + orr r9, r9, ip, push #\push + mov ip, ip, pull #\pull + orr ip, ip, lr, push #\push + stmia r0!, {r3 - r9, ip} + bge 10b + PLD( cmn r2, #97 ) + PLD( bge 11b ) + PLD( add r2, r2, #97 ) + cmn r2, #16 + blt 13f +12: mov r3, lr, pull #\pull + ldmia r1!, {r4 - r6, lr} + sub r2, r2, #16 + orr r3, r3, r4, push #\push + mov r4, r4, pull #\pull + orr r4, r4, r5, push #\push + mov r5, r5, pull #\pull + orr r5, r5, r6, push #\push + mov r6, r6, pull #\pull + orr r6, r6, lr, push #\push stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 9b - adds r2, r2, #12 - blt 100f -10: mov r3, r7, lsr #8 - ldr r7, [r1], #4 +13: adds r2, r2, #28 + blt 15f +14: mov r3, lr, pull #\pull + ldr lr, [r1], #4 subs r2, r2, #4 - orr r3, r3, r7, lsl #24 + orr r3, r3, lr, push #\push str r3, [r0], #4 - bge 10b -100: sub r1, r1, #3 + bge 14b +15: + .endm + + + forward_copy_shift pull=8 push=24 + sub r1, r1, #3 b 6b -11: cmp r2, #12 - blt 13f /* */ - sub r2, r2, #12 -12: mov r3, r7, lsr #16 - ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #16 - mov r4, r4, lsr #16 - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - mov r6, r6, lsr #16 - orr r6, r6, r7,LSL#16 - stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 12b - adds r2, r2, #12 - blt 14f -13: mov r3, r7, lsr #16 - ldr r7, [r1], #4 - subs r2, r2, #4 - orr r3, r3, r7, lsl #16 - str r3, [r0], #4 - bge 13b -14: sub r1, r1, #2 +16: forward_copy_shift pull=16 push=16 + sub r1, r1, #2 b 6b -15: cmp r2, #12 - blt 17f - sub r2, r2, #12 -16: mov r3, r7, lsr #24 - ldmia r1!,{r4 - r7} - orr r3, r3, r4, lsl #8 - mov r4, r4, lsr #24 - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - mov r6, r6, lsr #24 - orr r6, r6, r7, lsl #8 - stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 16b - adds r2, r2, #12 - blt 18f -17: mov r3, r7, lsr #24 - ldr r7, [r1], #4 - subs r2, r2, #4 - orr r3, r3, r7, lsl#8 - str r3, [r0], #4 - bge 17b -18: sub r1, r1, #1 +17: forward_copy_shift pull=24 push=8 + sub r1, r1, #1 b 6b -19: add r1, r1, r2 +18: add r1, r1, r2 add r0, r0, r2 subs r2, r2, #4 blt 24f + PLD( pld [r1, #-4] ) ands ip, r0, #3 bne 25f ands ip, r1, #3 bne 26f -20: subs r2, r2, #8 +19: subs r2, r2, #8 blt 23f - subs r2, r2, #0x14 + subs r2, r2, #20 blt 22f -21: ldmdb r1!, {r3 - r9, ip} - stmdb r0!, {r3 - r9, ip} + + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 21f ) + + PLD( @ cache alignment ) + PLD( ands ip, r1, #31 ) + PLD( pld [r1, #-64] ) + PLD( beq 20f ) + PLD( cmp r2, ip ) + PLD( pld [r1, #-96] ) + PLD( blt 20f ) + PLD( cmp ip, #16 ) + PLD( sub r2, r2, ip ) + PLD( ldmgedb r1!, {r3 - r6} ) + PLD( stmgedb r0!, {r3 - r6} ) + PLD( beq 20f ) + PLD( and ip, ip, #15 ) + PLD( cmp ip, #8 ) + PLD( ldr r3, [r1, #-4]! ) + PLD( ldrge r4, [r1, #-4]! ) + PLD( ldrgt r5, [r1, #-4]! ) + PLD( str r3, [r0, #-4]! ) + PLD( strge r4, [r0, #-4]! ) + PLD( strgt r5, [r0, #-4]! ) + +20: PLD( pld [r1, #-96] ) + PLD( pld [r1, #-128] ) +21: ldmdb r1!, {r3 - r6} subs r2, r2, #32 - bge 21b -22: cmn r2, #16 + stmdb r0!, {r3 - r6} + ldmdb r1!, {r3 - r6} + stmgedb r0!, {r3 - r6} ldmgedb r1!, {r3 - r6} stmgedb r0!, {r3 - r6} + ldmgedb r1!, {r3 - r6} + subges r2, r2, #32 + stmdb r0!, {r3 - r6} + bge 20b + PLD( cmn r2, #96 ) + PLD( bge 21b ) + PLD( add r2, r2, #96 ) +22: cmn r2, #16 + ldmgedb r1!, {r3 - r6} subge r2, r2, #16 + stmgedb r0!, {r3 - r6} adds r2, r2, #20 ldmgedb r1!, {r3 - r5} - stmgedb r0!, {r3 - r5} subge r2, r2, #12 + stmgedb r0!, {r3 - r5} 23: adds r2, r2, #8 blt 24f subs r2, r2, #4 ldrlt r3, [r1, #-4]! ldmgedb r1!, {r4, r5} + subge r2, r2, #4 strlt r3, [r0, #-4]! stmgedb r0!, {r4, r5} - subge r2, r2, #4 24: adds r2, r2, #4 EXITEQ @@ -230,89 +317,101 @@ subs r2, r2, ip blt 24b ands ip, r1, #3 - beq 20b + beq 19b 26: bic r1, r1, #3 - ldr r3, [r1], #0 cmp ip, #2 - blt 34f - beq 30f - cmp r2, #12 - blt 28f - sub r2, r2, #12 -27: mov r7, r3, lsl #8 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #24 - mov r6, r6, lsl #8 - orr r6, r6, r5, lsr #24 - mov r5, r5, lsl #8 - orr r5, r5, r4, lsr #24 - mov r4, r4, lsl #8 - orr r4, r4, r3, lsr #24 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 27b - adds r2, r2, #12 - blt 29f -28: mov ip, r3, lsl #8 - ldr r3, [r1, #-4]! - subs r2, r2, #4 - orr ip, ip, r3, lsr #24 - str ip, [r0, #-4]! - bge 28b -29: add r1, r1, #3 - b 24b + ldr r3, [r1], #0 + blt 35f + beq 34f -30: cmp r2, #12 + + .macro backward_copy_shift push pull + + cmp r2, #12 + PLD( pld [r1, #-4] ) blt 32f - sub r2, r2, #12 -31: mov r7, r3, lsl #16 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #16 - mov r6, r6, lsl #16 - orr r6, r6, r5, lsr #16 - mov r5, r5, lsl #16 - orr r5, r5, r4, lsr #16 - mov r4, r4, lsl #16 - orr r4, r4, r3, lsr #16 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 31b - adds r2, r2, #12 + subs r2, r2, #28 + blt 30f + + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 29f ) + PLD( pld [r1, #-64] ) + + PLD( @ cache alignment ) + PLD( ands ip, r1, #31 ) + PLD( pld [r1, #-96] ) + PLD( beq 28f ) + PLD( cmp r2, ip ) + PLD( pld [r1, #-128] ) + PLD( blt 28f ) + PLD( sub r2, r2, ip ) +27: PLD( mov r4, r3, push #\push ) + PLD( ldr r3, [r1, #-4]! ) + PLD( subs ip, ip, #4 ) + PLD( orr r4, r4, r3, pull #\pull ) + PLD( str r4, [r0, #-4]! ) + PLD( bgt 27b ) + +28: PLD( pld [r1, #-128] ) +29: mov lr, r3, push #\push + ldmdb r1!, {r3 - r9, ip} + subs r2, r2, #32 + orr lr, lr, ip, pull #\pull + mov ip, ip, push #\push + orr ip, ip, r9, pull #\pull + mov r9, r9, push #\push + orr r9, r9, r8, pull #\pull + mov r8, r8, push #\push + orr r8, r8, r7, pull #\pull + mov r7, r7, push #\push + orr r7, r7, r6, pull #\pull + mov r6, r6, push #\push + orr r6, r6, r5, pull #\pull + mov r5, r5, push #\push + orr r5, r5, r4, pull #\pull + mov r4, r4, push #\push + orr r4, r4, r3, pull #\pull + stmdb r0!, {r4 - r9, ip, lr} + bge 28b + PLD( cmn r2, #96 ) + PLD( bge 29b ) + PLD( add r2, r2, #96 ) + cmn r2, #16 + blt 31f +30: mov r7, r3, push #\push + ldmdb r1!, {r3 - r6} + sub r2, r2, #16 + orr r7, r7, r6, pull #\pull + mov r6, r6, push #\push + orr r6, r6, r5, pull #\pull + mov r5, r5, push #\push + orr r5, r5, r4, pull #\pull + mov r4, r4, push #\push + orr r4, r4, r3, pull #\pull + stmdb r0!, {r4 - r7} +31: adds r2, r2, #28 blt 33f -32: mov ip, r3, lsl #16 +32: mov r4, r3, push #\push ldr r3, [r1, #-4]! subs r2, r2, #4 - orr ip, ip, r3, lsr #16 - str ip, [r0, #-4]! + orr r4, r4, r3, pull #\pull + str r4, [r0, #-4]! bge 32b -33: add r1, r1, #2 +33: + .endm + + + backward_copy_shift push=8 pull=24 + add r1, r1, #3 b 24b -34: cmp r2, #12 - blt 36f - sub r2, r2, #12 -35: mov r7, r3, lsl #24 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #8 - mov r6, r6, lsl #24 - orr r6, r6, r5, lsr #8 - mov r5, r5, lsl #24 - orr r5, r5, r4, lsr #8 - mov r4, r4, lsl #24 - orr r4, r4, r3, lsr #8 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 35b - adds r2, r2, #12 - blt 37f -36: mov ip, r3, lsl #24 - ldr r3, [r1, #-4]! - subs r2, r2, #4 - orr ip, ip, r3, lsr #8 - str ip, [r0, #-4]! - bge 36b -37: add r1, r1, #1 +34: backward_copy_shift push=16 pull=16 + add r1, r1, #2 + b 24b + +35: backward_copy_shift push=24 pull=8 + add r1, r1, #1 b 24b - .align --- linux-2.4.25/arch/arm/lib/uaccess.S~2.4.25-vrs2-pxa1.patch 2000-09-19 00:15:25.000000000 +0200 +++ linux-2.4.25/arch/arm/lib/uaccess.S 2004-03-31 17:15:11.000000000 +0200 @@ -43,6 +43,8 @@ stmfd sp!, {r2, r4 - r7, lr} cmp r2, #4 blt .c2u_not_enough + PLD( pld [r1, #0] ) + PLD( pld [r0, #0] ) ands ip, r0, #3 bne .c2u_dest_not_aligned .c2u_dest_aligned: @@ -71,13 +73,26 @@ sub r2, r2, ip subs ip, ip, #32 blt .c2u_0rem8lp + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) + PLD( subs ip, ip, #64 ) + PLD( blt .c2u_0cpynopld ) + PLD( pld [r1, #60] ) + PLD( pld [r0, #60] ) -.c2u_0cpy8lp: ldmia r1!, {r3 - r6} +.c2u_0cpy8lp: + PLD( pld [r1, #92] ) + PLD( pld [r0, #92] ) +.c2u_0cpynopld: ldmia r1!, {r3 - r6} stmia r0!, {r3 - r6} @ Shouldnt fault ldmia r1!, {r3 - r6} - stmia r0!, {r3 - r6} @ Shouldnt fault subs ip, ip, #32 + stmia r0!, {r3 - r6} @ Shouldnt fault bpl .c2u_0cpy8lp + PLD( cmn ip, #64 ) + PLD( bge .c2u_0cpynopld ) + PLD( add ip, ip, #64 ) + .c2u_0rem8lp: cmn ip, #16 ldmgeia r1!, {r3 - r6} stmgeia r0!, {r3 - r6} @ Shouldnt fault @@ -115,9 +130,9 @@ .c2u_1fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .c2u_1nowords - mov r3, r7, lsr #8 + mov r3, r7, pull #8 ldr r7, [r1], #4 - orr r3, r3, r7, lsl #24 + orr r3, r3, r7, push #24 USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -128,50 +143,63 @@ sub r2, r2, ip subs ip, ip, #16 blt .c2u_1rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .c2u_1cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.c2u_1cpy8lp: mov r3, r7, lsr #8 +.c2u_1cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.c2u_1cpynopld: mov r3, r7, pull #8 ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #24 - mov r4, r4, lsr #8 - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - mov r6, r6, lsr #8 - orr r6, r6, r7, lsl #24 - stmia r0!, {r3 - r6} @ Shouldnt fault subs ip, ip, #16 + orr r3, r3, r4, push #24 + mov r4, r4, pull #8 + orr r4, r4, r5, push #24 + mov r5, r5, pull #8 + orr r5, r5, r6, push #24 + mov r6, r6, pull #8 + orr r6, r6, r7, push #24 + stmia r0!, {r3 - r6} @ Shouldnt fault bpl .c2u_1cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .c2u_1cpynopld ) + PLD( add ip, ip, #32 ) + .c2u_1rem8lp: tst ip, #8 - movne r3, r7, lsr #8 + movne r3, r7, pull #8 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, lsl #24 - movne r4, r4, lsr #8 - orrne r4, r4, r7, lsl #24 + orrne r3, r3, r4, push #24 + movne r4, r4, pull #8 + orrne r4, r4, r7, push #24 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, lsr #8 + movne r3, r7, pull #8 ldrne r7, [r1], #4 - orrne r3, r3, r7, lsl #24 + orrne r3, r3, r7, push #24 strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_1fupi -.c2u_1nowords: mov r3, r7, lsr #8 +.c2u_1nowords: mov r3, r7, lsr #byte(1) teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r3, lsr #8 + movge r3, r7, lsr #byte(2) USER( strgebt r3, [r0], #1) @ May fault - movgt r3, r3, lsr #8 + movgt r3, r7, lsr #byte(3) USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished .c2u_2fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .c2u_2nowords - mov r3, r7, lsr #16 + mov r3, r7, pull #16 ldr r7, [r1], #4 - orr r3, r3, r7, lsl #16 + orr r3, r3, r7, push #16 USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -182,39 +210,52 @@ sub r2, r2, ip subs ip, ip, #16 blt .c2u_2rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .c2u_2cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.c2u_2cpy8lp: mov r3, r7, lsr #16 +.c2u_2cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.c2u_2cpynopld: mov r3, r7, pull #16 ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #16 - mov r4, r4, lsr #16 - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - mov r6, r6, lsr #16 - orr r6, r6, r7, lsl #16 - stmia r0!, {r3 - r6} @ Shouldnt fault subs ip, ip, #16 + orr r3, r3, r4, push #16 + mov r4, r4, pull #16 + orr r4, r4, r5, push #16 + mov r5, r5, pull #16 + orr r5, r5, r6, push #16 + mov r6, r6, pull #16 + orr r6, r6, r7, push #16 + stmia r0!, {r3 - r6} @ Shouldnt fault bpl .c2u_2cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .c2u_2cpynopld ) + PLD( add ip, ip, #32 ) + .c2u_2rem8lp: tst ip, #8 - movne r3, r7, lsr #16 + movne r3, r7, pull #16 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, lsl #16 - movne r4, r4, lsr #16 - orrne r4, r4, r7, lsl #16 + orrne r3, r3, r4, push #16 + movne r4, r4, pull #16 + orrne r4, r4, r7, push #16 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, lsr #16 + movne r3, r7, pull #16 ldrne r7, [r1], #4 - orrne r3, r3, r7, lsl #16 + orrne r3, r3, r7, push #16 strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_2fupi -.c2u_2nowords: mov r3, r7, lsr #16 +.c2u_2nowords: mov r3, r7, lsr #byte(2) teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r3, lsr #8 + movge r3, r7, lsr #byte(3) USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 USER( strgtbt r3, [r0], #1) @ May fault @@ -223,9 +264,9 @@ .c2u_3fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .c2u_3nowords - mov r3, r7, lsr #24 + mov r3, r7, pull #24 ldr r7, [r1], #4 - orr r3, r3, r7, lsl #8 + orr r3, r3, r7, push #8 USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -236,41 +277,54 @@ sub r2, r2, ip subs ip, ip, #16 blt .c2u_3rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .c2u_3cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.c2u_3cpy8lp: mov r3, r7, lsr #24 +.c2u_3cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.c2u_3cpynopld: mov r3, r7, pull #24 ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #8 - mov r4, r4, lsr #24 - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - mov r6, r6, lsr #24 - orr r6, r6, r7, lsl #8 - stmia r0!, {r3 - r6} @ Shouldnt fault subs ip, ip, #16 + orr r3, r3, r4, push #8 + mov r4, r4, pull #24 + orr r4, r4, r5, push #8 + mov r5, r5, pull #24 + orr r5, r5, r6, push #8 + mov r6, r6, pull #24 + orr r6, r6, r7, push #8 + stmia r0!, {r3 - r6} @ Shouldnt fault bpl .c2u_3cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .c2u_3cpynopld ) + PLD( add ip, ip, #32 ) + .c2u_3rem8lp: tst ip, #8 - movne r3, r7, lsr #24 + movne r3, r7, pull #24 ldmneia r1!, {r4, r7} - orrne r3, r3, r4, lsl #8 - movne r4, r4, lsr #24 - orrne r4, r4, r7, lsl #8 + orrne r3, r3, r4, push #8 + movne r4, r4, pull #24 + orrne r4, r4, r7, push #8 stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 - movne r3, r7, lsr #24 + movne r3, r7, pull #24 ldrne r7, [r1], #4 - orrne r3, r3, r7, lsl #8 + orrne r3, r3, r7, push #8 strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_3fupi -.c2u_3nowords: mov r3, r7, lsr #24 +.c2u_3nowords: mov r3, r7, lsr #byte(3) teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - ldrge r3, [r1], #0 + ldrgeb r3, [r1], #1 USER( strgebt r3, [r0], #1) @ May fault - movgt r3, r3, lsr #8 + ldrgtb r3, [r1], #0 USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished @@ -302,6 +356,8 @@ stmfd sp!, {r0, r2, r4 - r7, lr} cmp r2, #4 blt .cfu_not_enough + PLD( pld [r1, #0] ) + PLD( pld [r0, #0] ) ands ip, r0, #3 bne .cfu_dest_not_aligned .cfu_dest_aligned: @@ -329,13 +385,26 @@ sub r2, r2, ip subs ip, ip, #32 blt .cfu_0rem8lp + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) + PLD( subs ip, ip, #64 ) + PLD( blt .cfu_0cpynopld ) + PLD( pld [r1, #60] ) + PLD( pld [r0, #60] ) -.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault +.cfu_0cpy8lp: + PLD( pld [r1, #92] ) + PLD( pld [r0, #92] ) +.cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault stmia r0!, {r3 - r6} ldmia r1!, {r3 - r6} @ Shouldnt fault - stmia r0!, {r3 - r6} subs ip, ip, #32 + stmia r0!, {r3 - r6} bpl .cfu_0cpy8lp + PLD( cmn ip, #64 ) + PLD( bge .cfu_0cpynopld ) + PLD( add ip, ip, #64 ) + .cfu_0rem8lp: cmn ip, #16 ldmgeia r1!, {r3 - r6} @ Shouldnt fault stmgeia r0!, {r3 - r6} @@ -374,9 +443,9 @@ .cfu_1fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .cfu_1nowords - mov r3, r7, lsr #8 + mov r3, r7, pull #8 USER( ldrt r7, [r1], #4) @ May fault - orr r3, r3, r7, lsl #24 + orr r3, r3, r7, push #24 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -387,50 +456,63 @@ sub r2, r2, ip subs ip, ip, #16 blt .cfu_1rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .cfu_1cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.cfu_1cpy8lp: mov r3, r7, lsr #8 +.cfu_1cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.cfu_1cpynopld: mov r3, r7, pull #8 ldmia r1!, {r4 - r7} @ Shouldnt fault - orr r3, r3, r4, lsl #24 - mov r4, r4, lsr #8 - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - mov r6, r6, lsr #8 - orr r6, r6, r7, lsl #24 - stmia r0!, {r3 - r6} subs ip, ip, #16 + orr r3, r3, r4, push #24 + mov r4, r4, pull #8 + orr r4, r4, r5, push #24 + mov r5, r5, pull #8 + orr r5, r5, r6, push #24 + mov r6, r6, pull #8 + orr r6, r6, r7, push #24 + stmia r0!, {r3 - r6} bpl .cfu_1cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .cfu_1cpynopld ) + PLD( add ip, ip, #32 ) + .cfu_1rem8lp: tst ip, #8 - movne r3, r7, lsr #8 + movne r3, r7, pull #8 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, lsl #24 - movne r4, r4, lsr #8 - orrne r4, r4, r7, lsl #24 + orrne r3, r3, r4, push #24 + movne r4, r4, pull #8 + orrne r4, r4, r7, push #24 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, lsr #8 + movne r3, r7, pull #8 USER( ldrnet r7, [r1], #4) @ May fault - orrne r3, r3, r7, lsl #24 + orrne r3, r3, r7, push #24 strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_1fupi -.cfu_1nowords: mov r3, r7, lsr #8 +.cfu_1nowords: mov r3, r7, lsr #byte(1) teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r3, lsr #8 + movge r3, r7, lsr #byte(2) strgeb r3, [r0], #1 - movgt r3, r3, lsr #8 + movgt r3, r7, lsr #byte(3) strgtb r3, [r0], #1 b .cfu_finished .cfu_2fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .cfu_2nowords - mov r3, r7, lsr #16 + mov r3, r7, pull #16 USER( ldrt r7, [r1], #4) @ May fault - orr r3, r3, r7, lsl #16 + orr r3, r3, r7, push #16 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -441,39 +523,52 @@ sub r2, r2, ip subs ip, ip, #16 blt .cfu_2rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .cfu_2cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.cfu_2cpy8lp: mov r3, r7, lsr #16 +.cfu_2cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.cfu_2cpynopld: mov r3, r7, pull #16 ldmia r1!, {r4 - r7} @ Shouldnt fault - orr r3, r3, r4, lsl #16 - mov r4, r4, lsr #16 - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - mov r6, r6, lsr #16 - orr r6, r6, r7, lsl #16 - stmia r0!, {r3 - r6} subs ip, ip, #16 + orr r3, r3, r4, push #16 + mov r4, r4, pull #16 + orr r4, r4, r5, push #16 + mov r5, r5, pull #16 + orr r5, r5, r6, push #16 + mov r6, r6, pull #16 + orr r6, r6, r7, push #16 + stmia r0!, {r3 - r6} bpl .cfu_2cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .cfu_2cpynopld ) + PLD( add ip, ip, #32 ) + .cfu_2rem8lp: tst ip, #8 - movne r3, r7, lsr #16 + movne r3, r7, pull #16 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, lsl #16 - movne r4, r4, lsr #16 - orrne r4, r4, r7, lsl #16 + orrne r3, r3, r4, push #16 + movne r4, r4, pull #16 + orrne r4, r4, r7, push #16 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, lsr #16 + movne r3, r7, pull #16 USER( ldrnet r7, [r1], #4) @ May fault - orrne r3, r3, r7, lsl #16 + orrne r3, r3, r7, push #16 strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_2fupi -.cfu_2nowords: mov r3, r7, lsr #16 +.cfu_2nowords: mov r3, r7, lsr #byte(2) teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r3, lsr #8 + movge r3, r7, lsr #byte(3) strgeb r3, [r0], #1 USER( ldrgtbt r3, [r1], #0) @ May fault strgtb r3, [r0], #1 @@ -482,9 +577,9 @@ .cfu_3fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .cfu_3nowords - mov r3, r7, lsr #24 + mov r3, r7, pull #24 USER( ldrt r7, [r1], #4) @ May fault - orr r3, r3, r7, lsl #8 + orr r3, r3, r7, push #8 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 @@ -495,41 +590,54 @@ sub r2, r2, ip subs ip, ip, #16 blt .cfu_3rem8lp + PLD( pld [r1, #12] ) + PLD( pld [r0, #12] ) + PLD( subs ip, ip, #32 ) + PLD( blt .cfu_3cpynopld ) + PLD( pld [r1, #28] ) + PLD( pld [r0, #28] ) -.cfu_3cpy8lp: mov r3, r7, lsr #24 +.cfu_3cpy8lp: + PLD( pld [r1, #44] ) + PLD( pld [r0, #44] ) +.cfu_3cpynopld: mov r3, r7, pull #24 ldmia r1!, {r4 - r7} @ Shouldnt fault - orr r3, r3, r4, lsl #8 - mov r4, r4, lsr #24 - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - mov r6, r6, lsr #24 - orr r6, r6, r7, lsl #8 + orr r3, r3, r4, push #8 + mov r4, r4, pull #24 + orr r4, r4, r5, push #8 + mov r5, r5, pull #24 + orr r5, r5, r6, push #8 + mov r6, r6, pull #24 + orr r6, r6, r7, push #8 stmia r0!, {r3 - r6} subs ip, ip, #16 bpl .cfu_3cpy8lp + PLD( cmn ip, #32 ) + PLD( bge .cfu_3cpynopld ) + PLD( add ip, ip, #32 ) + .cfu_3rem8lp: tst ip, #8 - movne r3, r7, lsr #24 + movne r3, r7, pull #24 ldmneia r1!, {r4, r7} @ Shouldnt fault - orrne r3, r3, r4, lsl #8 - movne r4, r4, lsr #24 - orrne r4, r4, r7, lsl #8 + orrne r3, r3, r4, push #8 + movne r4, r4, pull #24 + orrne r4, r4, r7, push #8 stmneia r0!, {r3 - r4} tst ip, #4 - movne r3, r7, lsr #24 + movne r3, r7, pull #24 USER( ldrnet r7, [r1], #4) @ May fault - orrne r3, r3, r7, lsl #8 + orrne r3, r3, r7, push #8 strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_3fupi -.cfu_3nowords: mov r3, r7, lsr #24 +.cfu_3nowords: mov r3, r7, lsr #byte(3) teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 -USER( ldrget r3, [r1], #0) @ May fault +USER( ldrgebt r3, [r1], #1) @ May fault strgeb r3, [r0], #1 - movgt r3, r3, lsr #8 +USER( ldrgtbt r3, [r1], #1) @ May fault strgtb r3, [r0], #1 b .cfu_finished @@ -544,7 +652,7 @@ ldr r1, [sp], #4 @ unsigned long count subs r4, r1, r2 @ bytes left to copy movne r1, r4 - blne SYMBOL_NAME(__memzero) + blne __memzero mov r0, r4 LOADREGS(fd,sp!, {r4 - r7, pc}) .previous --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,56 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +USE_STANDARD_AS_RULE := true + +O_TARGET := pxa.o + +obj-y := +obj-m := +obj-n := +obj- := + +export-objs := generic.o irq.o dma.o sa1111.o \ + usb_ctl.o usb_recv.o usb_send.o + +# Common support (must be linked before board specific support) +obj-y += generic.o irq.o dma.o +obj-$(CONFIG_SA1111) += sa1111.o + +# Specific board support +obj-$(CONFIG_ARCH_CSB226) += csb226.o +obj-$(CONFIG_ARCH_INNOKOM) += innokom.o +obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o +obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o +obj-$(CONFIG_ARCH_PXA_IDP) += idp.o +obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o + +# Support for blinky lights +leds-y := leds.o +leds-$(CONFIG_ARCH_CSB226) += leds-csb226.o +leds-$(CONFIG_ARCH_INNOKOM) += leds-innokom.o +leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o +leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o +leds-$(CONFIG_ARCH_PXA_CERF) += leds-cerf.o + +obj-$(CONFIG_LEDS) += $(leds-y) + +# PXA USB client support +list-multi += pxausb_core.o +pxausb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o +obj-$(CONFIG_PXA_USB) += pxausb_core.o +obj-$(CONFIG_PXA_USB_NETLINK) += usb-eth.o +obj-$(CONFIG_PXA_USB_CHAR) += usb-char.o + +# Misc features +obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o + +include $(TOPDIR)/Rules.make + +pxausb_core.o: $(pxausb_core-objs) + $(LD) -r -o $@ $(pxausb_core-objs) --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/cerf.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,266 @@ +/* + * linux/arch/arm/mach-pxa/cerf.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + +/* + * Set this to zero to remove all the debug statements via + * dead code elimination. + */ +#define DEBUGGING 1 + +#if DEBUGGING +static unsigned int cerf_debug = DEBUGGING; +#else +#define cerf_debug 0 +#endif + +static void __init cerf_init_irq(void) +{ + pxa_init_irq(); + + if( cerf_debug > 1) + { +#if 0 + GPDR0 = 0xc05b9130; + GPDR1 = 0xfcffab82; + GPDR2 = 0x0001ffff; +#endif + + printk(KERN_INFO "Pin directions:\n"); + printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0); + printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1); + printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2); + + printk(KERN_INFO "Pin State:\n"); + printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0); + printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1); + printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2); + + printk(KERN_INFO "Rising Edge:\n"); + printk(KERN_INFO "GRER0 0x%08x\n", GRER0); + printk(KERN_INFO "GRER1 0x%08x\n", GRER1); + printk(KERN_INFO "GRER2 0x%08x\n", GRER2); + + printk(KERN_INFO "Falling Edge:\n"); + printk(KERN_INFO "GFER0 0x%08x\n", GFER0); + printk(KERN_INFO "GFER1 0x%08x\n", GFER1); + printk(KERN_INFO "GFER2 0x%08x\n", GFER2); + } + + /* set_GPIO_IRQ_edge has to be called before an irq can be requested */ + set_GPIO_IRQ_edge( 0, GPIO_FALLING_EDGE); /* CPLD */ +#ifdef CONFIG_PXA_CERF_PDA + set_GPIO_IRQ_edge( 2, GPIO_RISING_EDGE); /* UART B Interrupt */ + set_GPIO_IRQ_edge( 3, GPIO_RISING_EDGE); /* UART A Interrupt */ + set_GPIO_IRQ_edge( 32, GPIO_RISING_EDGE); /* UCB1400 Interrupt */ +#endif + set_GPIO_IRQ_edge( 14, GPIO_FALLING_EDGE); /* PCMCIA Card Detect */ + set_GPIO_IRQ_edge( 21, GPIO_RISING_EDGE); /* Ethernet Interrupt */ +} + +static int __init cerf_init(void) +{ + /* + * All of the code that was here was SA1111 init code + * which we do not have. + */ + return 0; +} + +__initcall(cerf_init); + +static void __init +fixup_cerf(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + SET_BANK (0, CERF_RAM_BASE, CERF_RAM_SIZE); + mi->nr_banks = 1; + +#if 0 // Enable this stuff if you plan on not using jffs2 + setup_ramdisk (1, 0, 0, 8192); + setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024); + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); +#endif +} + +/* + * IO map for the devices. + */ +static struct map_desc cerf_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { CERF_FLASH_BASE , CERF_FLASH_PHYS , CERF_FLASH_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, + { CERF_ETH_BASE , CERF_ETH_PHYS , CERF_ETH_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, +#ifdef CONFIG_PXA_CERF_PDA + { CERF_BT_BASE , CERF_BT_PHYS , CERF_BT_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, + { CERF_SERIAL_BASE, CERF_SERIAL_PHYS, CERF_SERIAL_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, + { CERF_CPLD_BASE , CERF_CPLD_PHYS , CERF_CPLD_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, +#endif + + LAST_DESC +}; + +static void __init cerf_map_io(void) +{ + pxa_map_io(); + iotable_init(cerf_io_desc); + + if( cerf_debug > 1) + { + printk(KERN_INFO "origMCS0 = 0x%08x\n", MSC0); + printk(KERN_INFO "origMCS1 = 0x%08x\n", MSC1); + printk(KERN_INFO "origMCS2 = 0x%08x\n", MSC2); + } + + /* setup memory timing for CS0/1 */ + MSC0 = MSC_CS(0, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(3) | + MSC_RDN(15) | + MSC_RDF(13) | + MSC_RBW(0) | + MSC_RT(0)) | +#ifdef CONFIG_PXA_CERF_PDA + MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(7) | + MSC_RDN(15) | + MSC_RDF(15) | + MSC_RBW(1) | + MSC_RT(0)); +#elif defined(CONFIG_PXA_CERF_BOARD) + MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(1) | + MSC_RDN(2) | + MSC_RDF(4) | + MSC_RBW(0) | + MSC_RT(4)); +#endif + printk(KERN_INFO "MCS0 = 0x%08x\n", MSC0); + + /* setup memory timing for CS2/3 */ + MSC1 = MSC_CS(2, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(5) | + MSC_RDN(10) | + MSC_RDF(10) | + MSC_RBW(1) | + MSC_RT(0)) | + MSC_CS(3, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(5) | + MSC_RDN(10) | + MSC_RDF(10) | + MSC_RBW(1) | + MSC_RT(0)); + printk(KERN_INFO "MCS1 = 0x%08x\n", MSC1); + + /* setup memory timing for CS4/5 */ + MSC2 = MSC_CS(4, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(2) | + MSC_RDN(4) | + MSC_RDF(4) | + MSC_RBW(1) | + MSC_RT(0)) | + MSC_CS(5, MSC_RBUFF(MSC_RBUFF_SLOW) | + MSC_RRR(2) | + MSC_RDN(4) | + MSC_RDF(4) | + MSC_RBW(1) | + MSC_RT(0)); + printk(KERN_INFO "MCS2 = 0x%08x\n", MSC2); + +#ifdef CONFIG_SOUND_PXA_AC97 + printk(KERN_INFO "Enabling sound amp for pxa cerf pda.\n"); + outw( CERF_PDA_SOUND_ENABLE, CERF_CPLD_BASE+CERF_PDA_CPLD_SOUND_ENA); +#endif + +#ifdef CONFIG_FB_PXA + printk(KERN_INFO "Setting LCD to brightness to %d/15\n", CERF_PDA_DEFAULT_BRIGHTNESS); + outw( CERF_PDA_DEFAULT_BRIGHTNESS, CERF_CPLD_BASE+CERF_PDA_CPLD_BRIGHTNESS); +#endif + +#ifdef CONFIG_IRDA + /* Enable IrDA UART (SIR)*/ + CKEN |= CKEN5_STUART; + + /* We want to get our goods from the STUART */ + set_GPIO_mode(GPIO46_STRXD_MD); + set_GPIO_mode(GPIO47_STTXD_MD); + + /* make sure FIR ICP is off */ + ICCR0 = 0; + + /* configure STUART to for SIR + * NOTE: RCVEIR and XMITIR must not be set at the same time! + * Start with receive in IR mode, and switch transmit to IR only + * when we need to send something in serial driver. + */ + STISR = IrSR_IR_RECEIVE_ON; +#endif + +#if 0 + /* Connect FIR ICP to GPIO pins */ + CKEN |= CKEN13_FICP; + set_GPIO_mode(GPIO46_ICPRXD_MD); + set_GPIO_mode(GPIO47_ICPTXD_MD); + ICCR0 = 0x1 | 0x18; //ICP unit enable +#endif + +#if 0 + /* Enable BT UART */ + CKEN |= CKEN7_BTUART; + set_GPIO_mode(GPIO42_BTRXD_MD); + set_GPIO_mode(GPIO43_BTTXD_MD); + set_GPIO_mode(GPIO44_BTCTS_MD); + set_GPIO_mode(GPIO45_BTRTS_MD); +#endif + + if( cerf_debug > 1) + { + printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0); + printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1); + printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2); + printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0); + printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1); + printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2); + printk(KERN_INFO "GAFR0_L 0x%08x\n", GAFR0_L); + printk(KERN_INFO "GAFR0_U 0x%08x\n", GAFR0_U); + printk(KERN_INFO "GAFR1_L 0x%08x\n", GAFR1_L); + printk(KERN_INFO "GAFR1_U 0x%08x\n", GAFR1_U); + printk(KERN_INFO "GAFR2_L 0x%08x\n", GAFR2_L); + printk(KERN_INFO "GAFR2_U 0x%08x\n", GAFR2_U); + printk(KERN_INFO "CKEN = 0x%08x\n", CKEN); + printk(KERN_INFO "ICCR0 = 0x%08x\n", ICCR0); + printk(KERN_INFO "STISR = 0x%08x\n", STISR); + } +} + +MACHINE_START(PXA_CERF, "CerfBoard PXA Reference Board") + MAINTAINER("Intrinsyc Software Inc.") + BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000) + BOOT_PARAMS(0xa0000100) + FIXUP(fixup_cerf) + MAPIO(cerf_map_io) + INITIRQ(cerf_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/cpu-pxa.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,240 @@ +/* + * linux/arch/arm/mach-pxa/cpu-pxa.c + * + * Copyright (C) 2002,2003 Intrinsyc Software + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * 31-Jul-2002 : Initial version [FB] + * 29-Jan-2003 : added PXA255 support [FB] + * + * Note: + * + * Quote from erratum 134: + * ""If the operation of these peripherals would be adversely affected, + * then these peripherals would have to be disabled during a frequency + * change. (MMC,FFUART,STUART,BTUART,IRDA,SSP,UDC,AC97)"" + * + * This sounds like they are not sure what the bug is... + * If you run into problems with any of these peripherals, the effected + * driver should register with cpu freq notification and disable/enable + * the peripheral on CPUFREQ_PRECHANGE and CPUFREQ_POSTCHANGE. + * + * So far I've tested this code only under light load. It works for me. + * + * TODO: + * - determine min/max freq at runtime + * - determine pxbus value at runtime + * + */ + +#include +#include +#include +#include +#include + +#include + +#define DEBUGGING 1 + +#if DEBUGGING +static unsigned int freq_debug = DEBUGGING; +#else +#define freq_debug 0 +#endif + +typedef struct +{ + unsigned int khz; + unsigned int cccr; + unsigned int pxbus; +} pxa_freqs_t; + +#define CCLKCFG_TURBO 0x1 +#define CCLKCFG_FCS 0x2 + +#define PXA250_REV_A1 0x1 +#define PXA250_REV_B2 0x4 +#define PXA25x_MIN_FREQ 99000 + +//#define PXA25x_ALLOW_OVERCLOCK + +#ifdef PXA25x_ALLOW_OVERCLOCK +#warning *** Overclocking enabled - this may fry your hardware - you have been warned *** +#define OC(x...) x +#define PXA25x_MAX_FREQ 471000 +#else +#define OC(x...) +#define PXA25x_MAX_FREQ 400000 +#endif + +/* If CONFIG_CPU_FREQ is turned on but we find (at runtime) + * we can't support scaling, try to handle requests gracefully. + */ +static int supported; + +static pxa_freqs_t pxa250_valid_freqs[] = +{ + {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ + {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ + {398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ + {0,0} +}; + +static pxa_freqs_t pxa255_valid_freqs[] = +{ + { 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */ +OC( {118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */ + {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */ +OC( {236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */ + {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */ +OC( {354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */ + {398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */ + {398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */ +OC( {471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */ + {0,0} +}; + +static pxa_freqs_t *pxa_valid_freqs; + +/* This should be called with a valid freq point that was + * obtained via pxa_validate_speed + */ +static pxa_freqs_t * pxa_get_freq_info( unsigned int khz) +{ + int i=0; + while( pxa_valid_freqs[i].khz) + { + if( pxa_valid_freqs[i].khz == khz) + return &pxa_valid_freqs[i]; + i++; + } + + /* shouldn't get here */ + return 0; +} + +/* find a valid frequency point */ +static unsigned int pxa_validate_speed(unsigned int khz) +{ + int i=0; + unsigned int vfreq = 0; + while( pxa_valid_freqs[i].khz && (khz >= pxa_valid_freqs[i].khz)) + { + vfreq = pxa_valid_freqs[i].khz; + i++; + } + return vfreq; +} + +/* This should be called with a valid freq point that was + * obtained via pxa_validate_speed + */ +static void pxa_setspeed(unsigned int khz) +{ + unsigned long flags; + unsigned int unused; + void *ramstart = phys_to_virt(0xa0000000); + pxa_freqs_t *freq_info; + + if( ! supported) return; + + freq_info = pxa_get_freq_info( khz); + + if( ! freq_info) return; + + CCCR = freq_info->cccr; + if( freq_debug) + printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n", + khz/1000, freq_info->pxbus); + + local_irq_save(flags); + __asm__ __volatile__("\ + ldr r4, [%1] @load MDREFR \n\ + b 2f \n\ + .align 5 \n\ +1: \n\ + mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\ + \n\ + @ restart sdcke 0 / 1 \n\ + bic r5, r4, #(0x00001000 | 0x00008000) @ MDREFR_E0PIN | MDREFR_E1PIN \n\ + str r5, [%1] @clear \n\ + str r4, [%1] @restore \n\ + \n\ + @ Generate refresh cycles for all banks \n\ + ldr r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + str r4, [%3] \n\ + \n\ + b 3f \n\ +2: b 1b \n\ +3: nop \n\ + " + : "=&r" (unused) + : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart) + : "r4", "r5"); + local_irq_restore(flags); +} + +static int pxa_init_freqs( void) +{ + int cpu_ver; + asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); + + if( (cpu_ver & 0xf) <= PXA250_REV_A1) + { + return 0; + } + + if( (cpu_ver & 0xf) <= PXA250_REV_B2) + { + if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n"); + pxa_valid_freqs = pxa250_valid_freqs; + } + else /* C0 and above */ + { + if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n"); + pxa_valid_freqs = pxa255_valid_freqs; + } + + return 1; +} + +static int __init pxa_clk_init(void) +{ + if( pxa_init_freqs()) + { + if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n"); + supported = 1; + + cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ); + cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed); + } + else + { + if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n"); + /* Note that we have to initialize the generic code in order to + * release a lock (cpufreq_sem). Any registration for freq changes + * (e.g. lcd driver) will get blocked otherwise. + */ + cpufreq_init( 0, 0, 0); + cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed); + } + + return 0; +} + +module_init(pxa_clk_init); + +MODULE_AUTHOR ("Intrinsyc Software Inc."); +MODULE_LICENSE("GPL"); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/csb226.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,180 @@ +/* + * linux/arch/arm/mach-pxa/csb226.c + * + * (c) 2003 Robert Schwebel , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static unsigned long csb226_irq_en_mask; + +static void csb226_mask_and_ack_irq(unsigned int irq) +{ + int csb226_irq = (irq - CSB226_IRQ(0)); + csb226_irq_en_mask &= ~(1 << csb226_irq); + CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq); + CSB226_IRQ_SET_CLR &= ~(1 << csb226_irq); +} + +static void csb226_mask_irq(unsigned int irq) +{ + int csb226_irq = (irq - CSB226_IRQ(0)); + csb226_irq_en_mask &= ~(1 << csb226_irq); + CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq); +} + +static void csb226_unmask_irq(unsigned int irq) +{ + int csb226_irq = (irq - CSB226_IRQ(0)); + csb226_irq_en_mask |= (1 << csb226_irq); + CSB226_IRQ_MASK_EN |= (1 << csb226_irq); +} + +void csb226_irq_demux(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long irq_status; + int i; + + while ((irq_status = CSB226_IRQ_SET_CLR & csb226_irq_en_mask)) { + for (i = 0; i < 6; i++) { + if(irq_status & (1<nr_banks = 1; +#if 0 + setup_ramdisk (1, 0, 0, 8192); + setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024); + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); +#endif +} + +/* FIXME: shouldn't this be moved to arch/arm/mach-pxa/mm.c? [RS] */ +static struct map_desc csb226_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ +// { 0xf4000000, 0x04000000, 0x00ffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* HT4562B PS/2 controller */ + { 0xf8000000, 0x08000000, 1024*1024, DOMAIN_IO, 0, 1, 0, 0 }, /* CS8900 LAN controller */ +// { 0xe0000000, 0x20000000, 0x0fffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* CompactFlash */ +#if 0 + { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ + { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */ + { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */ + { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */ +#endif + LAST_DESC +}; + +static void __init csb226_map_io(void) +{ + pxa_map_io(); + iotable_init(csb226_io_desc); + + /* This enables the BTUART */ + CKEN |= CKEN7_BTUART; + set_GPIO_mode(GPIO42_BTRXD_MD); + set_GPIO_mode(GPIO43_BTTXD_MD); + set_GPIO_mode(GPIO44_BTCTS_MD); + set_GPIO_mode(GPIO45_BTRTS_MD); + + /* This is for the CS8900 chip select */ + set_GPIO_mode(GPIO78_nCS_2_MD); + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; +} + +MACHINE_START(CSB226, "Cogent CSB226 Development Platform") + MAINTAINER("Robert Schwebel, Pengutronix") + BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) + BOOT_PARAMS(0xa0000100) + FIXUP(fixup_csb226) + MAPIO(csb226_map_io) + INITIRQ(csb226_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/dma.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,131 @@ +/* + * linux/arch/arm/mach-pxa/dma.c + * + * PXA DMA registration and IRQ dispatching + * + * Author: Nicolas Pitre + * Created: Nov 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +static struct dma_channel { + char *name; + void (*irq_handler)(int, void *, struct pt_regs *); + void *data; +} dma_channels[16]; + + +int pxa_request_dma (char *name, pxa_dma_prio prio, + void (*irq_handler)(int, void *, struct pt_regs *), + void *data) +{ + unsigned long flags; + int i, found = 0; + + /* basic sanity checks */ + if (!name || !irq_handler) + return -EINVAL; + + local_irq_save(flags); + + /* try grabbing a DMA channel with the requested priority */ + for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) { + if (!dma_channels[i].name) { + found = 1; + break; + } + } + + if (!found) { + /* requested prio group is full, try hier priorities */ + for (i = prio-1; i >= 0; i--) { + if (!dma_channels[i].name) { + found = 1; + break; + } + } + } + + if (found) { + DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + dma_channels[i].name = name; + dma_channels[i].irq_handler = irq_handler; + dma_channels[i].data = data; + } else { + printk (KERN_WARNING "No more available DMA channels for %s\n", name); + i = -ENODEV; + } + + local_irq_restore(flags); + return i; +} + +void pxa_free_dma (int dma_ch) +{ + unsigned long flags; + + if (!dma_channels[dma_ch].name) { + printk (KERN_CRIT __FUNCTION__ + ": trying to free channel %d which is already freed\n", + dma_ch); + return; + } + + local_irq_save(flags); + DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + dma_channels[dma_ch].name = NULL; + local_irq_restore(flags); +} + +static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + int i, dint = DINT; + + for (i = 0; i < 16; i++) { + if (dint & (1 << i)) { + struct dma_channel *channel = &dma_channels[i]; + if (channel->name && channel->irq_handler) { + channel->irq_handler(i, channel->data, regs); + } else { + /* + * IRQ for an unregistered DMA channel: + * let's clear the interrupts and disable it. + */ + printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i); + DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + } + } + } +} + +static int __init pxa_dma_init (void) +{ + int ret; + + ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL); + if (ret) + printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); + return ret; +} + +__initcall(pxa_dma_init); + +EXPORT_SYMBOL(pxa_request_dma); +EXPORT_SYMBOL(pxa_free_dma); + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/generic.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,142 @@ +/* + * linux/arch/arm/mach-pxa/generic.c + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software Inc. + * + * Code common to all PXA machines. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Since this file should be linked before any other machine specific file, + * the __initcall() here will be executed first. This serves as default + * initialization stuff for PXA machines which can be overriden later if + * need be. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "generic.h" + +/* + * Various clock factors driven by the CCCR register. + */ + +/* Crystal Frequency to Memory Frequency Multiplier (L) */ +static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, }; + +/* Memory Frequency to Run Mode Frequency Multiplier (M) */ +static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 }; + +/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */ +/* Note: we store the value N * 2 here. */ +static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 }; + +/* Crystal clock */ +#define BASE_CLK 3686400 + +/* + * Get the clock frequency as reflected by CCCR and the turbo flag. + * We assume these values have been applied via a fcs. + * If info is not 0 we also display the current settings. + */ +unsigned int get_clk_frequency_khz( int info) +{ + unsigned long cccr, turbo; + unsigned int l, L, m, M, n2, N; + + cccr = CCCR; + asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) ); + + l = L_clk_mult[(cccr >> 0) & 0x1f]; + m = M_clk_mult[(cccr >> 5) & 0x03]; + n2 = N2_clk_mult[(cccr >> 7) & 0x07]; + + L = l * BASE_CLK; + M = m * L; + N = n2 * M / 2; + + if( info) + { + L += 5000; + printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n", + L / 1000000, (L % 1000000) / 10000, l ); + M += 5000; + printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n", + M / 1000000, (M % 1000000) / 10000, m ); + N += 5000; + printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n", + N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5, + (turbo & 1) ? "" : "in" ); + } + + return (turbo & 1) ? (N/1000) : (M/1000); +} + +EXPORT_SYMBOL(get_clk_frequency_khz); + +/* + * Return the current lclk requency in units of 10kHz + */ +unsigned int get_lclk_frequency_10khz(void) +{ + return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000; +} + +EXPORT_SYMBOL(get_lclk_frequency_10khz); + +/* + * Handy function to set GPIO alternate functions + */ + +void set_GPIO_mode(int gpio_mode) +{ + long flags; + int gpio = gpio_mode & GPIO_MD_MASK_NR; + int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8; + int gafr; + + local_irq_save(flags); + if (gpio_mode & GPIO_MD_MASK_DIR) + GPDR(gpio) |= GPIO_bit(gpio); + else + GPDR(gpio) &= ~GPIO_bit(gpio); + gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2)); + GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2)); + local_irq_restore(flags); +} + +EXPORT_SYMBOL(set_GPIO_mode); + +/* + * Note that 0xfffe0000-0xffffffff is reserved for the vector table and + * cache flush area. + */ +static struct map_desc standard_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ + { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ + { 0xf8000000, 0x40000000, 0x01800000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */ + { 0xfa000000, 0x44000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */ + { 0xfc000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */ + { 0xff000000, 0x00000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* UNCACHED_PHYS_0 */ + LAST_DESC +}; + +void __init pxa_map_io(void) +{ + iotable_init(standard_io_desc); + get_clk_frequency_khz( 1); +} --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/generic.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,19 @@ +/* + * linux/arch/arm/mach-pxa/generic.h + * + * Author: Nicolas Pitre + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +extern void __init pxa_map_io(void); +extern void __init pxa_init_irq(void); + +#define SET_BANK(__nr,__start,__size) \ + mi->bank[__nr].start = (__start), \ + mi->bank[__nr].size = (__size), \ + mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/idp.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,142 @@ +/* + * linux/arch/arm/mach-pxa/idp.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc. + * + * 2001-09-13: Cliff Brake + * Initial code + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "generic.h" + +#define PXA_IDP_REV02 + +#ifndef PXA_IDP_REV02 +/* shadow registers for write only registers */ +unsigned int idp_cpld_led_control_shadow = 0x1; +unsigned int idp_cpld_periph_pwr_shadow = 0xd; +unsigned int ipd_cpld_cir_shadow = 0; +unsigned int idp_cpld_kb_col_high_shadow = 0; +unsigned int idp_cpld_kb_col_low_shadow = 0; +unsigned int idp_cpld_pccard_en_shadow = 0xC3; +unsigned int idp_cpld_gpioh_dir_shadow = 0; +unsigned int idp_cpld_gpioh_value_shadow = 0; +unsigned int idp_cpld_gpiol_dir_shadow = 0; +unsigned int idp_cpld_gpiol_value_shadow = 0; + +/* + * enable all LCD signals -- they should still be on + * write protect flash + * enable all serial port transceivers + */ + +unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */ + (0x1 << 19) | /* disable flash write enable */ + (0x7 << 9)); /* enable serial port transeivers */ + +#endif + +static int __init idp_init(void) +{ + printk("idp_init()\n"); + return 0; +} + +__initcall(idp_init); + +static void __init idp_init_irq(void) +{ + pxa_init_irq(); +} + +static void __init +fixup_idp(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ +#ifdef PXA_IDP_REV02 + SET_BANK (0, 0xa0000000, 64*1024*1024); +#else + SET_BANK (0, 0xa0000000, 32*1024*1024); +#endif + mi->nr_banks = 1; +#if 0 + setup_ramdisk (1, 0, 0, 8192); + setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024); + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); +#endif +} + +static struct map_desc idp_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + + +#ifndef PXA_IDP_REV02 + { IDP_CTRL_PORT_BASE, + IDP_CTRL_PORT_PHYS, + IDP_CTRL_PORT_SIZE, + DOMAIN_IO, + 0, 1, 0, 0 }, +#endif + + { IDP_IDE_BASE, + IDP_IDE_PHYS, + IDP_IDE_SIZE, + DOMAIN_IO, + 0, 1, 0, 0 }, + { IDP_ETH_BASE, + IDP_ETH_PHYS, + IDP_ETH_SIZE, + DOMAIN_IO, + 0, 1, 0, 0 }, + { IDP_COREVOLT_BASE, + IDP_COREVOLT_PHYS, + IDP_COREVOLT_SIZE, + DOMAIN_IO, + 0, 1, 0, 0 }, + { IDP_CPLD_BASE, + IDP_CPLD_PHYS, + IDP_CPLD_SIZE, + DOMAIN_IO, + 0, 1, 0, 0 }, + + LAST_DESC +}; + +static void __init idp_map_io(void) +{ + pxa_map_io(); + iotable_init(idp_io_desc); + + set_GPIO_IRQ_edge(IRQ_TO_GPIO(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE); + set_GPIO_IRQ_edge(IRQ_TO_GPIO(SMC_IRQ), GPIO_RISING_EDGE); +} + +MACHINE_START(PXA_IDP, "Accelent Xscale IDP") + MAINTAINER("Accelent Systems Inc.") + BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000) + FIXUP(fixup_idp) + MAPIO(idp_map_io) + INITIRQ(idp_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/innokom.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,129 @@ +/* + * linux/arch/arm/mach-pxa/innokom.c + * + * (c) 2003 Robert Schwebel , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + + +static void __init innokom_init_irq(void) +{ + pxa_init_irq(); +} + + +void sw_update_handler( int irq, void* dev_id,struct pt_regs* regs) +{ +} + + +void reset_handler( int irq, void* dev_id,struct pt_regs* regs) +{ +} + + +static int __init innokom_init(void) +{ + int sw_irq = GPIO_2_80_TO_IRQ(11); /* software update button */ + int reset_irq = GPIO_2_80_TO_IRQ(3); /* reset button */ + + set_GPIO_IRQ_edge(11,GPIO_FALLING_EDGE); + if (request_irq(sw_irq,sw_update_handler,SA_INTERRUPT,"software update button",NULL)) + printk(KERN_INFO "innokom: can't get assigned irq %i\n",sw_irq); + + set_GPIO_IRQ_edge(3,GPIO_FALLING_EDGE); + if (request_irq(reset_irq,reset_handler,SA_INTERRUPT,"reset button",NULL)) + printk(KERN_INFO "innokom: can't get assigned irq %i\n",reset_irq); + + return 0; +} + + +__initcall(innokom_init); + + +static void __init +fixup_innokom(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + /* we probably want to get this information from the bootloader later */ + SET_BANK (0, 0xa0000000, 64*1024*1024); + mi->nr_banks = 1; +} + + +/* memory mapping */ +static struct map_desc innokom_io_desc[] __initdata = { +/* virtual physical length domain r w c b */ + { INNOKOM_ETH_BASE, INNOKOM_ETH_PHYS, INNOKOM_ETH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* ETH SMSC 91111 */ + LAST_DESC +}; + +static void __init innokom_map_io(void) +{ + pxa_map_io(); + iotable_init(innokom_io_desc); + + /* Enable the BTUART */ + CKEN |= CKEN7_BTUART; + set_GPIO_mode(GPIO42_BTRXD_MD); + set_GPIO_mode(GPIO43_BTTXD_MD); + set_GPIO_mode(GPIO44_BTCTS_MD); + set_GPIO_mode(GPIO45_BTRTS_MD); + + set_GPIO_mode(GPIO33_nCS_5_MD); /* SMSC network chip */ + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; +} + +MACHINE_START(INNOKOM, "Auerswald Innokom") + MAINTAINER("Robert Schwebel, Pengutronix") + BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) + BOOT_PARAMS(0xa0000100) + FIXUP(fixup_innokom) + MAPIO(innokom_map_io) + INITIRQ(innokom_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/irq.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,282 @@ +/* + * linux/arch/arm/mach-pxa/irq.c + * + * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc. + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "generic.h" + + +/* + * PXA GPIO edge detection for IRQs: + * IRQs are generated on Falling-Edge, Rising-Edge, or both. + * This must be called *before* the appropriate IRQ is registered. + * Use this instead of directly setting GRER/GFER. + */ + +static int GPIO_IRQ_rising_edge[3]; +static int GPIO_IRQ_falling_edge[3]; + +void set_GPIO_IRQ_edge (int gpio_nr, int edge) +{ + long flags; + local_irq_save(flags); + set_GPIO_mode(gpio_nr | GPIO_IN); + if (edge & GPIO_FALLING_EDGE) + set_bit (gpio_nr, GPIO_IRQ_falling_edge); + else + clear_bit (gpio_nr, GPIO_IRQ_falling_edge); + if (edge & GPIO_RISING_EDGE) + set_bit (gpio_nr, GPIO_IRQ_rising_edge); + else + clear_bit (gpio_nr, GPIO_IRQ_rising_edge); + irq_desc[IRQ_GPIO(gpio_nr)].valid = 1; + local_irq_restore(flags); +} + +EXPORT_SYMBOL(set_GPIO_IRQ_edge); + + +/* + * We don't need to ACK IRQs on the PXA unless they're GPIOs + * this is for IRQs known as PXA_IRQ([10...31]). + */ + +static void pxa_mask_irq(unsigned int irq) +{ + ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); +} + +static void pxa_unmask_irq(unsigned int irq) +{ + ICMR |= (1 << (irq + PXA_IRQ_SKIP)); +} + +/* + * GPIO IRQs must be acknoledged. This is for GPIO 0 and 1. + */ + +static void pxa_mask_and_ack_GPIO_0_1_irq(unsigned int irq) +{ + ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); + GEDR0 = (1 << (irq - IRQ_GPIO0)); +} + +static void pxa_mask_GPIO_0_1_irq(unsigned int irq) +{ + ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); +} + +static void pxa_unmask_GPIO_0_1_irq(unsigned int irq) +{ + int gpio = irq - IRQ_GPIO0; + GRER0 = (GRER0 & ~(1 << gpio))|(GPIO_IRQ_rising_edge[0] & (1 << gpio)); + GFER0 = (GFER0 & ~(1 << gpio))|(GPIO_IRQ_falling_edge[0] & (1 << gpio)); + ICMR |= (1 << (irq + PXA_IRQ_SKIP)); +} + +/* + * Demux handler for GPIO 2-80 edge detect interrupts + */ + +static int GPIO_2_80_enabled[3]; /* enabled i.e. unmasked GPIO IRQs */ +static int GPIO_2_80_spurious[3]; /* GPIOs that triggered when masked */ + +static void pxa_GPIO_2_80_demux(int irq, void *dev_id, + struct pt_regs *regs) +{ + int i, gedr, spurious; + + while ((gedr = (GEDR0 & ~3))) { + /* + * We don't want to clear GRER/GFER when the corresponding + * IRQ is masked because we could miss a level transition + * i.e. an IRQ which need servicing as soon as it is + * unmasked. However, such situation should happen only + * during the loop below. Thus all IRQs which aren't + * enabled at this point are considered spurious. Those + * are cleared but only de-activated if they happen twice. + */ + spurious = gedr & ~GPIO_2_80_enabled[0]; + if (spurious) { + GEDR0 = spurious; + GRER0 &= ~(spurious & GPIO_2_80_spurious[0]); + GFER0 &= ~(spurious & GPIO_2_80_spurious[0]); + GPIO_2_80_spurious[0] |= spurious; + gedr ^= spurious; + if (!gedr) continue; + } + + for (i = 2; i < 32; ++i) { + if (gedr & (1<> 5; + GPIO_2_80_spurious[index] &= ~mask; + GPIO_2_80_enabled[index] &= ~mask; + GEDR_x(index) = mask; +} + +static void pxa_mask_GPIO_2_80_irq(unsigned int irq) +{ + int gpio_nr = IRQ_TO_GPIO_2_80(irq); + int mask = 1 << (gpio_nr & 0x1f); + int index = gpio_nr >> 5; + GPIO_2_80_spurious[index] &= ~mask; + GPIO_2_80_enabled[index] &= ~mask; +} + +static void pxa_unmask_GPIO_2_80_irq(unsigned int irq) +{ + int gpio_nr = IRQ_TO_GPIO_2_80(irq); + int mask = 1 << (gpio_nr & 0x1f); + int index = gpio_nr >> 5; + if (GPIO_2_80_spurious[index] & mask) { + /* + * We don't want to miss an interrupt that would have occurred + * while it was masked. Simulate it if it is the case. + */ + int state = GPLR_x(index); + if (((state & GPIO_IRQ_rising_edge[index]) | + (~state & GPIO_IRQ_falling_edge[index])) & mask) + { + /* just in case it gets referenced: */ + struct pt_regs dummy; + + memzero(&dummy, sizeof(dummy)); + do_IRQ(irq, &dummy); + + /* we are being called recursively from do_IRQ() */ + return; + } + } + GPIO_2_80_enabled[index] |= mask; + GRER_x(index) = + (GRER_x(index) & ~mask) | (GPIO_IRQ_rising_edge[index] & mask); + GFER_x(index) = + (GFER_x(index) & ~mask) | (GPIO_IRQ_falling_edge[index] & mask); +} + + +void __init pxa_init_irq(void) +{ + int irq; + + /* disable all IRQs */ + ICMR = 0; + + /* all IRQs are IRQ, not FIQ */ + ICLR = 0; + + /* clear all GPIO edge detects */ + GFER0 = GFER1 = GFER2 = 0; + GRER0 = GRER1 = GRER2 = 0; + GEDR0 = GEDR0; + GEDR1 = GEDR1; + GEDR2 = GEDR2; + + /* only unmasked interrupts kick us out of idle */ + ICCR = 1; + + for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 0; + irq_desc[irq].mask_ack = pxa_mask_irq; + irq_desc[irq].mask = pxa_mask_irq; + irq_desc[irq].unmask = pxa_unmask_irq; + } + + /* + * Note: GPIO IRQs are initially invalid until set_GPIO_IRQ_edge() + * is called at least once. + */ + + for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { + irq_desc[irq].valid = 0; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_0_1_irq; + irq_desc[irq].mask = pxa_mask_GPIO_0_1_irq; + irq_desc[irq].unmask = pxa_unmask_GPIO_0_1_irq; + } + + for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) { + irq_desc[irq].valid = 0; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_2_80_irq; + irq_desc[irq].mask = pxa_mask_GPIO_2_80_irq; + irq_desc[irq].unmask = pxa_unmask_GPIO_2_80_irq; + } + setup_arm_irq( IRQ_GPIO_2_80, &GPIO_2_80_irqaction ); +} --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/leds-cerf.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,135 @@ +/* + * linux/arch/arm/mach-pxa/leds-cerf.c + * + * Copyright (C) 2000 John Dorsey + * + * Copyright (c) 2001 Jeff Sutherland + * + * Original (leds-footbridge.c) by Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#include +#include + +#include +#include +#include + +#include "leds.h" + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void pxa_cerf_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = CERF_HEARTBEAT_LED; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = CERF_HEARTBEAT_LED; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = CERF_HEARTBEAT_LED; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= CERF_HEARTBEAT_LED; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= CERF_SYS_BUSY_LED; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~CERF_SYS_BUSY_LED; + break; +#endif + + case led_halted: + break; + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~CERF_HEARTBEAT_LED; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= CERF_HEARTBEAT_LED; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + +#ifndef CONFIG_PXA_CERF_PDA + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~CERF_SYS_BUSY_LED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= CERF_SYS_BUSY_LED; + break; +#endif + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + { + switch (hw_led_state) { + case 0: // all on + CERF_HEARTBEAT_LED_ON; + CERF_SYS_BUSY_LED_ON; + break; + case 1: // turn off heartbeat, status on: + CERF_HEARTBEAT_LED_OFF; + CERF_SYS_BUSY_LED_ON; + break; + case 2: // status off, heartbeat on: + CERF_HEARTBEAT_LED_ON; + CERF_SYS_BUSY_LED_OFF; + break; + case 3: // turn them both off... + CERF_HEARTBEAT_LED_OFF; + CERF_SYS_BUSY_LED_OFF; + break; + default: + break; + } + } + local_irq_restore(flags); +} --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/leds-idp.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,112 @@ +/* + * linux/arch/arm/mach-pxa/leds-idp.c + * + * Copyright (C) 2000 John Dorsey + * + * Copyright (c) 2001 Jeff Sutherland + * + * Original (leds-footbridge.c) by Russell King + * + * Macros for actual LED manipulation should be in machine specific + * files in this 'mach' directory. + */ + + +#include +#include + +#include +#include +#include + +#include "leds.h" + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void idp_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = IDP_HB_LED | IDP_BUSY_LED; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = IDP_HB_LED | IDP_BUSY_LED; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = IDP_HB_LED | IDP_BUSY_LED; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= IDP_HB_LED; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= IDP_BUSY_LED; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~IDP_BUSY_LED; + break; +#endif + + case led_halted: + break; + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~IDP_HB_LED; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= IDP_HB_LED; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~IDP_BUSY_LED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= IDP_BUSY_LED; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + IDP_WRITE_LEDS(hw_led_state); + + local_irq_restore(flags); +} --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/leds-lubbock.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,134 @@ +/* + * linux/arch/arm/mach-pxa/leds-lubbock.c + * + * Copyright (C) 2000 John Dorsey + * + * Copyright (c) 2001 Jeff Sutherland + * + * Original (leds-footbridge.c) by Russell King + * + * See leds.h for bit definitions. The first version defines D28 on the + * Lubbock dev board as the heartbeat, and D27 as the Sys_busy led. + * There's plenty more if you're interested in adding them :) + */ + + +#include +#include + +#include +#include +#include + +#include "leds.h" + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void lubbock_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= HEARTBEAT_LED; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= SYS_BUSY_LED; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~SYS_BUSY_LED; + break; +#endif + + case led_halted: + break; + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~HEARTBEAT_LED; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= HEARTBEAT_LED; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~SYS_BUSY_LED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= SYS_BUSY_LED; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + { + switch (hw_led_state) { + case 0: // all on + HEARTBEAT_LED_ON; + SYS_BUSY_LED_ON; + break; + case 1: // turn off heartbeat, status on: + HEARTBEAT_LED_OFF; + SYS_BUSY_LED_ON; + break; + case 2: // status off, heartbeat on: + HEARTBEAT_LED_ON; + SYS_BUSY_LED_OFF; + break; + case 3: // turn them both off... + HEARTBEAT_LED_OFF; + SYS_BUSY_LED_OFF; + break; + default: + break; + } + } + local_irq_restore(flags); +} --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/leds.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,32 @@ +/* + * linux/arch/arm/mach-pxa/leds.c + * + * xscale LEDs dispatcher + * + * Copyright (C) 2001 Nicolas Pitre + * + * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc. + */ +#include +#include + +#include +#include + +#include "leds.h" + +static int __init +pxa_leds_init(void) +{ + if (machine_is_lubbock()) + leds_event = lubbock_leds_event; + if (machine_is_pxa_idp()) + leds_event = idp_leds_event; + if (machine_is_pxa_cerf()) + leds_event = pxa_cerf_leds_event; + + leds_event(led_start); + return 0; +} + +__initcall(pxa_leds_init); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/leds.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,12 @@ +/* + * include/asm-arm/arch-pxa/leds.h + * + * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc. + * + * blinky lights for various PXA-based systems: + * + */ + +extern void lubbock_leds_event(led_event_t evt); +extern void idp_leds_event(led_event_t evt); +extern void pxa_cerf_leds_event(led_event_t evt); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/lubbock.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,157 @@ +/* + * linux/arch/arm/mach-pxa/lubbock.c + * + * Support for the Intel DBPXA250 Development Platform. + * + * Author: Nicolas Pitre + * Created: Jun 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + +#ifdef CONFIG_SA1111 + #include "sa1111.h" +#endif + + +static unsigned long lubbock_irq_enabled; + +static void lubbock_mask_irq(unsigned int irq) +{ + int lubbock_irq = (irq - LUBBOCK_IRQ(0)); + LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq)); +} + +static void lubbock_unmask_irq(unsigned int irq) +{ + int lubbock_irq = (irq - LUBBOCK_IRQ(0)); + /* the irq can be acknowledged only if deasserted, so it's done here */ + LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq); + LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq)); +} + +void lubbock_irq_demux(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; + do { + GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ + if (likely(pending)) + do_IRQ( LUBBOCK_IRQ(0) + __ffs(pending), regs ); + pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; + } while (pending); +} + +static struct irqaction lubbock_irq = { + name: "Lubbock FPGA", + handler: lubbock_irq_demux, + flags: SA_INTERRUPT +}; + +static void __init lubbock_init_irq(void) +{ + int irq; + + pxa_init_irq(); + + /* setup extra lubbock irqs */ + for(irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = lubbock_mask_irq; + irq_desc[irq].mask = lubbock_mask_irq; + irq_desc[irq].unmask = lubbock_unmask_irq; + } + + set_GPIO_IRQ_edge(GPIO_LUBBOCK_IRQ, GPIO_FALLING_EDGE); + setup_arm_irq(IRQ_GPIO_LUBBOCK_IRQ, &lubbock_irq); +} + +static int __init lubbock_init(void) +{ + int ret; + + ret = sa1111_probe(LUBBOCK_SA1111_BASE); + if (ret) + return ret; + sa1111_wake(); + sa1111_init_irq(LUBBOCK_SA1111_IRQ); + return 0; +} + +__initcall(lubbock_init); + +static void __init +fixup_lubbock(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + /* Some boards have 32MB some 64MB. Let's use a safe default */ + SET_BANK (0, 0xa0000000, 32*1024*1024); + mi->nr_banks = 1; +} + +static struct map_desc lubbock_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ + { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */ + { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */ + { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */ + LAST_DESC +}; + +static void __init lubbock_map_io(void) +{ + pxa_map_io(); + iotable_init(lubbock_io_desc); + + /* This enables the BTUART */ + CKEN |= CKEN7_BTUART; + set_GPIO_mode(GPIO42_BTRXD_MD); + set_GPIO_mode(GPIO43_BTTXD_MD); + set_GPIO_mode(GPIO44_BTCTS_MD); + set_GPIO_mode(GPIO45_BTRTS_MD); + + /* This is for the SMC chip select */ + set_GPIO_mode(GPIO79_nCS_3_MD); + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; +} + +MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform") + MAINTAINER("MontaVista Software Inc.") + BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) + FIXUP(fixup_lubbock) + MAPIO(lubbock_map_io) + INITIRQ(lubbock_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/pm.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,265 @@ +/* + * PXA250/210 Power Management Routines + * + * Original code for the SA11x0: + * Copyright (c) 2001 Cliff Brake + * + * Modified for the PXA250 by Nicolas Pitre: + * Copyright (c) 2002 Monta Vista Software, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* + * Debug macros + */ +#undef DEBUG + +extern void pxa_cpu_suspend(void); +extern void pxa_cpu_resume(void); + +#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x +#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] + +/* + * List of global PXA peripheral registers to preserve. + * More ones like CP and general purpose register values are preserved + * with the stack pointer in sleep.S. + */ +enum { SLEEP_SAVE_START = 0, + + SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, + SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, + + SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, + SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, + SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, + SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L, + SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U, + + SLEEP_SAVE_FFIER, SLEEP_SAVE_FFLCR, SLEEP_SAVE_FFMCR, + SLEEP_SAVE_FFSPR, SLEEP_SAVE_FFISR, + SLEEP_SAVE_FFDLL, SLEEP_SAVE_FFDLH, + + SLEEP_SAVE_ICMR, + SLEEP_SAVE_CKEN, + + SLEEP_SAVE_CKSUM, + + SLEEP_SAVE_SIZE +}; + + +int pm_do_suspend(void) +{ + unsigned long sleep_save[SLEEP_SAVE_SIZE]; + unsigned long checksum = 0; + int i; + + cli(); + clf(); + + leds_event(led_stop); + + /* preserve current time */ + RCNR = xtime.tv_sec; + + /* + * Temporary solution. This won't be necessary once + * we move pxa support into the serial/* driver + * Save the FF UART + */ + SAVE(FFIER); + SAVE(FFLCR); + SAVE(FFMCR); + SAVE(FFSPR); + SAVE(FFISR); + FFLCR |= 0x80; + SAVE(FFDLL); + SAVE(FFDLH); + FFLCR &= 0xef; + + /* save vital registers */ + SAVE(OSCR); + SAVE(OSMR0); + SAVE(OSMR1); + SAVE(OSMR2); + SAVE(OSMR3); + SAVE(OIER); + + SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); + SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); + SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); + SAVE(GAFR0_L); SAVE(GAFR0_U); + SAVE(GAFR1_L); SAVE(GAFR1_U); + SAVE(GAFR2_L); SAVE(GAFR2_U); + + SAVE(ICMR); + ICMR = 0; + + SAVE(CKEN); + CKEN = 0; + + /* Note: wake up source are set up in each machine specific files */ + + /* clear GPIO transition detect bits */ + GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; + + /* Clear sleep reset status */ + RCSR = RCSR_SMR; + + /* set resume return address */ + PSPR = virt_to_phys(pxa_cpu_resume); + + /* before sleeping, calculate and save a checksum */ + for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) + checksum += sleep_save[i]; + sleep_save[SLEEP_SAVE_CKSUM] = checksum; + + /* *** go zzz *** */ + pxa_cpu_suspend(); + + /* after sleeping, validate the checksum */ + checksum = 0; + for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) + checksum += sleep_save[i]; + + /* if invalid, display message and wait for a hardware reset */ + if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { +#ifdef CONFIG_ARCH_LUBBOCK + LUB_HEXLED = 0xbadbadc5; +#endif + while (1); + } + + /* ensure not to come back here if it wasn't intended */ + PSPR = 0; + + /* restore registers */ + RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); + RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); + RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); + RESTORE(GAFR0_L); RESTORE(GAFR0_U); + RESTORE(GAFR1_L); RESTORE(GAFR1_U); + RESTORE(GAFR2_L); RESTORE(GAFR2_U); + + PSSR = PSSR_PH; + + RESTORE(OSMR0); + RESTORE(OSMR1); + RESTORE(OSMR2); + RESTORE(OSMR3); + RESTORE(OSCR); + RESTORE(OIER); + + RESTORE(CKEN); + + ICLR = 0; + ICCR = 1; + RESTORE(ICMR); + + /* + * Temporary solution. This won't be necessary once + * we move pxa support into the serial/* driver. + * Restore the FF UART. + */ + RESTORE(FFMCR); + RESTORE(FFSPR); + RESTORE(FFLCR); + FFLCR |= 0x80; + RESTORE(FFDLH); + RESTORE(FFDLL); + RESTORE(FFLCR); + RESTORE(FFISR); + FFFCR = 0x07; + RESTORE(FFIER); + + /* restore current time */ + xtime.tv_sec = RCNR; + +#ifdef DEBUG + printk(KERN_DEBUG "*** made it back from resume\n"); +#endif + + leds_event(led_start); + + sti(); + + return 0; +} + +unsigned long sleep_phys_sp(void *sp) +{ + return virt_to_phys(sp); +} + +#ifdef CONFIG_SYSCTL +/* + * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than + * linux/sysctl.h. + * + * This means our interface here won't survive long - it needs a new + * interface. Quick hack to get this working - use sysctl id 9999. + */ +#warning ACPI broke the kernel, this interface needs to be fixed up. +#define CTL_ACPI 9999 +#define ACPI_S1_SLP_TYP 19 + +/* + * Send us to sleep. + */ +static int sysctl_pm_do_suspend(void) +{ + int retval; + + retval = pm_send_all(PM_SUSPEND, (void *)3); + + if (retval == 0) { + retval = pm_do_suspend(); + + pm_send_all(PM_RESUME, (void *)0); + } + + return retval; +} + +static struct ctl_table pm_table[] = +{ + {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend}, + {0} +}; + +static struct ctl_table pm_dir_table[] = +{ + {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, + {0} +}; + +/* + * Initialize power interface + */ +static int __init pm_init(void) +{ + register_sysctl_table(pm_dir_table, 1); + return 0; +} + +__initcall(pm_init); + +#endif --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/pxa_usb.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,230 @@ +/* + * pxa_usb.h + * + * Public interface to the pxa USB core. For use by client modules + * like usb-eth and usb-char. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - derived from sa1100_usb.h + * + */ + +#ifndef _PXA_USB_H +#define _PXA_USB_H +#include + +typedef void (*usb_callback_t)(int flag, int size); + +/* in usb_ctl.c (see also descriptor methods at bottom of file) */ + +// Open the USB client for client and initialize data structures +// to default values, but _do not_ start UDC. +int pxa_usb_open( const char * client_name ); + +// Start UDC running +int pxa_usb_start( void ); + +// Immediately stop udc, fire off completion routines w/-EINTR +int pxa_usb_stop( void ) ; + +// Disconnect client from usb core +int pxa_usb_close( void ) ; + +// set notify callback for when core reaches configured state +// return previous pointer (if any) +typedef void (*usb_notify_t)(void); +usb_notify_t pxa_set_configured_callback( usb_notify_t callback ); + +/* in usb_send.c */ +int pxa_usb_xmitter_avail( void ); +int pxa_usb_send(char *buf, int len, usb_callback_t callback); +void sa110a_usb_send_reset(void); + +/* in usb_recev.c */ +int pxa_usb_recv(char *buf, int len, usb_callback_t callback); +void pxa_usb_recv_reset(void); + +////////////////////////////////////////////////////////////////////////////// +// Descriptor Management +////////////////////////////////////////////////////////////////////////////// + +#define DescriptorHeader \ + __u8 bLength; \ + __u8 bDescriptorType + + +// --- Device Descriptor ------------------- + +typedef struct { + DescriptorHeader; + __u16 bcdUSB; /* USB specification revision number in BCD */ + __u8 bDeviceClass; /* USB class for entire device */ + __u8 bDeviceSubClass; /* USB subclass information for entire device */ + __u8 bDeviceProtocol; /* USB protocol information for entire device */ + __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */ + __u16 idVendor; /* USB vendor ID */ + __u16 idProduct; /* USB product ID */ + __u16 bcdDevice; /* vendor assigned device release number */ + __u8 iManufacturer; /* index of manufacturer string */ + __u8 iProduct; /* index of string that describes product */ + __u8 iSerialNumber; /* index of string containing device serial number */ + __u8 bNumConfigurations; /* number fo configurations */ +} __attribute__ ((packed)) device_desc_t; + +// --- Configuration Descriptor ------------ + +typedef struct { + DescriptorHeader; + __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */ + __u8 bNumInterfaces; /* number of interfaces in this cfg */ + __u8 bConfigurationValue; /* used to uniquely ID this cfg */ + __u8 iConfiguration; /* index of string describing configuration */ + __u8 bmAttributes; /* bitmap of attributes for ths cfg */ + __u8 MaxPower; /* power draw in 2ma units */ +} __attribute__ ((packed)) config_desc_t; + +// bmAttributes: +enum { + USB_CONFIG_REMOTEWAKE=0x20, + USB_CONFIG_SELFPOWERED=0x40, + USB_CONFIG_BUSPOWERED=0x80 +}; + +// MaxPower: +#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */ + +// --- Interface Descriptor --------------- + +typedef struct { + DescriptorHeader; + __u8 bInterfaceNumber; /* Index uniquely identfying this interface */ + __u8 bAlternateSetting; /* ids an alternate setting for this interface */ + __u8 bNumEndpoints; /* number of endpoints in this interface */ + __u8 bInterfaceClass; /* USB class info applying to this interface */ + __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */ + __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */ + __u8 iInterface; /* index of string describing interface */ +} __attribute__ ((packed)) intf_desc_t; + +// --- Endpoint Descriptor --------------- + +typedef struct { + DescriptorHeader; + __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */ + __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */ + __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */ + __u8 bInterval; /* polling interval for this ep in this cfg */ +} __attribute__ ((packed)) ep_desc_t; + +// bEndpointAddress: +enum { + USB_OUT =0, + USB_IN =1 +}; + +#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7)) +// bmAttributes: +enum { + USB_EP_CNTRL =0, + USB_EP_BULK =2, + USB_EP_INT =3, + USB_EP_ISO =4 +}; + +// --- String Descriptor ------------------- + +typedef struct { + DescriptorHeader; + __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */ +} __attribute__ ((packed)) string_desc_t; + +/*======================================================= + * Handy helpers when working with above + * + */ +// these are x86-style 16 bit "words" ... +#define make_word_c( w ) __constant_cpu_to_le16(w) +#define make_word( w ) __cpu_to_le16(w) + +// descriptor types +enum { + USB_DESC_DEVICE = 1, + USB_DESC_CONFIG = 2, + USB_DESC_STRING = 3, + USB_DESC_INTERFACE = 4, + USB_DESC_ENDPOINT = 5 +}; + + +/*======================================================= + * Default descriptor layout for SA-1100 and SA-1110 UDC + */ + +enum { + UNUSED = 0, + + BULK_IN1 = 1, + BULK_OUT1 = 2, + ISO_IN1 = 3, + ISO_OUT1 = 4, + INT_IN1 = 5, + + BULK_IN2 = 6, + BULK_OUT2 = 7, + ISO_IN2 = 8, + ISO_OUT2 = 9, + INT_IN2 = 10, + + BULK_IN3 = 11, + BULK_OUT3 = 12, + ISO_IN3 = 13, + ISO_OUT3 = 14, + INT_IN3 = 15 +} /*endpoint_type*/; + +/* "config descriptor buffer" - that is, one config, + ..one interface and 2 endpoints */ +struct cdb { + config_desc_t cfg; + intf_desc_t intf; + ep_desc_t ep1; + ep_desc_t ep2; +} __attribute__ ((packed)); + +/* all SA device descriptors */ +typedef struct { + device_desc_t dev; /* device descriptor */ + struct cdb b; /* bundle of descriptors for this cfg */ +} __attribute__ ((packed)) desc_t; + + +/*======================================================= + * Descriptor API + */ + +/* Get the address of the statically allocated desc_t structure + in the usb core driver. Clients can modify this between + the time they call pxa_usb_open() and pxa_usb_start() +*/ +desc_t * +pxa_usb_get_descriptor_ptr( void ); + + +/* Set a pointer to the string descriptor at "index". The driver + ..has room for 8 string indicies internally. Index zero holds + ..a LANGID code and is set to US English by default. Inidices + ..1-7 are available for use in the config descriptors as client's + ..see fit. This pointer is assumed to be good as long as the + ..SA usb core is open (so statically allocate them). Returnes -EINVAL + ..if index out of range */ +int pxa_usb_set_string_descriptor( int index, string_desc_t * p ); + +/* reverse of above */ +string_desc_t * +pxa_usb_get_string_descriptor( int index ); + +/* kmalloc() a string descriptor and convert "p" to unicode in it */ +string_desc_t * +pxa_usb_kmalloc_string_descriptor( const char * p ); + +#endif /* _PXA_USB_H */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/sa1111.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,3 @@ +#include "../mach-sa1100/sa1111.c" + + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/sa1111.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,2 @@ +#include "../mach-sa1100/sa1111.h" + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/sleep.S 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,150 @@ +/* + * Low-level PXA250/210 sleep/wakeUp support + * + * Initial SA1110 code: + * Copyright (c) 2001 Cliff Brake + * + * Adapted for PXA by Nicolas Pitre: + * Copyright (c) 2002 Monta Vista Software, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License. + */ + +#include +#include +#include +#include + + .text + +/* + * pxa_cpu_suspend() + * + * Forces CPU into sleep state + */ + +ENTRY(pxa_cpu_suspend) + + mra r2, r3, acc0 + stmfd sp!, {r2 - r12, lr} @ save registers on stack + + @ get coprocessor registers + mrc p15, 0, r4, c15, c1, 0 @ CP access reg + mrc p15, 0, r5, c13, c0, 0 @ PID + mrc p15, 0, r6, c3, c0, 0 @ domain ID + mrc p15, 0, r7, c2, c0, 0 @ translation table base addr + mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg + + @ store them plus current virtual stack ptr on stack + mov r10, sp + stmfd sp!, {r4 - r10} + + @ preserve phys address of stack + mov r0, sp + bl sleep_phys_sp + ldr r1, =sleep_save_sp + str r0, [r1] + + @ clean data cache + bl cpu_xscale_cache_clean_invalidate_all + + @ Put the processor to sleep + @ (also workaround for sighting 28071) + + @ prepare value for sleep mode + mov r1, #3 @ sleep mode + + @ prepare to put SDRAM into self-refresh manually + ldr r4, =MDREFR + ldr r5, [r4] + orr r5, r5, #MDREFR_SLFRSH + + @ prepare pointer to physical address 0 (virtual mapping in generic.c) + mov r2, #UNCACHED_PHYS_0 + + @ align execution to a cache line + b 1f + + .ltorg + .align 5 +1: + + @ All needed values are now in registers. + @ These last instructions should be in cache + + @ put SDRAM into self-refresh + str r5, [r4] + + @ force address lines low by reading at physical address 0 + ldr r3, [r2] + + @ enter sleep mode + mcr p14, 0, r1, c7, c0, 0 + +20: nop + b 20b @ loop waiting for sleep + +/* + * cpu_pxa_resume() + * + * entry point from bootloader into kernel during resume + * + * Note: Yes, part of the following code is located into the .data section. + * This is to allow sleep_save_sp to be accessed with a relative load + * while we can't rely on any MMU translation. We could have put + * sleep_save_sp in the .text section as well, but some setups might + * insist on it to be truely read-only. + */ + + .data + .align 5 +ENTRY(pxa_cpu_resume) + mov r0, #I_BIT | F_BIT | MODE_SVC @ set SVC, irqs off + msr cpsr_c, r0 + + ldr r0, sleep_save_sp @ stack phys addr + ldr r2, =resume_after_mmu @ its absolute virtual address + ldmfd r0, {r4 - r9, sp} @ CP regs + virt stack ptr + + mov r1, #0 + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs + mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB + +#ifdef CONFIG_XSCALE_CACHE_ERRATA + bic r9, r9, #0x0004 @ see cpu_xscale_proc_init +#endif + + mcr p15, 0, r4, c15, c1, 0 @ CP access reg + mcr p15, 0, r5, c13, c0, 0 @ PID + mcr p15, 0, r6, c3, c0, 0 @ domain ID + mcr p15, 0, r7, c2, c0, 0 @ translation table base addr + mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg + b resume_turn_on_mmu @ cache align execution + + .align 5 +resume_turn_on_mmu: + mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, caches, etc. + + @ Let us ensure we jump to resume_after_mmu only when the mcr above + @ actually took effect. They call it the "cpwait" operation. + mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15 + sub pc, r2, r1, lsr #32 @ jump to virtual addr + nop + nop + nop + +sleep_save_sp: + .word 0 @ preserve stack phys ptr here + + .text +resume_after_mmu: +#ifdef CONFIG_XSCALE_CACHE_ERRATA + bl cpu_xscale_proc_init +#endif + ldmfd sp!, {r2, r3} + mar acc0, r2, r3 + ldmfd sp!, {r4 - r12, pc} @ return to caller + + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/trizeps2.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,105 @@ +/* + * linux/arch/arm/mach-pxa/trizeps2.c + * + * Support for the Keith&Koep MT6N Development Platform. + * + * Author: Luc De Cock + * Created: Jan 13, 2003 + * Copyright: Teradyne DS, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "generic.h" + +static unsigned long trizeps2_irq_en_mask; +unsigned short trizeps2_bcr_shadow = 0x50; // 0x70 + + +static void __init trizeps2_init_irq(void) +{ + int irq; + + pxa_init_irq(); + + set_GPIO_IRQ_edge(GPIO_ETHERNET_IRQ, GPIO_RISING_EDGE); +} + +static int __init trizeps2_init(void) +{ + /* Configure the BCR register */ + unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE; + + *bcr = trizeps2_bcr_shadow; + return 0; +} + +__initcall(trizeps2_init); + +static void __init +fixup_trizeps2(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ +#ifdef TRIZEPS2_MEM_64MB + SET_BANK (0, 0xa0000000, 64*1024*1024); +#else + SET_BANK (0, 0xa0000000, 32*1024*1024); +#endif + mi->nr_banks = 1; +} + +static struct map_desc trizeps2_io_desc[] __initdata = { + /* virtual physical length domain r w c b */ + { 0xf0000000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* BCR */ + { 0xf0100000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA STATUS */ + { 0xf1000000, 0x0c800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */ + { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */ + { 0xf2000000, 0x0d800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* TTL-IO */ + LAST_DESC +}; + +static void __init trizeps2_map_io(void) +{ + pxa_map_io(); + iotable_init(trizeps2_io_desc); + + /* This is for the SMC chip select */ + set_GPIO_mode(GPIO79_nCS_3_MD); + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; +} + +MACHINE_START(TRIZEPS2, "Keith-n-Koep MT6N Development Platform") + MAINTAINER("Luc De Cock") + BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) + FIXUP(fixup_trizeps2) + MAPIO(trizeps2_map_io) + INITIRQ(trizeps2_init_irq) +MACHINE_END --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb-char.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,719 @@ +/* + * (C) Copyright 2000-2001 Extenex Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * usb-char.c + * + * Miscellaneous character device interface for SA1100 USB function + * driver. + * + * Background: + * The SA1100 function driver ported from the Compaq Itsy project + * has an interface, usb-eth.c, to feed network packets over the + * usb wire and into the Linux TCP/IP stack. + * + * This file replaces that one with a simple character device + * interface that allows unstructured "byte pipe" style reads and + * writes over the USB bulk endpoints by userspace programs. + * + * A new define, CONFIG_SA1100_USB_NETLINK, has been created that, + * when set, (the default) causes the ethernet interface to be used. + * When not set, this more pedestrian character interface is linked + * in instead. + * + * Please see linux/Documentation/arm/SA1100/SA1100_USB for details. + * + * ward.willats@extenex.com + * + * To do: + * - Can't dma into ring buffer directly with pci_map/unmap usb_recv + * uses and get bytes out at the same time DMA is going on. Investigate: + * a) changing usb_recv to use alloc_consistent() at client request; or + * b) non-ring-buffer based data structures. In the meantime, I am using + * a bounce buffer. Simple, but wasteful. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "usb-char.h" +#include "pxa_usb.h" + + + +////////////////////////////////////////////////////////////////////////////// +// Driver Options +////////////////////////////////////////////////////////////////////////////// + +#define VERSION "0.4" + + +#define VERBOSITY 1 + +#if VERBOSITY +# define PRINTK(x, a...) printk (x, ## a) +#else +# define PRINTK(x, a...) /**/ +#endif + +////////////////////////////////////////////////////////////////////////////// +// Globals - Macros - Enums - Structures +////////////////////////////////////////////////////////////////////////////// +#ifndef MIN +#define MIN( a, b ) ((a)<(b)?(a):(b)) +#endif + +typedef int bool; enum { false = 0, true = 1 }; + +static const char pszMe[] = "usbchr: "; + +static wait_queue_head_t wq_read; +static wait_queue_head_t wq_write; +static wait_queue_head_t wq_poll; + +/* Serialze multiple writers onto the transmit hardware +.. since we sleep the writer during transmit to stay in +.. sync. (Multiple writers don't make much sense, but..) */ +static DECLARE_MUTEX( xmit_sem ); + +// size of usb DATA0/1 packets. 64 is standard maximum +// for bulk transport, though most hosts seem to be able +// to handle larger. +#define TX_PACKET_SIZE 64 +#define RX_PACKET_SIZE 64 +#define RBUF_SIZE (4*PAGE_SIZE) + +static struct wcirc_buf { + char *buf; + int in; + int out; +} rx_ring = { NULL, 0, 0 }; + +static struct { + unsigned long cnt_rx_complete; + unsigned long cnt_rx_errors; + unsigned long bytes_rx; + unsigned long cnt_tx_timeouts; + unsigned long cnt_tx_errors; + unsigned long bytes_tx; +} charstats; + + +static char * tx_buf = NULL; +static char * packet_buffer = NULL; +static int sending = 0; +static int usb_ref_count = 0; +static int last_tx_result = 0; +static int last_rx_result = 0; +static int last_tx_size = 0; +static struct timer_list tx_timer; + +////////////////////////////////////////////////////////////////////////////// +// Prototypes +////////////////////////////////////////////////////////////////////////////// +static char * what_the_f( int e ); +static void free_txrx_buffers( void ); +static void twiddle_descriptors( void ); +static void free_string_descriptors( void ) ; +static int usbc_open( struct inode *pInode, struct file *pFile ); +static void rx_done_callback_packet_buffer( int flag, int size ); + +static void tx_timeout( unsigned long ); +static void tx_done_callback( int flag, int size ); + +static ssize_t usbc_read( struct file *, char *, size_t, loff_t * ); +static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * ); +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ); +static int usbc_ioctl( struct inode *pInode, struct file *pFile, + unsigned int nCmd, unsigned long argument ); +static int usbc_close( struct inode *pInode, struct file *pFile ); + +#ifdef CONFIG_SA1100_EXTENEX1 +static void extenex_configured_notify_proc( void ); +#endif +////////////////////////////////////////////////////////////////////////////// +// Private Helpers +////////////////////////////////////////////////////////////////////////////// + +static char * what_the_f( int e ) +{ + char * p; + switch( e ) { + case 0: + p = "noErr"; + break; + case -ENODEV: + p = "ENODEV - usb not in config state"; + break; + case -EBUSY: + p = "EBUSY - another request on the hardware"; + break; + case -EAGAIN: + p = "EAGAIN"; + break; + case -EINTR: + p = "EINTR - interrupted\n"; + break; + case -EPIPE: + p = "EPIPE - zero length xfer\n"; + break; + default: + p = "????"; + break; + } + return p; +} + +static void free_txrx_buffers( void ) +{ + if ( rx_ring.buf != NULL ) { + kfree( rx_ring.buf ); + rx_ring.buf = NULL; + } + if ( packet_buffer != NULL ) { + kfree( packet_buffer ); + packet_buffer = NULL; + } + if ( tx_buf != NULL ) { + kfree( tx_buf ); + tx_buf = NULL; + } +} + +/* twiddle_descriptors() + * It is between open() and start(). Setup descriptors. + */ +static void twiddle_descriptors( void ) +{ + desc_t * pDesc = pxa_usb_get_descriptor_ptr(); + string_desc_t * pString; + + pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE ); + pDesc->b.ep1.bmAttributes = USB_EP_BULK; + pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE ); + pDesc->b.ep2.bmAttributes = USB_EP_BULK; + + if ( machine_is_extenex1() ) { +#ifdef CONFIG_SA1100_EXTENEX1 + pDesc->dev.idVendor = make_word_c( 0xC9F ); + pDesc->dev.idProduct = 1; + pDesc->dev.bcdDevice = make_word_c( 0x0001 ); + pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED; + pDesc->b.cfg.MaxPower = 0; + + pString = pxa_usb_kmalloc_string_descriptor( "Extenex" ); + if ( pString ) { + pxa_usb_set_string_descriptor( 1, pString ); + pDesc->dev.iManufacturer = 1; + } + + pString = pxa_usb_kmalloc_string_descriptor( "Handheld Theater" ); + if ( pString ) { + pxa_usb_set_string_descriptor( 2, pString ); + pDesc->dev.iProduct = 2; + } + + pString = pxa_usb_kmalloc_string_descriptor( "00000000" ); + if ( pString ) { + pxa_usb_set_string_descriptor( 3, pString ); + pDesc->dev.iSerialNumber = 3; + } + + pString = pxa_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" ); + if ( pString ) { + pxa_usb_set_string_descriptor( 4, pString ); + pDesc->b.intf.iInterface = 4; + } + pxa_set_configured_callback( extenex_configured_notify_proc ); +#endif + } +} + +static void free_string_descriptors( void ) +{ + if ( machine_is_extenex1() ) { + string_desc_t * pString; + int i; + for( i = 1 ; i <= 4 ; i++ ) { + pString = pxa_usb_get_string_descriptor( i ); + if ( pString ) + kfree( pString ); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// ASYNCHRONOUS +////////////////////////////////////////////////////////////////////////////// +static void kick_start_rx( void ) +{ + if ( usb_ref_count ) { + int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE ); + if ( total_space >= RX_PACKET_SIZE ) { + pxa_usb_recv( packet_buffer, + RX_PACKET_SIZE, + rx_done_callback_packet_buffer + ); + } + } +} +/* + * rx_done_callback_packet_buffer() + * We have completed a DMA xfer into the temp packet buffer. + * Move to ring. + * + * flag values: + * on init, -EAGAIN + * on reset, -EINTR + * on RPE, -EIO + * on short packet -EPIPE + */ +static void +rx_done_callback_packet_buffer( int flag, int size ) +{ + charstats.cnt_rx_complete++; + + if ( flag == 0 || flag == -EPIPE ) { + size_t n; + + charstats.bytes_rx += size; + + n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); + n = MIN( n, size ); + size -= n; + + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n ); + rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1); + memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size ); + rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1); + + wake_up_interruptible( &wq_read ); + wake_up_interruptible( &wq_poll ); + + last_rx_result = 0; + + kick_start_rx(); + + } else if ( flag != -EAGAIN ) { + charstats.cnt_rx_errors++; + last_rx_result = flag; + wake_up_interruptible( &wq_read ); + wake_up_interruptible( &wq_poll ); + } + else /* init, start a read */ + kick_start_rx(); +} + + +static void tx_timeout( unsigned long unused ) +{ + printk( "%stx timeout\n", pszMe ); + pxa_usb_send_reset(); + charstats.cnt_tx_timeouts++; +} + + +// on init, -EAGAIN +// on reset, -EINTR +// on TPE, -EIO +static void tx_done_callback( int flags, int size ) +{ + if ( flags == 0 ) + charstats.bytes_tx += size; + else + charstats.cnt_tx_errors++; + last_tx_size = size; + last_tx_result = flags; + sending = 0; + wake_up_interruptible( &wq_write ); + wake_up_interruptible( &wq_poll ); +} + + +////////////////////////////////////////////////////////////////////////////// +// Workers +////////////////////////////////////////////////////////////////////////////// + +static int usbc_open( struct inode *pInode, struct file *pFile ) +{ + int retval = 0; + + PRINTK( KERN_DEBUG "%sopen()\n", pszMe ); + + /* start usb core */ + retval = pxa_usb_open( "usb-char" ); + if ( retval ) return retval; + + /* allocate memory */ + if ( usb_ref_count == 0 ) { + tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); + if ( tx_buf == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe ); + goto malloc_fail; + } + rx_ring.buf = + (char*) kmalloc( RBUF_SIZE, GFP_KERNEL ); + + if ( rx_ring.buf == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe ); + goto malloc_fail; + } + + packet_buffer = + (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA ); + + if ( packet_buffer == NULL ) { + printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe ); + goto malloc_fail; + } + rx_ring.in = rx_ring.out = 0; + memset( &charstats, 0, sizeof( charstats ) ); + sending = 0; + last_tx_result = 0; + last_tx_size = 0; + } + + /* modify default descriptors */ + twiddle_descriptors(); + + retval = pxa_usb_start(); + if ( retval ) { + printk( "%sAGHH! Could not USB core\n", pszMe ); + free_txrx_buffers(); + return retval; + } + usb_ref_count++; /* must do _before_ kick_start() */ + MOD_INC_USE_COUNT; + kick_start_rx(); + return 0; + + malloc_fail: + free_txrx_buffers(); + return -ENOMEM; +} + +/* + * Read endpoint. Note that you can issue a read to an + * unconfigured endpoint. Eventually, the host may come along + * and configure underneath this module and data will appear. + */ +static ssize_t usbc_read( struct file *pFile, char *pUserBuffer, + size_t stCount, loff_t *pPos ) +{ + ssize_t retval; + int flags; + DECLARE_WAITQUEUE( wait, current ); + + PRINTK( KERN_DEBUG "%sread()\n", pszMe ); + + local_irq_save( flags ); + if ( last_rx_result == 0 ) { + local_irq_restore( flags ); + } else { /* an error happended and receiver is paused */ + local_irq_restore( flags ); + last_rx_result = 0; + kick_start_rx(); + } + + add_wait_queue( &wq_read, &wait ); + while( 1 ) { + ssize_t bytes_avail; + ssize_t bytes_to_end; + + set_current_state( TASK_INTERRUPTIBLE ); + + /* snap ring buf state */ + local_irq_save( flags ); + bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ); + bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); + local_irq_restore( flags ); + + if ( bytes_avail != 0 ) { + ssize_t bytes_to_move = MIN( stCount, bytes_avail ); + retval = 0; // will be bytes transfered + if ( bytes_to_move != 0 ) { + size_t n = MIN( bytes_to_end, bytes_to_move ); + if ( copy_to_user( pUserBuffer, + &rx_ring.buf[ rx_ring.out ], + n ) ) { + retval = -EFAULT; + break; + } + bytes_to_move -= n; + retval += n; + // might go 1 char off end, so wrap + rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1); + if ( copy_to_user( pUserBuffer + n, + &rx_ring.buf[ rx_ring.out ], + bytes_to_move ) + ) { + retval = -EFAULT; + break; + } + rx_ring.out += bytes_to_move; // cannot wrap + retval += bytes_to_move; + kick_start_rx(); + } + break; + } + else if ( last_rx_result ) { + retval = last_rx_result; + break; + } + else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep + retval = -EAGAIN; + break; + } + else if ( signal_pending( current ) ) { // no data, can sleep, but signal + retval = -ERESTARTSYS; + break; + } + schedule(); // no data, can sleep + } + set_current_state( TASK_RUNNING ); + remove_wait_queue( &wq_read, &wait ); + + if ( retval < 0 ) + printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) ); + return retval; +} + +/* + * Write endpoint. This routine attempts to break the passed in buffer + * into usb DATA0/1 packet size chunks and send them to the host. + * (The lower-level driver tries to do this too, but easier for us + * to manage things here.) + * + * We are at the mercy of the host here, in that it must send an IN + * token to us to pull this data back, so hopefully some higher level + * protocol is expecting traffic to flow in that direction so the host + * is actually polling us. To guard against hangs, a 5 second timeout + * is used. + * + * This routine takes some care to only report bytes sent that have + * actually made it across the wire. Thus we try to stay in lockstep + * with the completion routine and only have one packet on the xmit + * hardware at a time. Multiple simultaneous writers will get + * "undefined" results. + * + */ +static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer, + size_t stCount, loff_t *pPos ) +{ + ssize_t retval = 0; + ssize_t stSent = 0; + + DECLARE_WAITQUEUE( wait, current ); + + PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount ); + + down( &xmit_sem ); // only one thread onto the hardware at a time + + while( stCount != 0 && retval == 0 ) { + int nThisTime = MIN( TX_PACKET_SIZE, stCount ); + copy_from_user( tx_buf, pUserBuffer, nThisTime ); + sending = nThisTime; + retval = pxa_usb_send( tx_buf, nThisTime, tx_done_callback ); + if ( retval < 0 ) { + char * p = what_the_f( retval ); + printk( "%sCould not queue xmission. rc=%d - %s\n", + pszMe, retval, p ); + sending = 0; + break; + } + /* now have something on the diving board */ + add_wait_queue( &wq_write, &wait ); + tx_timer.expires = jiffies + ( HZ * 5 ); + add_timer( &tx_timer ); + while( 1 ) { + set_current_state( TASK_INTERRUPTIBLE ); + if ( sending == 0 ) { /* it jumped into the pool */ + del_timer( &tx_timer ); + retval = last_tx_result; + if ( retval == 0 ) { + stSent += last_tx_size; + pUserBuffer += last_tx_size; + stCount -= last_tx_size; + } + else + printk( "%sxmission error rc=%d - %s\n", + pszMe, retval, what_the_f(retval) ); + break; + } + else if ( signal_pending( current ) ) { + del_timer( &tx_timer ); + printk( "%ssignal\n", pszMe ); + retval = -ERESTARTSYS; + break; + } + schedule(); + } + set_current_state( TASK_RUNNING ); + remove_wait_queue( &wq_write, &wait ); + } + + up( &xmit_sem ); + + if ( 0 == retval ) + retval = stSent; + return retval; +} + +static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ) +{ + unsigned int retval = 0; + + PRINTK( KERN_DEBUG "%poll()\n", pszMe ); + + poll_wait( pFile, &wq_poll, pWait ); + + if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) ) + retval |= POLLIN | POLLRDNORM; + if ( pxa_usb_xmitter_avail() ) + retval |= POLLOUT | POLLWRNORM; + return retval; +} + +static int usbc_ioctl( struct inode *pInode, struct file *pFile, + unsigned int nCmd, unsigned long argument ) +{ + int retval = 0; + + switch( nCmd ) { + + case USBC_IOC_FLUSH_RECEIVER: + pxa_usb_recv_reset(); + rx_ring.in = rx_ring.out = 0; + break; + + case USBC_IOC_FLUSH_TRANSMITTER: + pxa_usb_send_reset(); + break; + + case USBC_IOC_FLUSH_ALL: + pxa_usb_recv_reset(); + rx_ring.in = rx_ring.out = 0; + pxa_usb_send_reset(); + break; + + default: + retval = -ENOIOCTLCMD; + break; + + } + return retval; +} + + +static int usbc_close( struct inode *pInode, struct file * pFile ) +{ + PRINTK( KERN_DEBUG "%sclose()\n", pszMe ); + if ( --usb_ref_count == 0 ) { + down( &xmit_sem ); + pxa_usb_stop(); + free_txrx_buffers(); + free_string_descriptors(); + del_timer( &tx_timer ); + pxa_usb_close(); + up( &xmit_sem ); + } + MOD_DEC_USE_COUNT; + return 0; +} + +#ifdef CONFIG_SA1100_EXTENEX1 +#include "../../../drivers/char/ex_gpio.h" +void extenex_configured_notify_proc( void ) +{ + if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN ) + printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe ); +} +#endif +////////////////////////////////////////////////////////////////////////////// +// Initialization +////////////////////////////////////////////////////////////////////////////// + +static struct file_operations usbc_fops = { + owner: THIS_MODULE, + open: usbc_open, + read: usbc_read, + write: usbc_write, + poll: usbc_poll, + ioctl: usbc_ioctl, + release: usbc_close, +}; + +static struct miscdevice usbc_misc_device = { + USBC_MINOR, "usb_char", &usbc_fops +}; + +/* + * usbc_init() + */ + +int __init usbc_init( void ) +{ + int rc; + + if ( (rc = misc_register( &usbc_misc_device )) != 0 ) { + printk( KERN_WARNING "%sCould not register device 10, " + "%d. (%d)\n", pszMe, USBC_MINOR, rc ); + return -EBUSY; + } + + // initialize wait queues + init_waitqueue_head( &wq_read ); + init_waitqueue_head( &wq_write ); + init_waitqueue_head( &wq_poll ); + + // initialize tx timeout timer + init_timer( &tx_timer ); + tx_timer.function = tx_timeout; + + printk( KERN_INFO "USB Function Character Driver Interface" + " - %s, (C) 2001, Extenex Corp.\n", VERSION + ); + + return rc; +} + +void __exit usbc_exit( void ) +{ +} + +EXPORT_NO_SYMBOLS; + +module_init(usbc_init); +module_exit(usbc_exit); + + + +// end: usb-char.c + + + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb-char.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2001 Extenex Corporation + * + * usb-char.h + * + * Character device emulation client for SA-1100 client usb core. + * + * + * + */ +#ifndef _USB_CHAR_H +#define _USB_CHAR_H + +#define USBC_MAJOR 10 /* miscellaneous character device */ +#define USBC_MINOR 240 /* in the "reserved for local use" range */ + +#define USBC_MAGIC 0x8E + +/* zap everything in receive ring buffer */ +#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 ) + +/* reset transmitter */ +#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 ) + +/* do both of above */ +#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 ) + + + + + + +#endif /* _USB_CHAR_H */ + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb-eth.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,479 @@ +/* + * Ethernet driver for the PXA USB client function + * Copyright (c) 2001 by Nicolas Pitre + * + * This code was loosely inspired by the original initial ethernet test driver + * Copyright (c) Compaq Computer Corporation, 1999 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This is still work in progress... + * + * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com + * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit. + * Now, since we do not know what size of packet we are receiving + * last usb packet in sequence will always be less than max packet + * receive endpoint can accept. + * Now the only way to check correct start of frame is to compare + * MAC address. Also now we are stalling on each receive error. + * + * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte + * aligned buffer, but this breaks IP code (unaligned access). + * + * 01/04/2001 - stall endpoint operations appeared to be very unstable, so + * they are disabled now. + * + * 03/06/2001 - Readded "zerocopy" receive path (tunable). + * + */ + +// Define DMA_NO_COPY if you want data to arrive directly into the +// receive network buffers, instead of arriving into bounce buffer +// and then get copied to network buffer. +// This does not work correctly right now. +#undef DMA_NO_COPY + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pxa_usb.h" + + +#define ETHERNET_VENDOR_ID 0x49f +#define ETHERNET_PRODUCT_ID 0x505A +#define MAX_PACKET 32768 +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +// Should be global, so that insmod can change these +int usb_rsize=64; +int usb_wsize=64; + +static struct usbe_info_t { + struct net_device *dev; + u16 packet_id; + struct net_device_stats stats; +} usbe_info; + +static char usb_eth_name[16] = "usbf"; +static struct net_device usb_eth_device; +static struct sk_buff *cur_tx_skb, *next_tx_skb; +static struct sk_buff *cur_rx_skb, *next_rx_skb; +static volatile int terminating; +#ifndef DMA_NO_COPY +static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary +#endif + +static int usb_change_mtu (struct net_device *net, int new_mtu) +{ + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET) + return -EINVAL; + // no second zero-length packet read wanted after mtu-sized packets + if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0) + return -EDOM; + + net->mtu = new_mtu; + return 0; +} + +static struct sk_buff * +usb_new_recv_skb(void) +{ + struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC); + + if (skb) { + skb_reserve(skb, 2); + } + return skb; +} + +static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff}; +static void +usb_recv_callback(int flag, int size) +{ + struct sk_buff *skb; + + if (terminating) + return; + + skb = cur_rx_skb; + + /* flag validation */ + if (flag == 0) { + if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!! + usbe_info.stats.rx_over_errors++; + goto error; + } +#ifndef DMA_NO_COPY + memcpy(skb->tail,dmabuf,size); +#endif + skb_put(skb, size); + } else { + if (flag == -EIO) { + usbe_info.stats.rx_errors++; + } + goto error; + } + + + /* + * If the real size of the packet is divisible by usb_rsize + * an extra byte will be added. Thus size == usb_rsize + * should only happen if more data is to come. + */ + /* validate packet length */ + if (size == usb_rsize ) { + /* packet not complete yet */ + skb = NULL; + } + + /* + * At this point skb is non null if we have a complete packet. + * If so take a fresh skb right away and restart USB receive without + * further delays, then process the packet. Otherwise resume USB + * receive on the current skb and exit. + */ + + if (skb) + cur_rx_skb = next_rx_skb; +#ifndef DMA_NO_COPY + pxa_usb_recv(dmabuf, usb_rsize, + usb_recv_callback); +#else + pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), + usb_recv_callback); +#endif + if (!skb) + return; + + next_rx_skb = usb_new_recv_skb(); + if (!next_rx_skb) { + /* + * We can't aford loosing buffer space... + * So we drop the current packet and recycle its skb. + */ + printk("%s: can't allocate new skb\n", __FUNCTION__); + usbe_info.stats.rx_dropped++; + skb_trim(skb, 0); + next_rx_skb = skb; + return; + } + if ( skb->len >= sizeof(struct ethhdr)) { + if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) { + // This frame is not for us. nor it is broadcast + usbe_info.stats.rx_frame_errors++; + kfree_skb(skb); + goto error; + } + +#if 0 +{ + int i; + + for (i = 0; i < skb->len; i++) + { + printk("%02X ", skb->data[i]); + if( (i%8)==7) printk("\n"); + } + printk("...\n"); +} +#endif + + } + + if (skb->len) { + int status; +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? + + skb->dev = &usb_eth_device; + skb->protocol = eth_type_trans (skb, &usb_eth_device); + usbe_info.stats.rx_packets++; + usbe_info.stats.rx_bytes += skb->len; + skb->ip_summed = CHECKSUM_NONE; + status = netif_rx (skb); + if (status != NET_RX_SUCCESS) + printk("netif_rx failed with code %d\n",status); + } else { +error: +//printk("ERROR... tailroom=%d size=%d len=%d flag=%d\n", skb_tailroom(skb), size, skb->len, flag); + /* + * Error due to HW addr mismatch, or IO error. + * Recycle the current skb and reset USB reception. + */ + skb_trim(cur_rx_skb, 0); +// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall +#ifndef DMA_NO_COPY + pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback); +#else + pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback); +#endif + } +} + + +static void +usb_send_callback(int flag, int size) +{ + struct net_device *dev = usbe_info.dev; + struct net_device_stats *stats; + struct sk_buff *skb=cur_tx_skb; + int ret; + + if (terminating) + return; + + stats = &usbe_info.stats; + switch (flag) { + case 0: + stats->tx_packets++; + stats->tx_bytes += size; + break; + case -EIO: + stats->tx_errors++; + break; + default: + stats->tx_dropped++; + break; + } + + cur_tx_skb = next_tx_skb; + next_tx_skb = NULL; + dev_kfree_skb_irq(skb); + if (!cur_tx_skb) + return; + + dev->trans_start = jiffies; + ret = pxa_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback); + if (ret) { + /* If the USB core can't accept the packet, we drop it. */ + dev_kfree_skb_irq(cur_tx_skb); + cur_tx_skb = NULL; + usbe_info.stats.tx_carrier_errors++; + } + netif_wake_queue(dev); +} + +static int +usb_eth_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + long flags; + + if (next_tx_skb) { + printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__); + return 1; + } + + if (skb_shared (skb)) { + struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC); + if (!skb2) { + usbe_info.stats.tx_dropped++; + dev_kfree_skb(skb); + return 1; + } + skb = skb2; + } + + if ((skb->len % usb_wsize) == 0) { + skb->len++; // other side will ignore this one, anyway. + } + + save_flags_cli(flags); + if (cur_tx_skb) { + next_tx_skb = skb; + netif_stop_queue(dev); + } else { + cur_tx_skb = skb; + dev->trans_start = jiffies; + ret = pxa_usb_send(skb->data, skb->len, usb_send_callback); + if (ret) { + /* If the USB core can't accept the packet, we drop it. */ + dev_kfree_skb(skb); + cur_tx_skb = NULL; + usbe_info.stats.tx_carrier_errors++; + } + } + restore_flags(flags); + return 0; +} + +static void +usb_xmit_timeout(struct net_device *dev ) +{ + pxa_usb_send_reset(); + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + + +static int +usb_eth_open(struct net_device *dev) +{ + int rc; + rc = pxa_usb_open( "usb-eth" ); + if ( rc == 0 ) { + string_desc_t * pstr; + desc_t * pd = pxa_usb_get_descriptor_ptr(); + + pd->b.ep1.wMaxPacketSize = make_word( usb_rsize ); + pd->b.ep2.wMaxPacketSize = make_word( usb_wsize ); + pd->dev.idVendor = ETHERNET_VENDOR_ID; + pd->dev.idProduct = ETHERNET_PRODUCT_ID; + pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" ); + if ( pstr ) { + pxa_usb_set_string_descriptor( 1, pstr ); + pd->dev.iProduct = 1; + } + rc = pxa_usb_start(); + } + + if( rc == 0) + { + terminating = 0; + cur_tx_skb = next_tx_skb = NULL; + cur_rx_skb = usb_new_recv_skb(); + next_rx_skb = usb_new_recv_skb(); + if (!cur_rx_skb || !next_rx_skb) { + printk("%s: can't allocate new skb\n", __FUNCTION__); + if (cur_rx_skb) + kfree_skb(cur_rx_skb); + if (next_rx_skb) + kfree_skb(next_rx_skb); + + pxa_usb_stop(); + pxa_usb_close(); + return -ENOMEM;; + } + + MOD_INC_USE_COUNT; +#ifndef DMA_NO_COPY + pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback); +#else + pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), + usb_recv_callback); +#endif + } + + return rc; +} + +static int +usb_eth_release(struct net_device *dev) +{ + string_desc_t * pstr; + + terminating = 1; + pxa_usb_send_reset(); + pxa_usb_recv_reset(); + if (cur_tx_skb) + kfree_skb(cur_tx_skb); + if (next_tx_skb) + kfree_skb(next_tx_skb); + if (cur_rx_skb) + kfree_skb(cur_rx_skb); + if (next_rx_skb) + kfree_skb(next_rx_skb); + + pxa_usb_stop(); + pxa_usb_close(); + if ( (pstr = pxa_usb_get_string_descriptor(1)) != NULL ) + kfree( pstr ); + + MOD_DEC_USE_COUNT; + return 0; +} + +static struct net_device_stats * +usb_eth_stats(struct net_device *dev) +{ + struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv; + struct net_device_stats *stats=NULL; + + if (priv) + stats = &priv->stats; + return stats; +} + +static int +usb_eth_probe(struct net_device *dev) +{ + u8 node_id [ETH_ALEN]; + + get_random_bytes (node_id, sizeof node_id); + node_id [0] &= 0xfe; // clear multicast bit + + /* + * Assign the hardware address of the board: + * generate it randomly, as there can be many such + * devices on the bus. + */ + memcpy (dev->dev_addr, node_id, sizeof node_id); + + dev->open = usb_eth_open; + dev->change_mtu = usb_change_mtu; + dev->stop = usb_eth_release; + dev->hard_start_xmit = usb_eth_xmit; + dev->get_stats = usb_eth_stats; + dev->watchdog_timeo = 1*HZ; + dev->tx_timeout = usb_xmit_timeout; + dev->priv = &usbe_info; + + usbe_info.dev = dev; + + /* clear the statistics */ + memset(&usbe_info.stats, 0, sizeof(struct net_device_stats)); + + ether_setup(dev); + dev->flags &= ~IFF_MULTICAST; + dev->flags &= ~IFF_BROADCAST; + //dev->flags |= IFF_NOARP; + + return 0; +} + +#ifdef MODULE +MODULE_PARM(usb_rsize, "1i"); +MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to pxa"); +MODULE_PARM(usb_wsize, "1i"); +MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from pxa to host"); +#endif + +static int __init +usb_eth_init(void) +{ +#ifndef DMA_NO_COPY + dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA ); + if (!dmabuf) + return -ENOMEM; +#endif + strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ); + usb_eth_device.init = usb_eth_probe; + if (register_netdev(&usb_eth_device) != 0) + return -EIO; + + printk( KERN_INFO "USB Function Ethernet Driver Interface\n"); + + return 0; +} + +static void __exit +usb_eth_cleanup(void) +{ +#ifndef DMA_NO_COPY + kfree(dmabuf); +#endif + unregister_netdev(&usb_eth_device); +} + +module_init(usb_eth_init); +module_exit(usb_eth_cleanup); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,769 @@ +/* + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * Copyright (C) Extenex Corporation, 2001 + * Copyright (C) Intrinsyc, Inc., 2002 + * + * PXA USB controller core driver. + * + * This file provides interrupt routing and overall coordination + * of the endpoints. + * + * Please see: + * linux/Documentation/arm/SA1100/SA1100_USB + * for more info. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pxa_usb.h" +#include "usb_ctl.h" + +//#define DEBUG 1 + +#if DEBUG +static unsigned int usb_debug = DEBUG; +#else +#define usb_debug 0 /* gcc will remove all the debug code for us */ +#endif + +////////////////////////////////////////////////////////////////////////////// +// Prototypes +////////////////////////////////////////////////////////////////////////////// + +int usbctl_next_state_on_event( int event ); +static void udc_int_hndlr(int, void *, struct pt_regs *); +static void initialize_descriptors( void ); +static void soft_connect_hook( int enable ); +static void udc_disable(void); +static void udc_enable(void); + +#if CONFIG_PROC_FS +#define PROC_NODE_NAME "driver/pxausb" +static int usbctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); +#endif + +////////////////////////////////////////////////////////////////////////////// +// Globals +////////////////////////////////////////////////////////////////////////////// +static const char pszMe[] = "usbctl: "; +struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */ + +/* device descriptors */ +static desc_t desc; + +#define MAX_STRING_DESC 8 +static string_desc_t * string_desc_array[ MAX_STRING_DESC ]; +static string_desc_t sd_zero; /* special sd_zero holds language codes */ + +// called when configured +static usb_notify_t configured_callback = NULL; + +enum { + kStateZombie = 0, + kStateZombieSuspend = 1, + kStateDefault = 2, + kStateDefaultSuspend = 3, + kStateAddr = 4, + kStateAddrSuspend = 5, + kStateConfig = 6, + kStateConfigSuspend = 7 +}; + +/* + * FIXME: The PXA UDC handles several host device requests without user + * notification/intervention. The table could be collapsed quite a bit... + */ +static int device_state_machine[8][6] = { +// suspend reset resume adddr config deconfig +/* zombie */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError }, +/* zom sus */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError }, +/* default */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kStateAddr, kStateConfig, kError }, +/* def sus */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kError , kError , kError }, +/* addr */ { kStateAddrSuspend , kStateDefault, kStateAddr , kError , kStateConfig, kError }, +/* addr sus */{ kStateAddrSuspend , kStateDefault, kStateAddr , kError , kError , kError }, +/* config */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kStateDefault }, +/* cfg sus */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kError } +}; + +/* "device state" is the usb device framework state, as opposed to the + "state machine state" which is whatever the driver needs and is much + more fine grained +*/ +static int sm_state_to_device_state[8] = { +// zombie zom suspend +USB_STATE_POWERED, USB_STATE_SUSPENDED, +// default default sus +USB_STATE_DEFAULT, USB_STATE_SUSPENDED, +// addr addr sus +USB_STATE_ADDRESS, USB_STATE_SUSPENDED, +// config config sus +USB_STATE_CONFIGURED, USB_STATE_SUSPENDED +}; + +static char * state_names[8] = +{ "zombie", "zombie suspended", + "default", "default suspended", + "address", "address suspended", + "configured", "config suspended" +}; + +static char * event_names[6] = +{ "suspend", "reset", "resume", + "address assigned", "configure", "de-configure" +}; + +static char * device_state_names[] = +{ "not attached", "attached", "powered", "default", + "address", "configured", "suspended" }; + +static int sm_state = kStateZombie; + +////////////////////////////////////////////////////////////////////////////// +// Async +////////////////////////////////////////////////////////////////////////////// + +/* The UDCCR reg contains mask and interrupt status bits, + * so using '|=' isn't safe as it may ack an interrupt. + */ + +void udc_set_mask_UDCCR( int mask ) +{ + UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); +} + +void udc_clear_mask_UDCCR( int mask) +{ + UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); +} + +void udc_ack_int_UDCCR( int mask) +{ + /* udccr contains the bits we dont want to change */ + __u32 udccr = UDCCR & UDCCR_MASK_BITS; + + UDCCR = udccr | (mask & ~UDCCR_MASK_BITS); +} + +static void +udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs) +{ + __u32 status = UDCCR; + __u32 ir0_status = USIR0; + __u32 ir1_status = USIR1; + __u32 uicr0 = UICR0; + __u32 uicr1 = UICR1; + + //mask ints + udc_set_mask_UDCCR( UDCCR_REM | UDCCR_SRM); + UICR0 = 0xff; + UICR1 = 0xff; + + if( usb_debug > 2) + { + printk("%s--- udc_int_hndlr\n" + "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n" + "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", + pszMe, status, UDCCS0, UDCCS1, UDCCS2, ir0_status, ir1_status, uicr0, uicr1); + } + + /* SUSpend Interrupt Request */ + if ( status & UDCCR_SUSIR ) + { + udc_ack_int_UDCCR( UDCCR_SUSIR); + if( usb_debug) printk("%sSuspend...\n", pszMe); + usbctl_next_state_on_event( kEvSuspend ); + } + + /* RESume Interrupt Request */ + if ( status & UDCCR_RESIR ) + { + udc_ack_int_UDCCR( UDCCR_RESIR); + if( usb_debug) printk("%sResume...\n", pszMe); + usbctl_next_state_on_event( kEvResume ); + } + + /* ReSeT Interrupt Request - UDC has been reset */ + if ( status & UDCCR_RSTIR ) + { + /* clear the reset interrupt */ + udc_ack_int_UDCCR( UDCCR_RSTIR); + + /* check type of reset */ + if( (UDCCR & UDCCR_UDA) == 0) + { + /* reset assertion took place, nothing to do */ + if( usb_debug) printk("%sReset assertion...\n", pszMe); + } + + /* ok, it's a reset negation, go on with reset */ + else if ( usbctl_next_state_on_event( kEvReset ) != kError ) + { + /* starting reset sequence now... */ + if( usb_debug) printk("%sResetting\n", pszMe); + + ep0_reset(); + ep_bulk_in1_reset(); + ep_bulk_out1_reset(); + + usbctl_next_state_on_event( kEvConfig ); + } + else + { + printk("%sUnexpected reset\n", pszMe); + } + } + else + { + /* ep0 int */ + if (ir0_status & USIR0_IR0) + ep0_int_hndlr(); + + /* transmit bulk */ + if (ir0_status & USIR0_IR1) + ep_bulk_in1_int_hndlr(ir0_status); + + /* receive bulk */ + if ( ir0_status & USIR0_IR2) + ep_bulk_out1_int_hndlr(ir0_status); + + while (UDCCS2 & UDCCS_BO_RNE) + { + if( usb_debug) printk("More Bulk-out data...\n"); + ep_bulk_out1_int_hndlr(ir0_status); + } + } + + UICR0 = uicr0; + UICR1 = uicr1; + udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); /* enable suspend/resume, reset */ + + /* clear all endpoint ints */ + USIR0 |= 0xff; + USIR1 |= 0xff; + + if( usb_debug > 2) + { + printk("%sudc_int_hndlr\n" + "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n" + "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n", + pszMe, UDCCR, UDCCS0, UDCCS1, UDCCS2, USIR0, USIR1, UICR0, UICR1); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Public Interface +////////////////////////////////////////////////////////////////////////////// + +/* Open PXA usb core on behalf of a client, but don't start running */ + +int +pxa_usb_open( const char * client ) +{ + if ( usbd_info.client_name != NULL ) + { + printk( "%sUnable to register %s (%s already registered).\n", + pszMe, client, usbd_info.client_name ); + return -EBUSY; + } + + usbd_info.client_name = (char*) client; + memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t)); + memset(string_desc_array, 0, sizeof(string_desc_array)); + + /* hack to start in zombie suspended state */ + sm_state = kStateZombieSuspend; + usbd_info.state = USB_STATE_SUSPENDED; + + /* create descriptors for enumeration */ + initialize_descriptors(); + + printk( "%s%s registered.\n", pszMe, client ); + return 0; +} + +/* Start running. Must have called usb_open (above) first */ +int +pxa_usb_start( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + + /* start UDC internal machinery running */ + udc_enable(); + udelay( 100 ); + + /* flush DMA and fire through some -EAGAINs */ + ep_bulk_out1_init( usbd_info.dmach_rx ); + ep_bulk_in1_init( usbd_info.dmach_tx ); + + /* give endpoint notification we are starting */ + ep_bulk_out1_state_change_notify( USB_STATE_SUSPENDED ); + ep_bulk_in1_state_change_notify( USB_STATE_SUSPENDED ); + + /* enable any platform specific hardware */ + soft_connect_hook( 1 ); + + /* enable suspend/resume, reset */ + udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); + /* enable ep0, ep1, ep2 */ + UICR0 &= ~(UICR0_IM0 | UICR0_IM1 | UICR0_IM2); + + if( usb_debug) printk( "%sStarted %s\n", pszMe, usbd_info.client_name ); + return 0; +} + +/* Stop USB core from running */ +int +pxa_usb_stop( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + /* mask everything */ + /* disable suspend/resume, reset */ + udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM); + /* disable ep0, ep1, ep2 */ + UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2); + + ep_bulk_out1_reset(); + ep_bulk_in1_reset(); + + udc_disable(); + if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name ); + return 0; +} + +/* Tell PXA core client is through using it */ +int +pxa_usb_close( void ) +{ + if ( usbd_info.client_name == NULL ) { + printk( "%s%s - no client registered\n", + pszMe, __FUNCTION__ ); + return -EPERM; + } + printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name ); + usbd_info.client_name = NULL; + return 0; +} + +/* set a proc to be called when device is configured */ +usb_notify_t pxa_set_configured_callback( usb_notify_t func ) +{ + usb_notify_t retval = configured_callback; + configured_callback = func; + return retval; +} + +/*==================================================== + * Descriptor Manipulation. + * Use these between open() and start() above to setup + * the descriptors for your device. + * + */ + +/* get pointer to static default descriptor */ +desc_t * +pxa_usb_get_descriptor_ptr( void ) { return &desc; } + +/* optional: set a string descriptor */ +int +pxa_usb_set_string_descriptor( int i, string_desc_t * p ) +{ + int retval; + if ( i < MAX_STRING_DESC ) { + string_desc_array[i] = p; + retval = 0; + } else { + retval = -EINVAL; + } + return retval; +} + +/* optional: get a previously set string descriptor */ +string_desc_t * +pxa_usb_get_string_descriptor( int i ) +{ + return ( i < MAX_STRING_DESC ) + ? string_desc_array[i] + : NULL; +} + + +/* optional: kmalloc and unicode up a string descriptor */ +string_desc_t * +pxa_usb_kmalloc_string_descriptor( const char * p ) +{ + string_desc_t * pResult = NULL; + + if ( p ) { + int len = strlen( p ); + int uni_len = len * sizeof( __u16 ); + pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */ + if ( pResult != NULL ) { + int i; + pResult->bLength = uni_len + 2; + pResult->bDescriptorType = USB_DESC_STRING; + for( i = 0; i < len ; i++ ) { + pResult->bString[i] = make_word( (__u16) p[i] ); + } + } + } + return pResult; +} + +////////////////////////////////////////////////////////////////////////////// +// Exports to rest of driver +////////////////////////////////////////////////////////////////////////////// + +/* called by the int handler here and the two endpoint files when interesting + .."events" happen */ + +int +usbctl_next_state_on_event( int event ) +{ + int next_state = device_state_machine[ sm_state ][ event ]; + if ( next_state != kError ) + { + int next_device_state = sm_state_to_device_state[ next_state ]; + if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n", + pszMe, state_names[ sm_state ], event_names[ event ], + state_names[ next_state ], device_state_names[ next_device_state ] ); + + sm_state = next_state; + if ( usbd_info.state != next_device_state ) + { + if ( configured_callback != NULL + && + next_device_state == USB_STATE_CONFIGURED + && + usbd_info.state != USB_STATE_SUSPENDED + ) { + configured_callback(); + } + usbd_info.state = next_device_state; + + ep_bulk_out1_state_change_notify( next_device_state ); + ep_bulk_in1_state_change_notify( next_device_state ); + } + } +#if 1 + else + printk( "%s%s --> [%s] --> ??? is an error.\n", + pszMe, state_names[ sm_state ], event_names[ event ] ); +#endif + return next_state; +} + +////////////////////////////////////////////////////////////////////////////// +// Private Helpers +////////////////////////////////////////////////////////////////////////////// + +/* setup default descriptors */ + +static void +initialize_descriptors(void) +{ + desc.dev.bLength = sizeof( device_desc_t ); + desc.dev.bDescriptorType = USB_DESC_DEVICE; + desc.dev.bcdUSB = 0x100; /* 1.0 */ + desc.dev.bDeviceClass = 0xFF; /* vendor specific */ + desc.dev.bDeviceSubClass = 0; + desc.dev.bDeviceProtocol = 0; + desc.dev.bMaxPacketSize0 = 16; /* ep0 max fifo size */ + desc.dev.idVendor = 0; /* vendor ID undefined */ + desc.dev.idProduct = 0; /* product */ + desc.dev.bcdDevice = 0; /* vendor assigned device release num */ + desc.dev.iManufacturer = 0; /* index of manufacturer string */ + desc.dev.iProduct = 0; /* index of product description string */ + desc.dev.iSerialNumber = 0; /* index of string holding product s/n */ + desc.dev.bNumConfigurations = 1; + + desc.b.cfg.bLength = sizeof( config_desc_t ); + desc.b.cfg.bDescriptorType = USB_DESC_CONFIG; + desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) ); + desc.b.cfg.bNumInterfaces = 1; + desc.b.cfg.bConfigurationValue = 1; + desc.b.cfg.iConfiguration = 0; + desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED; + desc.b.cfg.MaxPower = USB_POWER( 500 ); + + desc.b.intf.bLength = sizeof( intf_desc_t ); + desc.b.intf.bDescriptorType = USB_DESC_INTERFACE; + desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/ + desc.b.intf.bAlternateSetting = 0; + desc.b.intf.bNumEndpoints = 2; + desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */ + desc.b.intf.bInterfaceSubClass = 0; + desc.b.intf.bInterfaceProtocol = 0; + desc.b.intf.iInterface = 0; + +/* + * FIXME... + * The host usbnet driver expects EP1=out EP2=in. On the PXA UDC EP1=in, EP2=out + */ + desc.b.ep1.bLength = sizeof( ep_desc_t ); + desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT; + desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_IN ); + desc.b.ep1.bmAttributes = USB_EP_BULK; + desc.b.ep1.wMaxPacketSize = make_word_c( 64 ); + desc.b.ep1.bInterval = 0; + + desc.b.ep2.bLength = sizeof( ep_desc_t ); + desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT; + desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_OUT ); + desc.b.ep2.bmAttributes = USB_EP_BULK; + desc.b.ep2.wMaxPacketSize = make_word_c( 64 ); + desc.b.ep2.bInterval = 0; + +// FIXME: Add support for all endpoint... + + /* set language */ + /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */ + sd_zero.bDescriptorType = USB_DESC_STRING; + sd_zero.bLength = sizeof( string_desc_t ); + sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */ + pxa_usb_set_string_descriptor( 0, &sd_zero ); +} + +/* soft_connect_hook() + * Some devices have platform-specific circuitry to make USB + * not seem to be plugged in, even when it is. This allows + * software to control when a device 'appears' on the USB bus + * (after Linux has booted and this driver has loaded, for + * example). If you have such a circuit, control it here. + */ +static void +soft_connect_hook( int enable ) +{ +} + +/* disable the UDC at the source */ +static void +udc_disable(void) +{ + soft_connect_hook( 0 ); + /* clear UDC-enable */ + udc_clear_mask_UDCCR( UDCCR_UDE); + + /* Disable clock for USB device */ + CKEN &= ~CKEN11_USB; +} + + +/* enable the udc at the source */ +static void +udc_enable(void) +{ + /* Enable clock for USB device */ + CKEN |= CKEN11_USB; + + /* try to clear these bits before we enable the udc */ + udc_ack_int_UDCCR( UDCCR_SUSIR); + udc_ack_int_UDCCR( UDCCR_RSTIR); + udc_ack_int_UDCCR( UDCCR_RESIR); + + /* set UDC-enable */ + udc_set_mask_UDCCR( UDCCR_UDE); + if( (UDCCR & UDCCR_UDA) == 0) + { + /* There's a reset on the bus, + * clear the interrupt bit and keep going + */ + udc_ack_int_UDCCR( UDCCR_RSTIR); + } + + /* "USB test mode" to work around errata 40-42 (stepping a0, a1) + * which could result in missing packets and interrupts. + * Supposedly this turns off double buffering for all endpoints. + */ + if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3); + UDC_RES1 = 0x00; + UDC_RES2 = 0x00; + if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3); +} + +////////////////////////////////////////////////////////////////////////////// +// Proc Filesystem Support +////////////////////////////////////////////////////////////////////////////// + +#if CONFIG_PROC_FS + +#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args ) +#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num ) +#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn ) +#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v ) + +static int usbctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + const char * num_fmt = "%25.25s: %8.8lX\n"; + const char * cnt_fmt = "%25.25s: %lu\n"; + const char * yn_fmt = "%25.25s: %s\n"; + const char * yes = "YES"; + const char * no = "NO"; + unsigned long v; + char * p = page; + int len; + + SAY( "PXA USB Controller Core\n" ); + SAY( "Active Client: %s\n", usbd_info.client_name ? usbd_info.client_name : "none"); + SAY( "USB state: %s (%s) %d\n", + device_state_names[ sm_state_to_device_state[ sm_state ] ], + state_names[ sm_state ], + sm_state ); + + SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read ); + SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written ); + SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures ); + SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures ); + + SAY( "\n" ); + + v = UDCCR; + SAY( "\nUDC Control Register\n" ); + SAYV( v ); + SAYC( "UDC Enabled", ( v & UDCCR_UDE ) ? yes : no ); + SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no ); + SAYC( "Suspend/Resume interrupts masked", ( v & UDCCR_SRM ) ? yes : no ); + SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no ); + SAYC( "Reset pending", ( v & UDCCR_RSTIR ) ? yes : no ); + SAYC( "Suspend pending", ( v & UDCCR_SUSIR ) ? yes : no ); + SAYC( "Resume pending", ( v & UDCCR_RESIR ) ? yes : no ); + + len = ( p - page ) - off; + if ( len < 0 ) + len = 0; + *eof = ( len <=count ) ? 1 : 0; + *start = page + off; + return len; +} + +#endif /* CONFIG_PROC_FS */ + +#if 0 +static void irq_handler(int channel, void *data, struct pt_regs *regs) +{ + if( channel == usbd_info.dmach_rx) + { + printk( "USB receive DMA\n"); + } + else if( channel == usbd_info.dmach_tx) + { + printk( "USB transmit DMA\n"); + } + else + { + printk( "USB unknown DMA channel\n"); + } +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// Module Initialization and Shutdown +////////////////////////////////////////////////////////////////////////////// +/* + * usbctl_init() + * Module load time. Allocate dma and interrupt resources. Setup /proc fs + * entry. Leave UDC disabled. + */ +int __init usbctl_init( void ) +{ + int retval = 0; + + udc_disable(); + + memset( &usbd_info, 0, sizeof( usbd_info ) ); + +#if CONFIG_PROC_FS + create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL); +#endif + +#if 0 + /* setup rx dma */ + usbd_info.dmach_rx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/); + if (usbd_info.dmach_rx < 0) { + printk("%sunable to register for rx dma rc=%d\n", pszMe, usbd_info.dmach_rx ); + goto err_rx_dma; + } + + /* setup tx dma */ + usbd_info.dmach_tx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/); + if (usbd_info.dmach_tx < 0) { + printk("%sunable to register for tx dma rc=%d\n",pszMe,usbd_info.dmach_tx); + goto err_tx_dma; + } +#endif + + /* now allocate the IRQ. */ + retval = request_irq(IRQ_USB, udc_int_hndlr, SA_INTERRUPT, "PXA USB core", NULL); + if (retval) { + printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval); + goto err_irq; + } + + printk( "PXA USB Controller Core Initialized\n"); + return 0; + +err_irq: +#if 0 + pxa_free_dma(usbd_info.dmach_tx); + usbd_info.dmach_tx = 0; +err_tx_dma: + pxa_free_dma(usbd_info.dmach_rx); + usbd_info.dmach_rx = 0; +err_rx_dma: +#endif + return retval; +} +/* + * usbctl_exit() + * Release DMA and interrupt resources + */ +void __exit usbctl_exit( void ) +{ + printk("Unloading PXA USB Controller\n"); + + udc_disable(); + +#if CONFIG_PROC_FS + remove_proc_entry ( PROC_NODE_NAME, NULL); +#endif + + pxa_free_dma(usbd_info.dmach_rx); + pxa_free_dma(usbd_info.dmach_tx); + free_irq(IRQ_USB, NULL); +} + +module_init( usbctl_init ); +module_exit( usbctl_exit ); + +EXPORT_SYMBOL( pxa_usb_open ); +EXPORT_SYMBOL( pxa_usb_start ); +EXPORT_SYMBOL( pxa_usb_stop ); +EXPORT_SYMBOL( pxa_usb_close ); +EXPORT_SYMBOL( pxa_usb_get_descriptor_ptr ); +EXPORT_SYMBOL( pxa_usb_set_string_descriptor ); +EXPORT_SYMBOL( pxa_usb_get_string_descriptor ); +EXPORT_SYMBOL( pxa_usb_kmalloc_string_descriptor ); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * Copyright (C) Extenex Corporation 2001 + * Copyright (C) Intrinsyc, Inc., 2002 + * + * usb_ctl.h + * + * PRIVATE interface used to share info among components of the PXA USB + * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core + * should use pxa_usb.h. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.h + * + */ + +#ifndef _USB_CTL_H +#define _USB_CTL_H + +/* Interrupt mask bits and UDC enable bit */ +#define UDCCR_MASK_BITS (UDCCR_REM | UDCCR_SRM | UDCCR_UDE) + +/* + * These states correspond to those in the USB specification v1.0 + * in chapter 8, Device Framework. + */ +enum { + USB_STATE_NOTATTACHED =0, + USB_STATE_ATTACHED =1, + USB_STATE_POWERED =2, + USB_STATE_DEFAULT =3, + USB_STATE_ADDRESS =4, + USB_STATE_CONFIGURED =5, + USB_STATE_SUSPENDED =6 +}; + +struct usb_stats_t { + unsigned long ep0_fifo_write_failures; + unsigned long ep0_bytes_written; + unsigned long ep0_fifo_read_failures; + unsigned long ep0_bytes_read; +}; + +struct usb_info_t +{ + char * client_name; + dmach_t dmach_tx, dmach_rx; + int state; + unsigned char address; + struct usb_stats_t stats; +}; + +/* in usb_ctl.c */ +extern struct usb_info_t usbd_info; + +/* + * Function Prototypes + */ +enum { + kError =-1, + kEvSuspend =0, + kEvReset =1, + kEvResume =2, + kEvAddress =3, + kEvConfig =4, + kEvDeConfig =5 +}; +int usbctl_next_state_on_event( int event ); + +/* endpoint zero */ +void ep0_reset(void); +void ep0_int_hndlr(void); + +/* receiver */ +void ep_bulk_out1_state_change_notify( int new_state ); +int ep_bulk_out1_recv(void); +int ep_bulk_out1_init(int chn); +void ep_bulk_out1_int_hndlr(int status); +void ep_bulk_out1_reset(void); +void ep_bulk_out1_stall(void); + +/* xmitter */ +void ep_bulk_in1_state_change_notify( int new_state ); +void ep_bulk_in1_reset(void); +int ep_bulk_in1_init(int chn); +void ep_bulk_in1_int_hndlr(int status); +void ep_bulk_in1_stall(void); + +#endif /* _USB_CTL_H */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,556 @@ +/* + * Copyright (C) Extenex Corporation 2001 + * Copyright (C) Compaq Computer Corporation, 1998, 1999 + * Copyright (C) Intrinsyc, Inc., 2002 + * + * PXA USB controller driver - Endpoint zero management + * + * Please see: + * linux/Documentation/arm/SA1100/SA1100_USB + * for more info. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pxa_usb.h" /* public interface */ +#include "usb_ctl.h" /* private stuff */ +#include "usb_ep0.h" + + +// 1 == lots of trace noise, 0 = only "important' stuff +#define VERBOSITY 0 + +enum { true = 1, false = 0 }; +typedef int bool; +#ifndef MIN +#define MIN( a, b ) ((a)<(b)?(a):(b)) +#endif + +#if 1 && !defined( ASSERT ) +# define ASSERT(expr) \ +if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n",\ +#expr,__FILE__,__FUNCTION__,__LINE__); \ +} +#else +# define ASSERT(expr) +#endif + +#if VERBOSITY +#define PRINTKD(fmt, args...) printk( fmt , ## args) +#else +#define PRINTKD(fmt, args...) +#endif + +static EP0_state ep0_state = EP0_IDLE; + +/*************************************************************************** + Prototypes + ***************************************************************************/ +/* "setup handlers" -- the main functions dispatched to by the + .. isr. These represent the major "modes" of endpoint 0 operation */ +static void sh_setup_begin(void); /* setup begin (idle) */ +static void sh_write( void ); /* writing data */ +static int read_fifo( usb_dev_request_t * p ); +static void write_fifo( void ); +static void get_descriptor( usb_dev_request_t * pReq ); +static void queue_and_start_write( void * p, int req, int act ); + +/*************************************************************************** + Inline Helpers + ***************************************************************************/ + +inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); } + +/* print string descriptor */ +static inline void psdesc( string_desc_t * p ) +{ + int i; + int nchars = ( p->bLength - 2 ) / sizeof( __u16 ); + printk( "'" ); + for( i = 0 ; i < nchars ; i++ ) { + printk( "%c", (char) p->bString[i] ); + } + printk( "'\n" ); +} + +#if VERBOSITY +/* "pcs" == "print control status" */ +static inline void pcs( void ) +{ + __u32 foo = UDCCS0; + printk( "%08x: %s %s %s %s %s %s\n", + foo, + foo & UDCCS0_SA ? "SA" : "", + foo & UDCCS0_OPR ? "OPR" : "", + foo & UDCCS0_RNE ? "RNE" : "", + foo & UDCCS0_SST ? "SST" : "", + foo & UDCCS0_FST ? "FST" : "", + foo & UDCCS0_DRWF ? "DRWF" : "" + ); +} +static inline void preq( usb_dev_request_t * pReq ) +{ + static char * tnames[] = { "dev", "intf", "ep", "oth" }; + static char * rnames[] = { "std", "class", "vendor", "???" }; + char * psz; + switch( pReq->bRequest ) { + case GET_STATUS: psz = "get stat"; break; + case CLEAR_FEATURE: psz = "clr feat"; break; + case SET_FEATURE: psz = "set feat"; break; + case SET_ADDRESS: psz = "set addr"; break; + case GET_DESCRIPTOR: psz = "get desc"; break; + case SET_DESCRIPTOR: psz = "set desc"; break; + case GET_CONFIGURATION: psz = "get cfg"; break; + case SET_CONFIGURATION: psz = "set cfg"; break; + case GET_INTERFACE: psz = "get intf"; break; + case SET_INTERFACE: psz = "set intf"; break; + case SYNCH_FRAME: psz = "synch frame"; break; + default: psz = "unknown"; break; + } + printk( "- [%s: %s req to %s. dir=%s]\n", psz, + rnames[ (pReq->bmRequestType >> 5) & 3 ], + tnames[ pReq->bmRequestType & 3 ], + ( pReq->bmRequestType & 0x80 ) ? "in" : "out" ); +} + +#else +static inline void pcs( void ){} +static inline void preq( usb_dev_request_t *x){} +#endif + +/*************************************************************************** + Globals + ***************************************************************************/ +static const char pszMe[] = "usbep0: "; + +/* pointer to current setup handler */ +static void (*current_handler)(void) = sh_setup_begin; + +/* global write struct to keep write + ..state around across interrupts */ +static struct { + unsigned char *p; + int bytes_left; +} wr; + +/*************************************************************************** + Public Interface + ***************************************************************************/ + +/* reset received from HUB (or controller just went nuts and reset by itself!) + so udc core has been reset, track this state here */ +void ep0_reset(void) +{ + PRINTKD( "%sep0_reset\n", pszMe); + /* reset state machine */ + current_handler = sh_setup_begin; + wr.p = NULL; + wr.bytes_left = 0; + usbd_info.address=0; +} + +/* handle interrupt for endpoint zero */ +void ep0_int_hndlr( void ) +{ + PRINTKD( "%sep0_int_hndlr\n", pszMe); + pcs(); + (*current_handler)(); +} + +/*************************************************************************** + Setup Handlers + ***************************************************************************/ +/* + * sh_setup_begin() + * This setup handler is the "idle" state of endpoint zero. It looks for OPR + * (OUT packet ready) to see if a setup request has been been received from the + * host. + * + */ +static void sh_setup_begin( void ) +{ + usb_dev_request_t req; + int request_type; + int n; + __u32 cs_reg_in = UDCCS0; + + PRINTKD( "%ssh_setup_begin\n", pszMe); + + /* Be sure out packet ready, otherwise something is wrong */ + if ( (cs_reg_in & UDCCS0_OPR) == 0 ) { + /* we can get here early...if so, we'll int again in a moment */ + PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe ); + goto sh_sb_end; + } + + if( ((cs_reg_in & UDCCS0_SA) == 0) && (ep0_state == EP0_IN_DATA_PHASE)) + { + PRINTKD( "%ssetup begin: premature status\n", pszMe ); + + /* premature status, reset tx fifo and go back to idle state*/ + UDCCS0 = UDCCS0_OPR | UDCCS0_FTF; + + ep0_state = EP0_IDLE; + return; + } + + if( (UDCCS0 & UDCCS0_RNE) == 0) + { + /* zero-length OUT? */ + printk( "%ssetup begin: zero-length OUT?\n", pszMe ); + goto sh_sb_end; + } + + /* read the setup request */ + n = read_fifo( &req ); + if ( n != sizeof( req ) ) { + printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. " + " Stalling out...\n", + pszMe, sizeof( req ), n ); + /* force stall, serviced out */ + UDCCS0 = UDCCS0_FST; + goto sh_sb_end; + } + + /* Is it a standard request? (not vendor or class request) */ + request_type = type_code_from_request( req.bmRequestType ); + if ( request_type != 0 ) { + printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n", + pszMe, request_type ); + goto sh_sb_end; + } + +#if VERBOSITY + { + unsigned char * pdb = (unsigned char *) &req; + PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ", + pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7] + ); + preq( &req ); + } +#endif + + /* Handle it */ + switch( req.bRequest ) { + + case SET_ADDRESS: + PRINTKD( "%sSET_ADDRESS handled by UDC\n", pszMe); + break; +#if 0 /* NOT_NEEDED */ + + case SET_FEATURE: + PRINTKD( "%sSET_FEATURE handled by UDC\n", pszMe); + break; + + case CLEAR_FEATURE: + PRINTKD( "%sCLEAR_FEATURE handled by UDC\n", pszMe); + break; + + case GET_CONFIGURATION: + PRINTKD( "%sGET_CONFIGURATION handled by UDC\n", pszMe ); + break; + + case GET_STATUS: + PRINTKD( "%s%sGET_STATUS handled by UDC\n", pszMe ); + break; + + case GET_INTERFACE: + PRINTKD( "%sGET_INTERFACE handled by UDC\n", pszMe); + break; + + case SYNCH_FRAME: + PRINTKD( "%sSYNCH_FRAME handled by UDC\n", pszMe ); + break; +#endif + + case GET_DESCRIPTOR: + PRINTKD( "%sGET_DESCRIPTOR\n", pszMe ); + get_descriptor( &req ); + break; + + case SET_INTERFACE: + PRINTKD( "%sSET_INTERFACE TODO...\n", pszMe); + break; + + case SET_DESCRIPTOR: + PRINTKD( "%sSET_DESCRIPTOR TODO...\n", pszMe ); + break; + + case SET_CONFIGURATION: + PRINTKD( "%sSET_CONFIGURATION %d\n", pszMe, req.wValue); + +/* + * FIXME: Something is not quite right here... I only ever get a + * de-configure from the host. Ignoring it for now, since usb + * ethernet won't do anything unless usb is 'configured'. + * + */ +#if 0 + switch( req.wValue) + { + case 0: + /* configured */ + usbctl_next_state_on_event( kEvConfig ); + break; + case 1: + /* de-configured */ + usbctl_next_state_on_event( kEvDeConfig ); + break; + default: + PRINTKD( "%sSET_CONFIGURATION: unknown configuration value (%d)\n", pszMe, req.wValue); + break; + } +#endif + break; + default : + printk("%sunknown request 0x%x\n", pszMe, req.bRequest); + break; + } /* switch( bRequest ) */ + +sh_sb_end: + return; +} + +/* + * sh_write() + * + * Due to UDC bugs we push everything into the fifo in one go. + * Using interrupts just didn't work right... + * This should be ok, since control request are small. + */ +static void sh_write() +{ + PRINTKD( "sh_write\n" ); + do + { + write_fifo(); + } while( ep0_state != EP0_END_XFER); +} + +/*************************************************************************** + Other Private Subroutines + ***************************************************************************/ +/* + * queue_and_start_write() + * data == data to send + * req == bytes host requested + * act == bytes we actually have + * + * Sets up the global "wr"-ite structure and load the outbound FIFO + * with data. + * + */ +static void queue_and_start_write( void * data, int req, int act ) +{ + PRINTKD( "write start: bytes requested=%d actual=%d\n", req, act); + + wr.p = (unsigned char*) data; + wr.bytes_left = MIN( act, req ); + + ep0_state = EP0_IN_DATA_PHASE; + sh_write(); + + return; +} +/* + * write_fifo() + * Stick bytes in the endpoint zero FIFO. + * + */ +static void write_fifo( void ) +{ + int bytes_this_time = MIN( wr.bytes_left, EP0_FIFO_SIZE ); + int bytes_written = 0; + + while( bytes_this_time-- ) { +// PRINTKD( "%2.2X ", *wr.p ); + UDDR0 = *wr.p++; + bytes_written++; + } + wr.bytes_left -= bytes_written; + + usbd_info.stats.ep0_bytes_written += bytes_written; + + if( (wr.bytes_left==0)) + { + wr.p = NULL; /* be anal */ + + if(bytes_written < EP0_FIFO_SIZE) + { + int count; + int udccs0; + + /* We always end the transfer with a short or zero length packet */ + ep0_state = EP0_END_XFER; + current_handler = sh_setup_begin; + + /* Let the packet go... */ + UDCCS0 = UDCCS0_IPR; + + /* Wait until we get to status-stage, then ack. + * + * When the UDC sets the UDCCS0[OPR] bit, an interrupt + * is supposed to be generated (see 12.5.1 step 14ff, PXA Dev Manual). + * That approach didn't work out. Usually a new SETUP command was + * already in the fifo. I tried many approaches but was always losing + * at least some OPR interrupts. Thus the polling below... + */ + count = 1000; + udccs0 = UDCCS0; + do + { + if( (UDCCS0 & UDCCS0_OPR)) + { + /* clear OPR, generate ack */ + UDCCS0 = UDCCS0_OPR; + break; + } + count--; + udelay(1); + } while( count); + + PRINTKD( "write fifo: count=%d UDCCS0=%x UDCCS0=%x\n", count, udccs0, UDCCS0); + } + } + /* something goes poopy if I dont wait here ... */ + udelay(500); + + PRINTKD( "write fifo: bytes sent=%d, bytes left=%d\n", bytes_written, wr.bytes_left); +} + +/* + * read_fifo() + * Read bytes out of FIFO and put in request. + * Called to do the initial read of setup requests + * from the host. Return number of bytes read. + * + */ +static int read_fifo( usb_dev_request_t * request ) +{ + int bytes_read = 0; + unsigned char * pOut = (unsigned char*) request; + + int udccs0 = UDCCS0; + + if( (udccs0 & SETUP_READY) == SETUP_READY) + { + /* ok it's a setup command */ + while( UDCCS0 & UDCCS0_RNE) + { + if( bytes_read >= sizeof( usb_dev_request_t)) + { + /* We've already read enought o fill usb_dev_request_t. + * Our tummy is full. Go barf... + */ + printk( "%sread_fifo(): read failure\n", pszMe ); + usbd_info.stats.ep0_fifo_read_failures++; + break; + } + + *pOut++ = UDDR0; + bytes_read++; + } + } + PRINTKD( "read_fifo %d bytes\n", bytes_read ); + + /* clear SA & OPR */ + UDCCS0 = SETUP_READY; + + usbd_info.stats.ep0_bytes_read += bytes_read; + return bytes_read; +} + +/* + * get_descriptor() + * Called from sh_setup_begin to handle data return + * for a GET_DESCRIPTOR setup request. + */ +static void get_descriptor( usb_dev_request_t * pReq ) +{ + string_desc_t * pString; + ep_desc_t * pEndpoint = 0; + + desc_t * pDesc = pxa_usb_get_descriptor_ptr(); + int type = pReq->wValue >> 8; + int idx = pReq->wValue & 0xFF; + +// PRINTKD( "%sget_descriptor for %d\n", pszMe, type ); + switch( type ) { + case USB_DESC_DEVICE: + queue_and_start_write( &pDesc->dev, + pReq->wLength, + pDesc->dev.bLength ); + break; + + // return config descriptor buffer, cfg, intf, 2 ep + case USB_DESC_CONFIG: + queue_and_start_write( &pDesc->b, + pReq->wLength, + sizeof( struct cdb ) ); + break; + + // not quite right, since doesn't do language code checking + case USB_DESC_STRING: + pString = pxa_usb_get_string_descriptor( idx ); + if ( pString ) { + if ( idx != 0 ) { // if not language index + printk( "%sReturn string %d: ", pszMe, idx ); + psdesc( pString ); + } + queue_and_start_write( pString, + pReq->wLength, + pString->bLength ); + } + else { + printk("%sunkown string index %d Stall.\n", pszMe, idx ); + } + break; + + case USB_DESC_INTERFACE: + if ( idx == pDesc->b.intf.bInterfaceNumber ) { + queue_and_start_write( &pDesc->b.intf, + pReq->wLength, + pDesc->b.intf.bLength ); + } + break; + + case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */ + if ( idx == 1 ) + pEndpoint = &pDesc->b.ep1; //[BULK_IN1]; + else if ( idx == 2 ) + pEndpoint = &pDesc->b.ep2; //[BULK_OUT1]; + else + pEndpoint = NULL; + if ( pEndpoint ) { + queue_and_start_write( pEndpoint, + pReq->wLength, + pEndpoint->bLength ); + } else { + printk("%sunkown endpoint index %d Stall.\n", pszMe, idx ); + } + break; + + + default : + printk("%sunknown descriptor type %d. Stall.\n", pszMe, type ); + break; + + } +} + +/* end usb_ep0.c - who needs this comment? */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (C) Intrinsyc, Inc., 2002 + * + * usb_ep0.h - PXA USB controller driver. + * Endpoint zero management + * + * Please see: + * linux/Documentation/arm/SA1100/SA1100_USB + * for details. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - + * + */ + +#ifndef __USB_EP0_H +#define __USB_EP0_H + +#define EP0_FIFO_SIZE 16 +#define SETUP_READY (UDCCS0_SA | UDCCS0_OPR) + +/*================================================ + * USB Protocol Stuff + */ + +/* Request Codes */ +enum { + GET_STATUS =0, + CLEAR_FEATURE =1, + /* reserved =2 */ + SET_FEATURE =3, + /* reserved =4 */ + SET_ADDRESS =5, + GET_DESCRIPTOR =6, + SET_DESCRIPTOR =7, + GET_CONFIGURATION =8, + SET_CONFIGURATION =9, + GET_INTERFACE =10, + SET_INTERFACE =11, + SYNCH_FRAME =12 +}; + +typedef enum { + EP0_IDLE, + EP0_IN_DATA_PHASE, + EP0_END_XFER, + EP0_OUT_DATA_PHASE +} EP0_state; + +/* USB Device Requests */ +typedef struct +{ + __u8 bmRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; +} usb_dev_request_t __attribute__ ((packed)); + +/* Data extraction from usb_request_t fields */ +enum { + kTargetDevice =0, + kTargetInterface=1, + kTargetEndpoint =2 +}; +#endif --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mach-pxa/usb_recv.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,173 @@ +/* + * Generic receive layer for the PXA USB client function + * + * This code was loosely inspired by the original version which was + * Copyright (c) Compaq Computer Corporation, 1998-1999 + * Copyright (c) 2001 by Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 02-May-2002 + * Frank Becker (Intrinsyc) - derived from sa1100 usb_recv.c + * + * TODO: Add support for DMA. + * + */ + +#include +#include +#include +#include +#include + +#include "pxa_usb.h" +#include "usb_ctl.h" + +#if DEBUG +static unsigned int usb_debug = DEBUG; +#else +#define usb_debug 0 /* gcc will remove all the debug code for us */ +#endif + +static char *ep_bulk_out1_buf; +static int ep_bulk_out1_len; +static int ep_bulk_out1_remain; +static usb_callback_t ep_bulk_out1_callback; +static int rx_pktsize; + +static void +ep_bulk_out1_start(void) +{ + /* disable DMA */ + UDCCS2 &= ~UDCCS_BO_DME; + + /* enable interrupts for endpoint 2 (bulk out) */ + UICR0 &= ~UICR0_IM2; +} + +static void +ep_bulk_out1_done(int flag) +{ + int size = ep_bulk_out1_len - ep_bulk_out1_remain; + + if (!ep_bulk_out1_len) + return; + + ep_bulk_out1_len = 0; + if (ep_bulk_out1_callback) { + ep_bulk_out1_callback(flag, size); + } +} + +void +ep_bulk_out1_state_change_notify( int new_state ) +{ +} + +void +ep_bulk_out1_stall( void ) +{ + /* SET_FEATURE force stall at UDC */ + UDCCS2 |= UDCCS_BO_FST; +} + +int +ep_bulk_out1_init(int chn) +{ + desc_t * pd = pxa_usb_get_descriptor_ptr(); + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize ); + ep_bulk_out1_done(-EAGAIN); + return 0; +} + +void +ep_bulk_out1_reset(void) +{ + desc_t * pd = pxa_usb_get_descriptor_ptr(); + rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize ); + UDCCS2 &= ~UDCCS_BO_FST; + ep_bulk_out1_done(-EINTR); +} + +void +ep_bulk_out1_int_hndlr(int udcsr) +{ + int status = UDCCS2; + if( usb_debug) printk("ep_bulk_out1_int_hndlr: UDCCS2=%x\n", status); + + if( (status & (UDCCS_BO_RNE | UDCCS_BO_RSP)) == UDCCS_BO_RSP) + { + /* zero-length packet */ + } + + if( status & UDCCS_BO_RNE) + { + int len; + int i; + char *buf = ep_bulk_out1_buf + ep_bulk_out1_len - ep_bulk_out1_remain; + + /* bytes in FIFO */ + len = (UBCR2 & 0xff) +1; + + if( usb_debug) printk("usb_recv: " + "len=%d out1_len=%d out1_remain=%d\n", + len,ep_bulk_out1_len,ep_bulk_out1_remain); + + if( len > ep_bulk_out1_remain) + { + /* FIXME: if this happens, we need a temporary overflow buffer */ + printk("usb_recv: Buffer overwrite warning...\n"); + len = ep_bulk_out1_remain; + } + + /* read data out of fifo */ + for( i=0; iphysical = KERNEL_XIP_BASE_PHYS; + p->virtual = KERNEL_XIP_BASE_VIRT; + p->length = PGDIR_SIZE * 8; + p->domain = DOMAIN_KERNEL; + p->prot_read = 0; /* r=0, b=0 --> read-only for kernel mode */ + p->prot_write = 0; + p->cacheable = 1; + p->bufferable = 1; + + p ++; +#endif + /* * Go through the initial mappings, but clear out any * pgdir entries that are not in the description. @@ -386,7 +399,7 @@ init_maps->prot_read = 0; init_maps->prot_write = 0; init_maps->cacheable = 1; - init_maps->bufferable = 0; + init_maps->bufferable = 1; create_mapping(init_maps); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/mm/proc-xscale.S 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,1086 @@ +/* + * linux/arch/arm/mm/proc-xscale.S + * + * Author: Nicolas Pitre + * Created: November 2000 + * Copyright: (C) 2000, 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * MMU functions for the Intel XScale CPUs + * + * 2001 Aug 21: + * some contributions by Brett Gaines + * Copyright 2001 by Intel Corp. + * + * 2001 Sep 08: + * Completely revisited, many important fixes + * Nicolas Pitre + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Some knobs for cache allocation policy. + * Allocate on write may or may not be beneficial depending on the memory + * usage pattern of your main application. Write through cache is definitely + * a performance loss in most cases, but might be used for special purposes. + */ +#define PMD_CACHE_WRITE_ALLOCATE 1 +#define PTE_CACHE_WRITE_ALLOCATE 1 +#define CACHE_WRITE_THROUGH 0 + +/* + * There are errata that say that dirty status bits in the cache may get + * corrupted. The workaround significantly affects performance, and the bug + * _might_ just not be that visible or critical to you, so it is configurable. + * Let's hope a future core revision will tell us this was only a bad dream. + * But in the mean time the risk and tradeoff is yours to decide.... + */ +#ifdef CONFIG_XSCALE_CACHE_ERRATA +#undef CACHE_WRITE_THROUGH +#define CACHE_WRITE_THROUGH 1 +#endif + +/* + * This is the maximum size of an area which will be flushed. If the area + * is larger than this, then we flush the whole cache + */ +#define MAX_AREA_SIZE 32768 + +/* + * the cache line size of the I and D cache + */ +#define CACHELINESIZE 32 + +/* + * the size of the data cache + */ +#define CACHESIZE 32768 + +/* + * and the page size + */ +#define PAGESIZE 4096 + +/* + * Virtual address used to allocate the cache when flushed + * + * This must be an address range which is _never_ used. It should + * apparently have a mapping in the corresponding page table for + * compatibility with future CPUs that _could_ require it. For instance we + * don't care. + * + * This must be aligned on a 2*CACHESIZE boundary. The code selects one of + * the 2 areas in alternance each time the clean_d_cache macro is used. + * Without this the XScale core exhibits cache eviction problems and no one + * knows why. + * + * Reminder: the vector table is located at 0xffff0000-0xffff0fff. + */ +#define CLEAN_ADDR 0xfffe0000 + +/* + * This macro is used to wait for a CP15 write and is needed + * when we have to ensure that the last operation to the co-pro + * was completed before continuing with operation. + */ + .macro cpwait, rd + mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15 + mov \rd, \rd @ wait for completion + sub pc, pc, #4 @ flush instruction pipeline + .endm + + .macro cpwait_ret, lr, rd + mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15 + sub pc, \lr, \rd, LSR #32 @ wait for completion and + @ flush instruction pipeline + .endm + +#if !CACHE_WRITE_THROUGH + +/* + * This macro cleans the entire dcache using line allocate. + * The main loop has been unrolled to reduce loop overhead. + * rd and rs are two scratch registers. + */ + .macro clean_d_cache, rd, rs + ldr \rs, =clean_addr + ldr \rd, [\rs] + eor \rd, \rd, #CACHESIZE + str \rd, [\rs] + add \rs, \rd, #CACHESIZE +1: mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line + add \rd, \rd, #CACHELINESIZE + mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line + add \rd, \rd, #CACHELINESIZE + mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line + add \rd, \rd, #CACHELINESIZE + mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line + add \rd, \rd, #CACHELINESIZE + teq \rd, \rs + bne 1b + .endm + + .macro clean_d_line, rd + mcr p15, 0, \rd, c7, c10, 1 + .endm + + .data +clean_addr: .word CLEAN_ADDR + +#else + +/* + * If cache is write-through, there is no need to clean it. + * Simply invalidating will do. + */ + + .macro clean_d_cache, rd, rs + mcr p15, 0, \rd, c7, c6, 0 + .endm + + /* let's try to skip this needless operations at least within loops */ + .macro clean_d_line, rd + .endm + +#endif + + .text + +/* + * cpu_xscale_data_abort() + * + * obtain information about current aborted instruction. + * Note: we read user space. This means we might cause a data + * abort here if the I-TLB and D-TLB aren't seeing the same + * picture. Unfortunately, this does happen. We live with it. + * + * r2 = address of aborted instruction + * r3 = saved SPSR + * + * Returns: + * r0 = address of abort + * r1 = FSR, bit 11 = write + * r3 = corrupted + */ + .align 5 +ENTRY(cpu_xscale_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + ldr r3, [r2] @ read aborted instruction + bic r1, r1, #1 << 11 @ clear bits 11 of FSR + tst r3, #1 << 20 @ check write + orreq r1, r1, #1 << 11 + mov pc, lr + +/* + * cpu_xscale_check_bugs() + */ +ENTRY(cpu_xscale_check_bugs) + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip + mov pc, lr + +#ifndef CONFIG_XSCALE_CACHE_ERRATA +/* + * cpu_xscale_proc_init() + * + * Nothing too exciting at the moment + */ +ENTRY(cpu_xscale_proc_init) + mov pc, lr +#else +/* + * We enable the cache here, but we make sure all the status bits for dirty + * lines are cleared as well (see PXA250 erratum #120). + */ +ENTRY(cpu_xscale_proc_init) + @ enable data cache + ldr r0, cr_p + ldmia r0, {r1, r2} + orr r1, r1, #0x4 + orr r2, r2, #0x4 + stmia r0, {r1, r2} + mcr p15, 0, r1, c1, c0, 0 + cpwait r0 + + @ invalidate data cache + mcr p15, 0, r0, c7, c6, 0 + + @ fill main cache with write-through lines + bic r0, pc, #0x1f + add r1, r0, #CACHESIZE +1: ldr r2, [r0], #32 + cmp r0, r1 + bne 1b + + @ enable test feature to force all fills to the mini-cache + mov r1, #0x8 + mcr p15, 0, r1, c15, c15, 3 + + @ fill mini-cache with write-through lines (2kbytes, 64 lines) + add r1, r0, #2048 +2: ldr r2, [r0], #32 + cmp r0, r1 + bne 2b + + @ disable test feature to force all fills to the mini-cache + mov r1, #0x0 + mcr p15, 0, r1, c15, c15, 3 + + @ invalidate data cache again + mcr p15, 0, r1, c7, c6, 0 + mov pc, lr + +cr_p: .long SYMBOL_NAME(cr_alignment) +#endif + +/* + * cpu_xscale_proc_fin() + */ +ENTRY(cpu_xscale_proc_fin) + str lr, [sp, #-4]! + mov r0, #F_BIT|I_BIT|SVC_MODE + msr cpsr_c, r0 + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1800 @ ...IZ........... + bic r0, r0, #0x0006 @ .............CA. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + bl cpu_xscale_cache_clean_invalidate_all @ clean caches + ldr pc, [sp], #4 + +/* + * cpu_xscale_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 5 +ENTRY(cpu_xscale_reset) + mov r1, #F_BIT|I_BIT|SVC_MODE + msr cpsr_c, r1 @ reset CPSR + mrc p15, 0, r1, c1, c0, 0 @ ctrl register + bic r1, r1, #0x0086 @ ........B....CA. + bic r1, r1, #0x1900 @ ...IZ..S........ + mcr p15, 0, r1, c1, c0, 0 @ ctrl register + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB + bic r1, r1, #0x0001 @ ...............M + mcr p15, 0, r1, c1, c0, 0 @ ctrl register + @ CAUTION: MMU turned off from this point. We count on the pipeline + @ already containing those two last instructions to survive. + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, r0 + +/* + * cpu_xscale_do_idle(type) + * + * Cause the processor to idle + * + * type: + * 0 = slow idle + * 1 = fast idle + * 2 = switch to slow processor clock + * 3 = switch to fast processor clock + * + * For now we do nothing but go to idle mode for every case + * + * XScale supports clock switching, but using idle mode support + * allows external hardware to react to system state changes. + */ + .align 5 + +ENTRY(cpu_xscale_do_idle) + mov r0, #1 + mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE + mov pc, lr + +/* ================================= CACHE ================================ */ + +/* + * cpu_xscale_cache_clean_invalidate_all (void) + * + * clean and invalidate all cache lines + * + * Note: + * 1. We should preserve r0 at all times. + * 2. Even if this function implies cache "invalidation" by its name, + * we don't need to actually use explicit invalidation operations + * since the goal is to discard all valid references from the cache + * and the cleaning of it already has that effect. + * 3. Because of 2 above and the fact that kernel space memory is always + * coherent across task switches there is no need to worry about + * inconsistencies due to interrupts, ence no irq disabling. + */ + .align 5 +ENTRY(cpu_xscale_cache_clean_invalidate_all) + mov r2, #1 +cpu_xscale_cache_clean_invalidate_all_r2: + clean_d_cache r0, r1 + teq r2, #0 + mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* + * cpu_xscale_cache_clean_invalidate_range(start, end, flags) + * + * clean and invalidate all cache lines associated with this area of memory + * + * start: Area start address + * end: Area end address + * flags: nonzero for I cache as well + */ + .align 5 +ENTRY(cpu_xscale_cache_clean_invalidate_range) + bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bhi cpu_xscale_cache_clean_invalidate_all_r2 +1: clean_d_line r0 @ Clean D cache line + mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b + teq r2, #0 + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + moveq pc, lr + sub r0, r0, r3 +1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB + mov pc, lr + +/* + * cpu_xscale_flush_ram_page(page) + * + * clean all cache lines associated with this memory page + * + * page: page to clean + */ + .align 5 +ENTRY(cpu_xscale_flush_ram_page) +#if !CACHE_WRITE_THROUGH + mov r1, #PAGESIZE +1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + subs r1, r1, #2 * CACHELINESIZE + bne 1b +#endif + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* ================================ D-CACHE =============================== */ + +/* + * cpu_xscale_dcache_invalidate_range(start, end) + * + * throw away all D-cached data in specified region without an obligation + * to write them back. Note however that on XScale we must clean all + * entries also due to hardware errata (80200 A0 & A1 only). + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_xscale_dcache_invalidate_range) + mrc p15, 0, r2, c0, c0, 0 @ Read part no. + eor r2, r2, #0x69000000 + eor r2, r2, #0x00052000 @ 80200 XX part no. + bics r2, r2, #0x1 @ Clear LSB in revision field + moveq r2, #0 + beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1 + + tst r0, #CACHELINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line + tst r1, #CACHELINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line + bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line +1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b + mov pc, lr + +/* + * cpu_xscale_dcache_clean_range(start, end) + * + * For the specified virtual address range, ensure that all caches contain + * clean data, such that peripheral accesses to the physical RAM fetch + * correct data. + * + * start: virtual start address + * end: virtual end address + */ + .align 5 +ENTRY(cpu_xscale_dcache_clean_range) +#if !CACHE_WRITE_THROUGH + bic r0, r0, #CACHELINESIZE - 1 + sub r2, r1, r0 + cmp r2, #MAX_AREA_SIZE + movhi r2, #0 + bhi cpu_xscale_cache_clean_invalidate_all_r2 + +1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b +#endif + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* + * cpu_xscale_clean_dcache_page(page) + * + * Cleans a single page of dcache so that if we have any future aliased + * mappings, they will be consistent at the time that they are created. + * + * Note: + * 1. we don't need to flush the write buffer in this case. [really? -Nico] + * 2. we don't invalidate the entries since when we write the page + * out to disk, the entries may get reloaded into the cache. + */ + .align 5 +ENTRY(cpu_xscale_dcache_clean_page) +#if !CACHE_WRITE_THROUGH + mov r1, #PAGESIZE +1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + add r0, r0, #CACHELINESIZE + subs r1, r1, #4 * CACHELINESIZE + bne 1b +#endif + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* + * cpu_xscale_dcache_clean_entry(addr) + * + * Clean the specified entry of any caches such that the MMU + * translation fetches will obtain correct data. + * + * addr: cache-unaligned virtual address + */ + .align 5 +ENTRY(cpu_xscale_dcache_clean_entry) + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* ================================ I-CACHE =============================== */ + +/* + * cpu_xscale_icache_invalidate_range(start, end) + * + * invalidate a range of virtual addresses from the Icache + * + * start: virtual start address + * end: virtual end address + * + * Note: This is vaguely defined as supposed to bring the dcache and the + * icache in sync by the way this function is used. + */ + .align 5 +ENTRY(cpu_xscale_icache_invalidate_range) + bic r0, r0, #CACHELINESIZE - 1 +1: clean_d_line r0 @ Clean D cache line + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* + * cpu_xscale_icache_invalidate_page(page) + * + * invalidate all Icache lines associated with this area of memory + * + * page: page to invalidate + */ + .align 5 +ENTRY(cpu_xscale_icache_invalidate_page) + mov r1, #PAGESIZE +1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + add r0, r0, #CACHELINESIZE + subs r1, r1, #4 * CACHELINESIZE + bne 1b + mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB + mov pc, lr + +/* ================================ CACHE LOCKING============================ + * + * The XScale MicroArchitecture implements support for locking entries into + * the data and instruction cache. The following functions implement the core + * low level instructions needed to accomplish the locking. The developer's + * manual states that the code that performs the locking must be in non-cached + * memory. To accomplish this, the code in xscale-cache-lock.c copies the + * following functions from the cache into a non-cached memory region that + * is allocated through consistent_alloc(). + * + */ + .align 5 +/* + * xscale_icache_lock + * + * r0: starting address to lock + * r1: end address to lock + */ +ENTRY(xscale_icache_lock) + +iLockLoop: + bic r0, r0, #CACHELINESIZE - 1 + mcr p15, 0, r0, c9, c1, 0 @ lock into cache + cmp r0, r1 @ are we done? + add r0, r0, #CACHELINESIZE @ advance to next cache line + bls iLockLoop + mov pc, lr + +/* + * xscale_icache_unlock + */ +ENTRY(xscale_icache_unlock) + mcr p15, 0, r0, c9, c1, 1 @ Unlock icache + mov pc, lr + +/* + * xscale_dcache_lock + * + * r0: starting address to lock + * r1: end address to lock + */ +ENTRY(xscale_dcache_lock) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov r2, #1 + mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode + cpwait ip @ Wait for completion + + mrs r2, cpsr + orr r3, r2, #F_BIT | I_BIT +dLockLoop: + msr cpsr_c, r3 + mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty + mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line + msr cpsr_c, r2 + ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from + @ location [r0]. Post-increment + @ r3 to next cache line + cmp r0, r1 @ Are we done? + bls dLockLoop + + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov r2, #0 + mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode + cpwait_ret lr, ip + +/* + * xscale_dcache_unlock + */ +ENTRY(xscale_dcache_unlock) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, ip, c9, c2, 1 @ Unlock cache + mov pc, lr + +/* + * Needed to determine the length of the code that needs to be copied. + */ + .align 5 +ENTRY(xscale_cache_dummy) + mov pc, lr + +/* ================================== TLB ================================= */ + +/* + * cpu_xscale_tlb_invalidate_all() + * + * Invalidate all TLB entries + */ + .align 5 +ENTRY(cpu_xscale_tlb_invalidate_all) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + cpwait_ret lr, ip + +/* + * cpu_xscale_tlb_invalidate_range(start, end) + * + * invalidate TLB entries covering the specified range + * + * start: range start address + * end: range end address + */ + .align 5 +ENTRY(cpu_xscale_tlb_invalidate_range) + bic r0, r0, #(PAGESIZE - 1) & 0x00ff + bic r0, r0, #(PAGESIZE - 1) & 0xff00 + sub r3, r1, r0 + cmp r3, #256 * PAGESIZE @ arbitrary, should be tuned + bhi cpu_xscale_tlb_invalidate_all + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer +1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry + add r0, r0, #PAGESIZE + cmp r0, r1 + blo 1b + cpwait_ret lr, ip + +/* + * cpu_xscale_tlb_invalidate_page(page, flags) + * + * invalidate the TLB entries for the specified page. + * + * page: page to invalidate + * flags: non-zero if we include the I TLB + */ + .align 5 +ENTRY(cpu_xscale_tlb_invalidate_page) + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + teq r1, #0 + mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry + mcrne p15, 0, r3, c8, c5, 1 @ invalidate I TLB entry + cpwait_ret lr, ip + +/* ================================ TLB LOCKING============================== + * + * The XScale MicroArchitecture implements support for locking entries into + * the Instruction and Data TLBs. The following functions provide the + * low level support for supporting these under Linux. xscale-lock.c + * implements some higher level management code. Most of the following + * is taken straight out of the Developer's Manual. + */ + +/* + * Lock I-TLB entry + * + * r0: Virtual address to translate and lock + */ + .align 5 +ENTRY(xscale_itlb_lock) + mrs r2, cpsr + orr r3, r2, #F_BIT | I_BIT + msr cpsr_c, r3 @ Disable interrupts + mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry + mcr p15, 0, r0, c10, c4, 0 @ Translate and lock + msr cpsr_c, r2 @ Restore interrupts + cpwait_ret lr, ip + +/* + * Lock D-TLB entry + * + * r0: Virtual address to translate and lock + */ + .align 5 +ENTRY(xscale_dtlb_lock) + mrs r2, cpsr + orr r3, r2, #F_BIT | I_BIT + msr cpsr_c, r3 @ Disable interrupts + mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry + mcr p15, 0, r0, c10, c8, 0 @ Translate and lock + msr cpsr_c, r2 @ Restore interrupts + cpwait_ret lr, ip + +/* + * Unlock all I-TLB entries + */ + .align 5 +ENTRY(xscale_itlb_unlock) + mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB + mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB + cpwait_ret lr, ip + +/* + * Unlock all D-TLB entries + */ +ENTRY(xscale_dtlb_unlock) + mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL + mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB + cpwait_ret lr, ip + +/* =============================== PageTable ============================== */ + +/* + * cpu_xscale_set_pgd(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_xscale_set_pgd) + clean_d_cache r1, r2 + mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + cpwait_ret lr, ip + +/* + * cpu_xscale_set_pmd(pmdp, pmd) + * + * Set a level 1 translation table entry, and clean it out of + * any caches such that the MMUs can load it correctly. + * + * pmdp: pointer to PMD entry + * pmd: PMD value to store + */ + .align 5 +ENTRY(cpu_xscale_set_pmd) +#if PMD_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH + and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE + cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE + orreq r1, r1, #PMD_SECT_TEX(1) +#elif CACHE_WRITE_THROUGH + and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE + cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE + biceq r1, r1, #PMD_SECT_BUFFERABLE +#endif + str r1, [r0] + mov ip, #0 + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + +/* + * cpu_xscale_set_pte(ptep, pte) + * + * Set a PTE and flush it out + * + * Errata 40: must set memory to write-through for user read-only pages. + */ + .align 5 +ENTRY(cpu_xscale_set_pte) + str r1, [r0], #-1024 @ linux version + + bic r2, r1, #0xff0 + orr r2, r2, #PTE_TYPE_EXT @ extended page + + eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY + + tst r3, #L_PTE_USER | L_PTE_EXEC @ User or Exec? + orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w + + tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w + @ combined with user -> user r/w + + @ + @ Handle the X bit. We want to set this bit for the minicache + @ (U = E = B = W = 0, C = 1) or when write allocate is enabled, + @ and we have a writeable, cacheable region. If we ignore the + @ U and E bits, we can allow user space to use the minicache as + @ well. + @ + @ X = C & ~W & ~B + @ | C & W & B & write_allocate + @ + eor ip, r1, #L_PTE_CACHEABLE + tst ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE +#if PTE_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH + eorne ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE + tstne ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE +#endif + orreq r2, r2, #PTE_EXT_TEX(1) + +#if CACHE_WRITE_THROUGH + tst r1, #L_PTE_CACHEABLE + bicne r2, r2, #L_PTE_BUFFERABLE @ clear B only if C is set +#else + @ + @ Errata 40: The B bit must be cleared for a user read-only + @ cacheable page. + @ + @ B = B & ~((U|E) & C & ~W) + @ + and ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE + teq ip, #L_PTE_USER | L_PTE_CACHEABLE + teqne ip, #L_PTE_EXEC | L_PTE_CACHEABLE + teqne ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE + biceq r2, r2, #PTE_BUFFERABLE +#endif + + tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + movne r2, #0 @ no -> fault + + str r2, [r0] @ hardware version + + @ We try to map 64K page entries when possible. + @ We do that for kernel space only since the usage pattern from + @ the setting of VM area is quite simple. User space is not worth + @ the implied complexity because of ever randomly changing PTEs + @ (page aging, swapout, etc) requiring constant coherency checks. + @ Since PTEs are usually set in increasing order, we test the + @ possibility for a large page only when given the last PTE of a + @ 64K boundary. + tsteq r1, #L_PTE_USER + andeq r1, r0, #(15 << 2) + teqeq r1, #(15 << 2) + beq 1f + + mov ip, #0 + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + + @ See if we have 16 identical PTEs but with consecutive base addresses +1: bic r3, r2, #0x0000f000 + mov r1, #0x0000f000 +2: eor r2, r2, r3 + teq r2, r1 + bne 4f + subs r1, r1, #0x00001000 + ldr r2, [r0, #-4]! + bne 2b + eors r2, r2, r3 + bne 4f + + @ Now create our LARGE PTE from the current EXT one. + bic r3, r3, #PTE_TYPE_MASK + orr r3, r3, #PTE_TYPE_LARGE + and r2, r3, #0x30 @ EXT_AP --> LARGE_AP0 + orr r2, r2, r2, lsl #2 @ add LARGE_AP1 + orr r2, r2, r2, lsl #4 @ add LARGE_AP3 + LARGE_AP2 + and r1, r3, #0x3c0 @ EXT_TEX + bic r3, r3, #0x3c0 + orr r2, r2, r1, lsl #(12 - 6) @ --> LARGE_TEX + orr r2, r2, r3 @ add remaining bits + + @ then put it in the pagetable + mov r3, r2 +3: strd r2, [r0], #8 + tst r0, #(15 << 2) + bne 3b + + @ Then sync the 2 corresponding cache lines + sub r0, r0, #(16 << 2) + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line +4: orr r0, r0, #(15 << 2) + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + mov ip, #0 + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mov pc, lr + + .ltorg + +cpu_manu_name: + .asciz "Intel" + +cpu_80200_name: + .asciz "XScale-80200" + +cpu_pxa210_name: + .asciz "XScale-PXA210" + +cpu_pxa250_name: + .asciz "XScale-PXA250" + +cpu_pxa255_name: + .asciz "XScale-PXA255" + + .align + + .section ".text.init", #alloc, #execinstr + +__xscale_setup: + mov r0, #F_BIT|I_BIT|SVC_MODE + msr cpsr_c, r0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB + mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0, 0 @ load domain access register + mov r0, #1 @ Allow user space to access + mcr p15, 0, r0, c15, c1, 0 @ ... CP 0 only. +#if CACHE_WRITE_THROUGH + mov r0, #0x20 +#else + mov r0, #0x00 +#endif + mcr p15, 0, r0, c1, c1, 0 @ set auxiliary control reg + mrc p15, 0, r0, c1, c0, 0 @ get control register + bic r0, r0, #0x0200 @ ......R......... + bic r0, r0, #0x0082 @ ........B.....A. + orr r0, r0, #0x0005 @ .............C.M + orr r0, r0, #0x3900 @ ..VIZ..S........ +#ifdef CONFIG_XSCALE_CACHE_ERRATA + bic r0, r0, #0x0004 @ see cpu_xscale_proc_init +#endif + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + + .type xscale_processor_functions, #object +ENTRY(xscale_processor_functions) + .word cpu_xscale_data_abort + .word cpu_xscale_check_bugs + .word cpu_xscale_proc_init + .word cpu_xscale_proc_fin + .word cpu_xscale_reset + .word cpu_xscale_do_idle + + /* cache */ + .word cpu_xscale_cache_clean_invalidate_all + .word cpu_xscale_cache_clean_invalidate_range + .word cpu_xscale_flush_ram_page + + /* dcache */ + .word cpu_xscale_dcache_invalidate_range + .word cpu_xscale_dcache_clean_range + .word cpu_xscale_dcache_clean_page + .word cpu_xscale_dcache_clean_entry + + /* icache */ + .word cpu_xscale_icache_invalidate_range + .word cpu_xscale_icache_invalidate_page + + /* tlb */ + .word cpu_xscale_tlb_invalidate_all + .word cpu_xscale_tlb_invalidate_range + .word cpu_xscale_tlb_invalidate_page + + /* pgtable */ + .word cpu_xscale_set_pgd + .word cpu_xscale_set_pmd + .word cpu_xscale_set_pte + .size xscale_processor_functions, . - xscale_processor_functions + + .type cpu_80200_info, #object +cpu_80200_info: + .long cpu_manu_name + .long cpu_80200_name + .size cpu_80200_info, . - cpu_80200_info + + .type cpu_pxa210_info, #object +cpu_pxa210_info: + .long cpu_manu_name + .long cpu_pxa210_name + .size cpu_pxa210_info, . - cpu_pxa210_info + + .type cpu_pxa250_info, #object +cpu_pxa250_info: + .long cpu_manu_name + .long cpu_pxa250_name + .size cpu_pxa250_info, . - cpu_pxa250_info + + .type cpu_pxa255_info, #object +cpu_pxa255_info: + .long cpu_manu_name + .long cpu_pxa255_name + .size cpu_pxa255_info, . - cpu_pxa255_info + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv5te" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v5" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + .type __80200_proc_info,#object +__80200_proc_info: + .long 0x69052000 + .long 0xfffffff0 +#if CACHE_WRITE_THROUGH + .long 0x00000c0a +#else + .long 0x00000c0e +#endif + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE + .long cpu_80200_info + .long xscale_processor_functions + .size __80200_proc_info, . - __80200_proc_info + + .type __pxa210_proc_info,#object +__pxa210_proc_info: + .long 0x69052120 + .long 0xfffff3f0 +#if CACHE_WRITE_THROUGH + .long 0x00000c0a +#else + .long 0x00000c0e +#endif + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE + .long cpu_pxa210_info + .long xscale_processor_functions + .size __pxa210_proc_info, . - __pxa210_proc_info + + .type __pxa250_proc_info,#object +__pxa250_proc_info: + .long 0x69052100 + .long 0xfffff7f0 +#if CACHE_WRITE_THROUGH + .long 0x00000c0a +#else + .long 0x00000c0e +#endif + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE + .long cpu_pxa250_info + .long xscale_processor_functions + .size __pxa250_proc_info, . - __pxa250_proc_info + + .type __pxa255_proc_info,#object +__pxa255_proc_info: + .long 0x69052d00 + .long 0xfffffff0 +#if CACHE_WRITE_THROUGH + .long 0x00000c0a +#else + .long 0x00000c0e +#endif + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE + .long cpu_pxa255_info + .long xscale_processor_functions + .size __pxa255_proc_info, . - __pxa255_proc_info + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/arch/arm/vmlinux-armv-xip.lds.in 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,125 @@ +/* + * ld script to make ARM Linux kernel + * + * (C) Copyright 2001 Lineo Japan, Inc. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Based on arch/arm/vmlinux-armv.lds.in + * + * taken from the i386 version by Russell King + * Written by Martin Mares + */ +OUTPUT_ARCH(arm) +ENTRY(stext) +SECTIONS +{ + . = TEXTADDR; + .init : { /* Init code and data */ + _stext = .; + __init_begin = .; + *(.text.init) + __proc_info_begin = .; + *(.proc.info) + __proc_info_end = .; + __arch_info_begin = .; + *(.arch.info) + __arch_info_end = .; + __tagtable_begin = .; + *(.taglist) + __tagtable_end = .; + . = ALIGN(16); + __setup_start = .; + *(.setup.init) + __setup_end = .; + __initcall_start = .; + *(.initcall.init) + __initcall_end = .; + . = ALIGN(4096); + __init_end = .; + } + + /DISCARD/ : { /* Exit code and data */ + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + .text : { /* Real text segment */ + _text = .; /* Text and read-only data */ + *(.text) + *(.fixup) + *(.gnu.warning) + *(.text.lock) /* out-of-line lock text */ + *(.rodata) + *(.rodata.*) + *(.glue_7) + *(.glue_7t) + *(.kstrtab) + *(.got) /* Global offset table */ + *(.got.plt) + + _etext = .; /* End of text section */ + } + + . = ALIGN(16); + __ex_table : { /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } + + __ksymtab : { /* Kernel symbol table */ + __start___ksymtab = .; + *(__ksymtab) + __stop___ksymtab = .; + } + + _endtext = .; + + . = DATAADDR; + + _sdata = .; + + . = ALIGN(8192); + + .data : { + /* + * first, the init task union, aligned + * to an 8192 byte boundary. + */ + *(.init.task) + + /* + * then the cacheline aligned data + */ + . = ALIGN(32); + *(.data.cacheline_aligned) + + /* + * and the usual data section + */ + *(.data) + CONSTRUCTORS + + *(.data.init) + + _edata = .; + } + + .bss : { + __bss_start = .; /* BSS */ + *(.bss) + *(COMMON) + _end = . ; + } + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} --- linux-2.4.25/drivers/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -25,6 +25,7 @@ subdir-$(CONFIG_NUBUS) += nubus subdir-$(CONFIG_TC) += tc subdir-$(CONFIG_VT) += video +subdir-$(CONFIG_MMC) += mmc subdir-$(CONFIG_MAC) += macintosh subdir-$(CONFIG_PPC32) += macintosh subdir-$(CONFIG_USB) += usb --- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/char/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -253,6 +253,7 @@ dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100 + dep_tristate ' PXA250/210 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_PXA dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200 @@ -335,6 +336,9 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC fi +if [ "$CONFIG_ARCH_PXA" = "y" ]; then + tristate 'PXA250/210 Real Time Clock' CONFIG_PXA_RTC +fi if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC fi @@ -417,4 +421,8 @@ dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV fi +if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then + tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO +fi + endmenu --- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/char/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -280,6 +280,7 @@ obj-$(CONFIG_MIPS_RTC) += mips_rtc.o obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o +obj-$(CONFIG_PXA_RTC) += sa1100-rtc.o obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/char/mt6n_ttl.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,316 @@ +/* + * Trizeps-2 MT6N development board TTL-IO interface for Linux + * + * Copyright (C) 2003 Luc De Cock + * + * This driver allows use of the TTL-IO interface on the MT6N + * from user space. It exports the /dev/ttlio interface supporting + * some ioctl() and also the /proc/driver/ttlio pseudo-file + * for status information. + * + * The ioctls can be used to set individual TTL output lines. + * Only ioctls are supported. + * + * 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. + * + * Based on other minimal char device drivers, like Alan's + * watchdog, Ted's random, Paul's rtc, etc. etc. + * + * 1.00 Luc De Cock: initial version. + */ + +#define TTLIO_VERSION "1.00" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Writing to the register sets the output lines +* Reading from the register returns the status of the input lines +*/ +static unsigned short *ttlio_base = (unsigned short *) TRIZEPS2_TTLIO_BASE; +static unsigned short ttlio_shadow = 0; + +/* interrupt stuff */ +static struct fasync_struct *ttlio_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(ttlio_wait); +static int ttlio_irq_arrived = 0; +static spinlock_t ttlio_lock; +static unsigned short ttlio_in = 0; +static volatile unsigned long teller = 0; + + +static int ttlio_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static int ttlio_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + + +static void ttlio_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + ttlio_in = *ttlio_base; + + ttlio_irq_arrived = 1; + teller++; + + /* wake up the waiting process */ + wake_up_interruptible(&ttlio_wait); + kill_fasync(&ttlio_async_queue, SIGIO, POLL_IN); +} + +/* + * Now all the various file operations that we export. + */ + +static int ttlio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long ttlio_val; + + switch (cmd) { + case TTLIO_RESET: /* clear all lines */ + { + *ttlio_base = 0; + return 0; + } + case TTLIO_GET: /* get state of TTL input lines */ + { + ttlio_val = *ttlio_base; + return put_user(ttlio_val, (unsigned long *)arg); + } + case TTLIO_SET: /* set state of TTL output lines */ + { + unsigned long user_val; + if (copy_from_user(&user_val, arg, sizeof(unsigned long))) + return -EFAULT; + ttlio_shadow |= (unsigned short) user_val; + *ttlio_base = ttlio_shadow; + return 0; + } + case TTLIO_UNSET: /* unset (clear) state of TTL output lines */ + { + unsigned long user_val; + if (copy_from_user(&user_val, arg, sizeof(unsigned long))) + return -EFAULT; + ttlio_shadow &= ~((unsigned short) user_val); + *ttlio_base = ttlio_shadow; + return 0; + } + case 100: /* get counter */ + { + return put_user(teller, (unsigned long *)arg); + } + case 101: /* reset counter */ + { + teller = 0; + return 0; + } + default: + return -ENOTTY; + } + return 0; +} + +static ssize_t ttlio_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned short data; + ssize_t retval; + + if (count < sizeof(unsigned short)) + return -EINVAL; + + if (file->f_flags & O_NONBLOCK) { + spin_lock_irq(&ttlio_lock); + data = *ttlio_base; + spin_unlock_irq(&ttlio_lock); + retval = put_user(data, (unsigned short *) buf); + if (!retval) + retval = sizeof(unsigned short); + return retval; + } + /* blocking read: wait for interrupt */ + add_wait_queue(&ttlio_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq(&ttlio_lock); + data = *ttlio_base; + if (ttlio_irq_arrived) { + ttlio_irq_arrived = 0; + break; + } + spin_unlock_irq(&ttlio_lock); + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + schedule(); + } + + spin_unlock_irq(&ttlio_lock); + retval = put_user(data, (unsigned short *)buf); + if (!retval) + retval = sizeof(unsigned short); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&ttlio_wait, &wait); + return retval; +} + +static ssize_t ttlio_write(struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + unsigned short content; + + if (count < sizeof(unsigned short)) + return -EINVAL; + + if (copy_from_user (&content, buf, sizeof(unsigned short))) + return -EFAULT; + + ttlio_shadow = content; + *ttlio_base = ttlio_shadow; + + *ppos += sizeof(unsigned short); + + return sizeof(unsigned short); +} + +static int ttlio_open(struct inode *inode, struct file *file) +{ + ttlio_irq_arrived = 0; + return 0; +} + +static int ttlio_fasync(int fd, struct file *filp, int on) +{ + return fasync_helper(fd, filp, on, &ttlio_async_queue); +} + +static unsigned int ttlio_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &ttlio_wait, wait); + return ttlio_irq_arrived ? 0 : POLLIN | POLLRDNORM; +} + +static loff_t ttlio_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +/* + * The various file operations we support. + */ + +static struct file_operations ttlio_fops = { + owner: THIS_MODULE, + llseek: ttlio_llseek, + read: ttlio_read, + poll: ttlio_poll, + write: ttlio_write, + ioctl: ttlio_ioctl, + open: ttlio_open, + fasync: ttlio_fasync, +}; + +static struct miscdevice ttlio_dev = { + TTLIO_MINOR, + "ttlio", + &ttlio_fops +}; + +static int __init ttlio_init(void) +{ + printk(KERN_INFO "MT6N TTL-I/O driver (release %s)\n", + TTLIO_VERSION); + + misc_register(&ttlio_dev); + create_proc_read_entry ("driver/ttlio", 0, 0, ttlio_read_proc, NULL); + + set_GPIO_IRQ_edge(GPIO_TTLIO_IRQ, GPIO_FALLING_EDGE); + if (request_irq(TTLIO_IRQ, ttlio_interrupt, SA_INTERRUPT, "ttlio irq", NULL)) { + printk(KERN_ERR "ttlio: irq %d already in use\n", TTLIO_IRQ); + return 1; + } + return 0; +} + +static void __exit ttlio_exit(void) +{ + free_irq(TTLIO_IRQ, NULL); + remove_proc_entry ("driver/ttlio", NULL); + misc_deregister(&ttlio_dev); +} + +module_init(ttlio_init); +module_exit(ttlio_exit); +EXPORT_NO_SYMBOLS; + +/* + * Info exported via "/proc/driver/ttlio". + */ + +static int ttlio_proc_output(char *buf) +{ + char *p; + unsigned short val; + int i; + + p = buf; + + p += sprintf(p, "input : "); + /* write the state of the input lines */ + val = *ttlio_base; + for (i = 0; i < 8*sizeof(unsigned short); i++) { + *p++ = (val & 1) ? '1' : '0'; + val >>= 1; + } + *p = 0; + p += sprintf(p, "\noutput: "); + /* write the state of the output lines */ + val = ttlio_shadow; + for (i = 0; i < 8*sizeof(unsigned short); i++) { + *p++ = (val & 1) ? '1' : '0'; + val >>= 1; + } + *p = 0; + p += sprintf(p, "\n"); + + return p - buf; +} + +static int ttlio_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = ttlio_proc_output (page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len > count) len = count; + if (len < 0) len = 0; + return len; +} + +MODULE_AUTHOR("Luc De Cock"); +MODULE_DESCRIPTION("MT6N TTL-I/O driver"); +MODULE_LICENSE("GPL"); --- linux-2.4.25/drivers/char/sa1100-rtc.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/char/sa1100-rtc.c 2004-03-31 17:15:11.000000000 +0200 @@ -1,5 +1,6 @@ /* * Real Time Clock interface for Linux on StrongARM SA1100 + * and XScale PXA250/210. * * Copyright (c) 2000 Nils Faerber * @@ -470,5 +471,5 @@ module_exit(rtc_exit); MODULE_AUTHOR("Nils Faerber "); -MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)"); +MODULE_DESCRIPTION("SA1100/PXA Realtime Clock Driver (RTC)"); EXPORT_NO_SYMBOLS; --- linux-2.4.25/drivers/char/sa1100_wdt.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/char/sa1100_wdt.c 2004-03-31 17:15:11.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Watchdog driver for the SA11x0 + * Watchdog driver for the SA11x0/PXA * * (c) Copyright 2000 Oleg Drokin * Based on SoftDog driver by Alan Cox @@ -35,13 +35,20 @@ #define TIMER_MARGIN 60 /* (secs) Default is 1 minute */ -static int sa1100_margin = TIMER_MARGIN; /* in seconds */ +static int timer_margin = TIMER_MARGIN; /* in seconds */ static int sa1100wdt_users; static int pre_margin; #ifdef MODULE -MODULE_PARM(sa1100_margin,"i"); +MODULE_PARM(timer_margin,"i"); #endif +static void sa1100dog_ping( void) +{ + /* reload counter with (new) margin */ + pre_margin=3686400 * timer_margin; + OSMR3 = OSCR + pre_margin; +} + /* * Allow only one person to hold it open */ @@ -51,9 +58,7 @@ if(test_and_set_bit(1,&sa1100wdt_users)) return -EBUSY; MOD_INC_USE_COUNT; - /* Activate SA1100 Watchdog timer */ - pre_margin=3686400 * sa1100_margin; - OSMR3 = OSCR + pre_margin; + sa1100dog_ping(); OSSR = OSSR_M3; OWER = OWER_WME; OIER |= OIER_E3; @@ -93,8 +98,11 @@ unsigned int cmd, unsigned long arg) { static struct watchdog_info ident = { - identity: "SA1100 Watchdog", + identity: "PXA/SA1100 Watchdog", + options: WDIOF_SETTIMEOUT, + firmware_version: 0, }; + int new_margin; switch(cmd){ default: @@ -108,6 +116,16 @@ case WDIOC_KEEPALIVE: OSMR3 = OSCR + pre_margin; return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int *)arg)) + return -EFAULT; + if (new_margin < 1) + return -EINVAL; + timer_margin = new_margin; + sa1100dog_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(timer_margin, (int *)arg); } } @@ -123,7 +141,11 @@ static struct miscdevice sa1100dog_miscdev= { WATCHDOG_MINOR, - "SA1100 watchdog", +#if defined(CONFIG_SA1100_WATCHDOG) + "SA1100_watchdog", +#elif defined(CONFIG_PXA_WATCHDOG) + "PXA_watchdog", +#endif &sa1100dog_fops }; @@ -136,7 +158,7 @@ if (ret) return ret; - printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin); + printk("SA1100/PXA Watchdog Timer: timer margin %d sec\n", timer_margin); return 0; } --- linux-2.4.25/drivers/char/serial.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/char/serial.c 2004-03-31 17:15:11.000000000 +0200 @@ -133,6 +133,16 @@ #endif #endif +#ifdef CONFIG_ARCH_PXA +#define pxa_port(x) ((x) == PORT_PXA) +#define pxa_buggy_port(x) ({ \ + int cpu_ver; asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); \ + ((x) == PORT_PXA && (cpu_ver & ~1) == 0x69052100); }) +#else +#define pxa_port(x) (0) +#define pxa_buggy_port(x) (0) +#endif + /* Set of debugging defines */ #undef SERIAL_DEBUG_INTR @@ -311,6 +321,7 @@ { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "PXA UART", 32, UART_CLEAR_FIFO | UART_USE_FIFO }, { 0, 0} }; @@ -424,6 +435,9 @@ case SERIAL_IO_MEM: return readb((unsigned long) info->iomem_base + (offset<iomem_reg_shift)); + case SERIAL_IO_MEM32: + return readl((unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); default: return inb(info->port + offset); } @@ -443,6 +457,10 @@ writeb(value, (unsigned long) info->iomem_base + (offset<iomem_reg_shift)); break; + case SERIAL_IO_MEM32: + writel(value, (unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); + break; default: outb(value, info->port+offset); } @@ -1306,6 +1324,16 @@ } #endif +#ifdef CONFIG_ARCH_PXA + if (state->type == PORT_PXA) { + switch ((long)state->iomem_base) { + case (long)&FFUART: CKEN |= CKEN6_FFUART; break; + case (long)&BTUART: CKEN |= CKEN7_BTUART; break; + case (long)&STUART: CKEN |= CKEN5_STUART; break; + } + } +#endif + /* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) @@ -1403,6 +1431,8 @@ { if (state->irq != 0) info->MCR |= UART_MCR_OUT2; + if (pxa_buggy_port(state->type) && state->irq != 0) + info->MCR ^= UART_MCR_OUT2; } info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ serial_outp(info, UART_MCR, info->MCR); @@ -1411,6 +1441,8 @@ * Finally, enable interrupts */ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + if (pxa_port(state->type)) + info->IER |= UART_IER_UUE | UART_IER_RTOIE; serial_outp(info, UART_IER, info->IER); /* enable interrupts */ #ifdef CONFIG_SERIAL_MANY_PORTS @@ -1542,6 +1574,8 @@ } else #endif info->MCR &= ~UART_MCR_OUT2; + if (pxa_buggy_port(state->type)) + info->MCR ^= UART_MCR_OUT2; info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ /* disable break condition */ @@ -1567,6 +1601,20 @@ state->baud_base = SERIAL_RSA_BAUD_BASE_LO; #endif +#ifdef CONFIG_ARCH_PXA + if (state->type == PORT_PXA +#ifdef CONFIG_SERIAL_CONSOLE + && sercons.index != info->line +#endif + ) { + switch ((long)state->iomem_base) { + case (long)&FFUART: CKEN &= ~CKEN6_FFUART; break; + case (long)&BTUART: CKEN &= ~CKEN7_BTUART; break; + case (long)&STUART: CKEN &= ~CKEN5_STUART; break; + } + } +#endif + (void)serial_in(info, UART_RX); /* read data port to reset things */ @@ -1857,6 +1905,8 @@ save_flags(flags); cli(); info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); + if (pxa_buggy_port(info->state->type)) + rs_interrupt_single(info->state->irq, NULL, NULL); restore_flags(flags); } @@ -1933,6 +1983,11 @@ && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); + if (pxa_buggy_port(info->state->type)) { + save_flags(flags); cli(); + rs_interrupt_single(info->state->irq, NULL, NULL); + restore_flags(flags); + } } return ret; } @@ -1990,6 +2045,8 @@ /* Make sure transmit interrupts are on */ info->IER |= UART_IER_THRI; serial_out(info, UART_IER, info->IER); + if (pxa_buggy_port(info->state->type)) + rs_interrupt_single(info->state->irq, NULL, NULL); } } @@ -5517,7 +5574,6 @@ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { state->magic = SSTATE_MAGIC; state->line = i; - state->type = PORT_UNKNOWN; state->custom_divisor = 0; state->close_delay = 5*HZ/10; state->closing_wait = 30*HZ; @@ -5531,14 +5587,18 @@ state->irq = irq_cannonicalize(state->irq); if (state->hub6) state->io_type = SERIAL_IO_HUB6; - if (state->port && check_region(state->port,8)) + if (state->port && check_region(state->port,8)) { + state->type = PORT_UNKNOWN; continue; + } #ifdef CONFIG_MCA if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) continue; #endif - if (state->flags & ASYNC_BOOT_AUTOCONF) + if (state->flags & ASYNC_BOOT_AUTOCONF) { + state->type = PORT_UNKNOWN; autoconfig(state); + } } for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { if (state->type == PORT_UNKNOWN) @@ -5858,6 +5918,8 @@ */ ier = serial_in(info, UART_IER); serial_out(info, UART_IER, 0x00); + if (pxa_port(info->state->type)) + serial_out(info, UART_IER, UART_IER_UUE); /* * Now, do each character @@ -6009,6 +6071,8 @@ serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(info, UART_LCR, cval); /* reset DLAB */ serial_out(info, UART_IER, 0); + if (pxa_port(info->state->type)) + serial_out(info, UART_IER, UART_IER_UUE); serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); /* --- linux-2.4.25/drivers/i2c/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/i2c/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -54,6 +54,11 @@ fi fi + if [ "$CONFIG_ARCH_PXA" = "y" ]; then + dep_tristate 'PXA I2C Algorithm' CONFIG_I2C_PXA_ALGO $CONFIG_I2C + dep_tristate 'PXA I2C Adapter' CONFIG_I2C_PXA_ADAP $CONFIG_I2C_PXA_ALGO + fi + if [ "$CONFIG_ALL_PPC" = "y" ] ; then dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C fi --- linux-2.4.25/drivers/i2c/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/i2c/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -6,7 +6,7 @@ export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \ i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \ - i2c-proc.o + i2c-algo-pxa.o i2c-proc.o # Init order: core, chardev, bit adapters, pcf adapters @@ -35,6 +35,10 @@ obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o +# PXA adapters +obj-$(CONFIG_I2C_PXA_ALGO) += i2c-algo-pxa.o +obj-$(CONFIG_I2C_PXA_ADAP) += i2c-adap-pxa.o + # This is needed for automatic patch generation: sensors code starts here # This is needed for automatic patch generation: sensors code ends here --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/i2c/i2c-adap-pxa.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,396 @@ +/* + * i2c_adap_pxa.c + * + * I2C adapter for the PXA I2C bus access. + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Apr 2002: Initial version [CS] + * Jun 2002: Properly seperated algo/adap [FB] + * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] + * Jan 2003: added limited signal handling [Kai-Uwe Bloem] + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* for IRQ_I2C */ + +#include "i2c-pxa.h" + +/* + * Set this to zero to remove all debug statements via dead code elimination. + */ +//#define DEBUG 1 + +#if DEBUG +static unsigned int i2c_debug = DEBUG; +#else +#define i2c_debug 0 +#endif + +static int irq = 0; +static volatile int i2c_pending = 0; /* interrupt pending when 1 */ +static volatile int bus_error = 0; +static volatile int tx_finished = 0; +static volatile int rx_finished = 0; + +static wait_queue_head_t i2c_wait; +static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte); + +/* place a byte in the transmit register */ +static void i2c_pxa_write_byte(u8 value) +{ + IDBR = value; +} + +/* read byte in the receive register */ +static u8 i2c_pxa_read_byte(void) +{ + return (u8) (0xff & IDBR); +} + +static void i2c_pxa_start(void) +{ + unsigned long icr = ICR; + icr |= ICR_START; + icr &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK); + ICR = icr; + + bus_error=0; /* clear any bus_error from previous txfers */ + tx_finished=0; /* clear rx and tx interrupts from previous txfers */ + rx_finished=0; + i2c_pending = 0; +} + +static void i2c_pxa_repeat_start(void) +{ + unsigned long icr = ICR; + icr |= ICR_START; + icr &= ~(ICR_STOP | ICR_ALDIE); + ICR = icr; + + bus_error=0; /* clear any bus_error from previous txfers */ + tx_finished=0; /* clear rx and tx interrupts from previous txfers */ + rx_finished=0; + i2c_pending = 0; +} + +static void i2c_pxa_stop(void) +{ + unsigned long icr = ICR; + icr |= ICR_STOP; + icr &= ~(ICR_START); + ICR = icr; +} + +static void i2c_pxa_midbyte(void) +{ + unsigned long icr = ICR; + icr &= ~(ICR_START | ICR_STOP); + ICR = icr; +} + +static void i2c_pxa_abort(void) +{ + unsigned long timeout = jiffies + HZ/4; + +#ifdef PXA_ABORT_MA + while ((long)(timeout - jiffies) > 0 && (ICR & ICR_TB)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + ICR |= ICR_MA; + udelay(100); +#else + while ((long)(timeout - jiffies) > 0 && (IBMR & 0x1) == 0) { + i2c_pxa_transfer( 1, I2C_RECEIVE, 1); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } +#endif + ICR &= ~(ICR_MA | ICR_START | ICR_STOP); +} + +static int i2c_pxa_wait_bus_not_busy( void) +{ + int timeout = DEF_TIMEOUT; + + while (timeout-- && (ISR & ISR_IBB)) { + udelay(100); /* wait for 100 us */ + } + + return (timeout<=0); +} + +static void i2c_pxa_wait_for_ite(void){ + unsigned long flags; + if (irq > 0) { + save_flags_cli(flags); + if (i2c_pending == 0) { + interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT ); + } + i2c_pending = 0; + restore_flags(flags); + } else { + udelay(100); + } +} + +static int i2c_pxa_wait_for_int( int wait_type) +{ + int timeout = DEF_TIMEOUT; +#ifdef DEBUG + if (bus_error) + printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on enter\n"); + if (rx_finished) + printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on enter\n"); + if (tx_finished) + printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on enter\n"); +#endif + + if (wait_type == I2C_RECEIVE){ /* wait on receive */ + + do { + i2c_pxa_wait_for_ite(); + } while (!(rx_finished) && timeout-- && !signal_pending(current)); + +#ifdef DEBUG + if (timeout<0){ + if (tx_finished) + printk("Error: i2c-algo-pxa.o: received a tx" + " interrupt while waiting on a rx in wait_for_int"); + } +#endif + } else { /* wait on transmit */ + + do { + i2c_pxa_wait_for_ite(); + } while (!(tx_finished) && timeout-- && !signal_pending(current)); + +#ifdef DEBUG + if (timeout<0){ + if (rx_finished) + printk("Error: i2c-algo-pxa.o: received a rx" + " interrupt while waiting on a tx in wait_for_int"); + } +#endif + } + + udelay(ACK_DELAY); /* this is needed for the bus error */ + + tx_finished=0; + rx_finished=0; + + if (bus_error){ + bus_error=0; + if( i2c_debug > 2)printk("wait_for_int: error - no ack.\n"); + return BUS_ERROR; + } + + if (signal_pending(current)) { + return (-ERESTARTSYS); + } else if (timeout < 0) { + if( i2c_debug > 2)printk("wait_for_int: timeout.\n"); + return(-EIO); + } else + return(0); +} + +static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte) +{ + if( lastbyte) + { + if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK; + i2c_pxa_stop(); + } + else if( midbyte) + { + i2c_pxa_midbyte(); + } + ICR |= ICR_TB; +} + +static void i2c_pxa_reset( void) +{ +#ifdef DEBUG + printk("Resetting I2C Controller Unit\n"); +#endif + + /* abort any transfer currently under way */ + i2c_pxa_abort(); + + /* reset according to 9.8 */ + ICR = ICR_UR; + ISR = I2C_ISR_INIT; + ICR &= ~ICR_UR; + + /* set the global I2C clock on */ + CKEN |= CKEN14_I2C; + + /* set our slave address */ + ISAR = I2C_PXA_SLAVE_ADDR; + + /* set control register values */ + ICR = I2C_ICR_INIT; + + /* clear any leftover states from prior transmissions */ + i2c_pending = rx_finished = tx_finished = bus_error = 0; + + /* enable unit */ + ICR |= ICR_IUE; + udelay(100); +} + +static void i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs) +{ + int status, wakeup = 0; + status = (ISR); + + if (status & ISR_BED){ + (ISR) |= ISR_BED; + bus_error=ISR_BED; + wakeup = 1; + } + if (status & ISR_ITE){ + (ISR) |= ISR_ITE; + tx_finished=ISR_ITE; + wakeup = 1; + } + if (status & ISR_IRF){ + (ISR) |= ISR_IRF; + rx_finished=ISR_IRF; + wakeup = 1; + } + if (wakeup) { + i2c_pending = 1; + wake_up_interruptible(&i2c_wait); + } +} + +static int i2c_pxa_resource_init( void) +{ + init_waitqueue_head(&i2c_wait); + + if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C_PXA", 0) < 0) { + irq = 0; + if( i2c_debug) + printk(KERN_INFO "I2C: Failed to register I2C irq %i\n", IRQ_I2C); + return -ENODEV; + }else{ + irq = IRQ_I2C; + enable_irq(irq); + } + return 0; +} + +static void i2c_pxa_resource_release( void) +{ + if( irq > 0) + { + disable_irq(irq); + free_irq(irq,0); + irq=0; + } +} + +static void i2c_pxa_inc_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +static void i2c_pxa_dec_use(struct i2c_adapter *adap) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +static int i2c_pxa_client_register(struct i2c_client *client) +{ + return 0; +} + +static int i2c_pxa_client_unregister(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_algo_pxa_data i2c_pxa_data = { + write_byte: i2c_pxa_write_byte, + read_byte: i2c_pxa_read_byte, + + start: i2c_pxa_start, + repeat_start: i2c_pxa_repeat_start, + stop: i2c_pxa_stop, + abort: i2c_pxa_abort, + + wait_bus_not_busy: i2c_pxa_wait_bus_not_busy, + wait_for_interrupt: i2c_pxa_wait_for_int, + transfer: i2c_pxa_transfer, + reset: i2c_pxa_reset, + + udelay: 10, + timeout: DEF_TIMEOUT, +}; + +static struct i2c_adapter i2c_pxa_ops = { + name: "PXA-I2C-Adapter", + id: I2C_ALGO_PXA, + algo_data: &i2c_pxa_data, + inc_use: i2c_pxa_inc_use, + dec_use: i2c_pxa_dec_use, + client_register: i2c_pxa_client_register, + client_unregister: i2c_pxa_client_unregister, + retries: 2, +}; + +extern int i2c_pxa_add_bus(struct i2c_adapter *); +extern int i2c_pxa_del_bus(struct i2c_adapter *); + +static int __init i2c_adap_pxa_init(void) +{ + if( i2c_pxa_resource_init() == 0) { + + if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) { + i2c_pxa_resource_release(); + printk(KERN_INFO "I2C: Failed to add bus\n"); + return -ENODEV; + } + } else { + return -ENODEV; + } + + printk(KERN_INFO "I2C: Successfully added bus\n"); + + return 0; +} + +static void i2c_adap_pxa_exit(void) +{ + i2c_pxa_del_bus( &i2c_pxa_ops); + i2c_pxa_resource_release(); + + printk(KERN_INFO "I2C: Successfully removed bus\n"); +} + +module_init(i2c_adap_pxa_init); +module_exit(i2c_adap_pxa_exit); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/i2c/i2c-algo-pxa.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,376 @@ +/* + * i2c-algo-pxa.c + * + * I2C algorithm for the PXA I2C bus access. + * Byte driven algorithm similar to pcf. + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Apr 2002: Initial version [CS] + * Jun 2002: Properly seperated algo/adap [FB] + * Jan 2003: added limited signal handling [Kai-Uwe Bloem] + * Jan 2003: allow SMBUS_QUICK as valid msg [FB] + * + */ +#include +#include + +#include +#include +#include +#include /* struct i2c_msg and others */ +#include + +#include "i2c-pxa.h" + +/* + * Set this to zero to remove all the debug statements via dead code elimination. + */ +//#define DEBUG 1 + +#if DEBUG +static unsigned int i2c_debug = DEBUG; +#else +#define i2c_debug 0 +#endif + +static int pxa_scan = 1; + +static int i2c_pxa_valid_messages( struct i2c_msg msgs[], int num) +{ + int i; + if (num < 1 || num > MAX_MESSAGES){ + if( i2c_debug) + printk(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n", + MAX_MESSAGES, num); + return -EINVAL; + } + + /* check consistency of our messages */ + for (i=0;ialgo_data; + + /* increment number of bytes to read by one -- read dummy byte */ + for (i = 0; i <= count; i++) { + if (i!=0){ + /* set ACK to NAK for last received byte ICR[ACKNAK] = 1 + only if not a repeated start */ + + if ((i == count) && last) { + adap->transfer( last, I2C_RECEIVE, 0); + }else{ + adap->transfer( 0, I2C_RECEIVE, 1); + } + + timeout = adap->wait_for_interrupt(I2C_RECEIVE); + +#ifdef DEBUG + if (timeout==BUS_ERROR){ + printk(KERN_INFO "i2c_pxa_readbytes: bus error -> forcing reset\n"); + adap->reset(); + return I2C_RETRY; + } else +#endif + if (timeout == -ERESTARTSYS) { + adap->abort(); + return timeout; + } else + if (timeout){ +#ifdef DEBUG + printk(KERN_INFO "i2c_pxa_readbytes: timeout -> forcing reset\n"); +#endif + adap->reset(); + return I2C_RETRY; + } + + } + + if (i) { + buf[i - 1] = adap->read_byte(); + } else { + adap->read_byte(); /* dummy read */ + } + } + return (i - 1); +} + +static int i2c_pxa_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, + int count, int last) +{ + + struct i2c_algo_pxa_data *adap = i2c_adap->algo_data; + int wrcount, timeout; + + for (wrcount=0; wrcountwrite_byte(buf[wrcount]); + if ((wrcount==(count-1)) && last) { + adap->transfer( last, I2C_TRANSMIT, 0); + }else{ + adap->transfer( 0, I2C_TRANSMIT, 1); + } + + timeout = adap->wait_for_interrupt(I2C_TRANSMIT); + +#ifdef DEBUG + if (timeout==BUS_ERROR) { + printk(KERN_INFO "i2c_pxa_sendbytes: bus error -> forcing reset.\n"); + adap->reset(); + return I2C_RETRY; + } else +#endif + if (timeout == -ERESTARTSYS) { + adap->abort(); + return timeout; + } else + if (timeout) { +#ifdef DEBUG + printk(KERN_INFO "i2c_pxa_sendbytes: timeout -> forcing reset\n"); +#endif + adap->reset(); + return I2C_RETRY; + } + } + return (wrcount); +} + + +static inline int i2c_pxa_set_ctrl_byte(struct i2c_algo_pxa_data * adap, struct i2c_msg *msg) +{ + u16 flags = msg->flags; + u8 addr; + addr = (u8) ( (0x7f & msg->addr) << 1 ); + if (flags & I2C_M_RD ) + addr |= 1; + if (flags & I2C_M_REV_DIR_ADDR ) + addr ^= 1; + adap->write_byte(addr); + return 0; +} + +static int i2c_pxa_do_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + struct i2c_algo_pxa_data * adap; + struct i2c_msg *pmsg=NULL; + int i; + int ret=0, timeout; + + adap = i2c_adap->algo_data; + + timeout = adap->wait_bus_not_busy(); + + if (timeout) { + return I2C_RETRY; + } + + for (i = 0;ret >= 0 && i < num; i++) { + int last = i + 1 == num; + pmsg = &msgs[i]; + + ret = i2c_pxa_set_ctrl_byte(adap,pmsg); + + /* Send START */ + if (i == 0) { + adap->start(); + }else{ + adap->repeat_start(); + } + + adap->transfer(0, I2C_TRANSMIT, 0); + + /* Wait for ITE (transmit empty) */ + timeout = adap->wait_for_interrupt(I2C_TRANSMIT); + +#ifdef DEBUG + /* Check for ACK (bus error) */ + if (timeout==BUS_ERROR){ + printk(KERN_INFO "i2c_pxa_do_xfer: bus error -> forcing reset\n"); + adap->reset(); + return I2C_RETRY; + } else +#endif + if (timeout == -ERESTARTSYS) { + adap->abort(); + return timeout; + } else + if (timeout) { +#ifdef DEBUG + printk(KERN_INFO "i2c_pxa_do_xfer: timeout -> forcing reset\n"); +#endif + adap->reset(); + return I2C_RETRY; + } +/* FIXME: handle arbitration... */ +#if 0 + /* Check for bus arbitration loss */ + if (adap->arbitration_loss()){ + printk("Arbitration loss detected \n"); + adap->reset(); + return I2C_RETRY; + } +#endif + + /* Read */ + if (pmsg->flags & I2C_M_RD) { + /* read bytes into buffer*/ + ret = i2c_pxa_readbytes(i2c_adap, pmsg->buf, pmsg->len, last); +#if DEBUG > 2 + if (ret != pmsg->len) { + printk(KERN_INFO"i2c_pxa_do_xfer: read %d/%d bytes.\n", + ret, pmsg->len); + } else { + printk(KERN_INFO"i2c_pxa_do_xfer: read %d bytes.\n",ret); + } +#endif + } else { /* Write */ + ret = i2c_pxa_sendbytes(i2c_adap, pmsg->buf, pmsg->len, last); +#if DEBUG > 2 + if (ret != pmsg->len) { + printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d/%d bytes.\n", + ret, pmsg->len); + } else { + printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d bytes.\n",ret); + } +#endif + } + } + + if (ret<0){ + return ret; + }else{ + return i; + } +} + +static int i2c_pxa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + int retval = i2c_pxa_valid_messages( msgs, num); + if( retval > 0) + { + int i; + for (i=i2c_adap->retries; i>=0; i--){ + int retval = i2c_pxa_do_xfer(i2c_adap,msgs,num); + if (retval!=I2C_RETRY){ + return retval; + } + if( i2c_debug)printk(KERN_INFO"Retrying transmission \n"); + udelay(100); + } + if( i2c_debug)printk(KERN_INFO"Retried %i times\n",i2c_adap->retries); + return -EREMOTEIO; + + } + return retval; +} + +struct i2c_algorithm i2c_pxa_algorithm = { + name: "PXA-I2C-Algorithm", + id: I2C_ALGO_PXA, + master_xfer: i2c_pxa_xfer, + smbus_xfer: NULL, + slave_send: NULL, + slave_recv: NULL, + algo_control: NULL, +}; + +/* + * registering functions to load algorithms at runtime + */ +int i2c_pxa_add_bus(struct i2c_adapter *i2c_adap) +{ + struct i2c_algo_pxa_data *adap = i2c_adap->algo_data; + + printk(KERN_INFO"I2C: Adding %s.\n", i2c_adap->name); + + i2c_adap->algo = &i2c_pxa_algorithm; + + MOD_INC_USE_COUNT; + + /* register new adapter to i2c module... */ + i2c_add_adapter(i2c_adap); + + adap->reset(); + + /* scan bus */ + if (pxa_scan) { + int i; + printk(KERN_INFO "I2C: Scanning bus "); + for (i = 0x02; i < 0xff; i+=2) { + if( i==(I2C_PXA_SLAVE_ADDR<<1)) continue; + + if (adap->wait_bus_not_busy()) { + printk(KERN_INFO "I2C: scanning bus %s - TIMEOUTed.\n", + i2c_adap->name); + return -EIO; + } + adap->write_byte(i); + adap->start(); + adap->transfer(0, I2C_TRANSMIT, 0); + + if ((adap->wait_for_interrupt(I2C_TRANSMIT) != BUS_ERROR)) { + printk("(%02x)",i>>1); + adap->abort(); + } else { +// printk("."); + adap->stop(); + } + udelay(adap->udelay); + } + printk("\n"); + } + return 0; +} + +int i2c_pxa_del_bus(struct i2c_adapter *i2c_adap) +{ + int res; + if ((res = i2c_del_adapter(i2c_adap)) < 0) + return res; + + MOD_DEC_USE_COUNT; + + printk(KERN_INFO "I2C: Removing %s.\n", i2c_adap->name); + + return 0; +} + +static int __init i2c_algo_pxa_init (void) +{ + printk(KERN_INFO "I2C: PXA algorithm module loaded.\n"); + return 0; +} + +EXPORT_SYMBOL(i2c_pxa_add_bus); +EXPORT_SYMBOL(i2c_pxa_del_bus); + +MODULE_PARM(pxa_scan, "i"); +MODULE_PARM_DESC(pxa_scan, "Scan for active chips on the bus"); + +MODULE_AUTHOR("Intrinsyc Software Inc."); +MODULE_LICENSE("GPL"); + +module_init(i2c_algo_pxa_init); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/i2c/i2c-pxa.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,76 @@ +/* + * i2c_pxa.h + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef _I2C_PXA_H_ +#define _I2C_PXA_H_ + +struct i2c_algo_pxa_data +{ + void (*write_byte) (u8 value); + u8 (*read_byte) (void); + void (*start) (void); + void (*repeat_start) (void); + void (*stop) (void); + void (*abort) (void); + int (*wait_bus_not_busy) (void); + int (*wait_for_interrupt) (int wait_type); + void (*transfer) (int lastbyte, int receive, int midbyte); + void (*reset) (void); + + int udelay; + int timeout; +}; + +#define DEF_TIMEOUT 3 +#define BUS_ERROR (-EREMOTEIO) +#define ACK_DELAY 0 /* time to delay before checking bus error */ +#define MAX_MESSAGES 65536 /* maximum number of messages to send */ + +#define I2C_SLEEP_TIMEOUT 2 /* time to sleep for on i2c transactions */ +#define I2C_RETRY (-2000) /* an error has occurred retry transmit */ +#define I2C_TRANSMIT 1 +#define I2C_RECEIVE 0 +#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */ +#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */ +/* ICR initialize bit values +* +* 15. FM 0 (100 Khz operation) +* 14. UR 0 (No unit reset) +* 13. SADIE 0 (Disables the unit from interrupting on slave addresses +* matching its slave address) +* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration +* in master mode) +* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) +* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) +* 9. IRFIE 1 (Enable interrupts from full buffer received) +* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) +* 7. GCD 1 (Disables i2c unit response to general call messages as a slave) +* 6. IUE 0 (Disable unit until we change settings) +* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL) +* 4. MA 0 (Only send stop with the ICR stop bit) +* 3. TB 0 (We are not transmitting a byte initially) +* 2. ACKNAK 0 (Send an ACK after the unit receives a byte) +* 1. STOP 0 (Do not send a STOP) +* 0. START 0 (Do not send a START) +* +*/ + +#define I2C_ISR_INIT 0x7FF /* status register init */ +/* I2C status register init values + * + * 10. BED 1 (Clear bus error detected) + * 9. SAD 1 (Clear slave address detected) + * 7. IRF 1 (Clear IDBR Receive Full) + * 6. ITE 1 (Clear IDBR Transmit Empty) + * 5. ALD 1 (Clear Arbitration Loss Detected) + * 4. SSD 1 (Clear Slave Stop Detected) + */ + +#endif --- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -13,5 +13,6 @@ dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200 +dep_tristate ' UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND endmenu --- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -11,13 +11,15 @@ O_TARGET := misc.o -export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o +export-objs := mcp-core.o mcp-sa1100.o mcp-pxa.o \ + ucb1x00-core.o -obj-$(CONFIG_MCP) += mcp-core.o -obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o +obj-$(CONFIG_MCP_SA1100) += mcp-core.o mcp-sa1100.o obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o +obj-$(CONFIG_MCP_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o +obj-$(CONFIG_PXA_CERF_PDA) += cerf_ucb1400gpio.o include $(TOPDIR)/Rules.make --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/misc/cerf_ucb1400gpio.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,189 @@ +/* + * cerf_ucb1400gpio.c + * + * UCB1400 GPIO control stuff for the cerf. + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Mar 2002: Initial version [FB] + * Jun 2002: Removed ac97 dependency [FB] + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ucb1x00.h" + +/* + * Set this to zero to remove all the debug statements via + * dead code elimination. + */ +#define DEBUGGING 0 + +#if DEBUGGING +static unsigned int ucb_debug = DEBUGGING; +#else +#define ucb_debug 0 +#endif + +#define UP 1 +#define DOWN 0 + +/* -- -- */ + +void cerf_ucb1400gpio_lcd_enable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + if( ucb_debug > 2) printk( KERN_INFO "Enabling LCD.\n"); + /* Enable [not] LCD_RESET to enable the LCD display */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET); + ucb1x00_io_write( ucb, UCB1400_GPIO_LCD_RESET, 0); + + /* Enable the Contrast circuit */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA); + ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_ENA, 0); +} + +void cerf_ucb1400gpio_lcd_disable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + if( ucb_debug > 2) printk( KERN_INFO "Disabling LCD.\n"); + /* Disable the Contrast circuit */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA); + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_ENA); + + /* Disable [not] LCD_RESET to enable the LCD display */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET); + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_LCD_RESET); +} + +void cerf_ucb1400gpio_lcd_contrast_step( int direction) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + // Assert the chip select and the up modifier + ucb1x00_io_set_dir( ucb, 0, + (UCB1400_GPIO_CONT_CS | + UCB1400_GPIO_CONT_DOWN | + UCB1400_GPIO_CONT_INC)); + + if( direction == DOWN) + { + if( ucb_debug > 3) + printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: " + "stepping up\n"); + //goin' up + ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_DOWN, 0); + } + else + { + if( ucb_debug > 3) + printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: " + "stepping down\n"); + //goin' down + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN); + } + + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_CS); + + // Assert the line up, down then up again + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC); + udelay(1); + ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_INC, 0); + udelay(1); + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC); + + // Deassert the chip select and the up modifier + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN); + ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_CS, 0); +} + +/* -- -- */ + +void cerf_ucb1400gpio_irda_enable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + printk( KERN_INFO "Enabling IRDA.\n"); + /* Enable IRDA (active low) */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE); + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_IRDA_ENABLE); +} + +void cerf_ucb1400gpio_irda_disable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + printk( KERN_INFO "Disabling IRDA.\n"); + /* Disable IRDA (active low) */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE); + ucb1x00_io_write( ucb, UCB1400_GPIO_IRDA_ENABLE, 0); +} + +/* -- -- */ + +void cerf_ucb1400gpio_bt_enable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + printk( KERN_INFO "Enabling Bluetooth.\n"); + /* Enable BT (active low) */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE); + ucb1x00_io_write( ucb, 0, UCB1400_GPIO_BT_ENABLE); +} + +void cerf_ucb1400gpio_bt_disable( void) +{ + struct ucb1x00 * ucb = ucb1x00_get(); + printk( KERN_INFO "Disabling Bluetooth.\n"); + /* Disable BT (active low) */ + ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE); + ucb1x00_io_write( ucb, UCB1400_GPIO_BT_ENABLE, 0); +} + +/* -- -- */ + +/* -- Enable Bluetooth and IRDA automatically via pseudo module -- */ +#if defined(CONFIG_BLUEZ) || defined(CONFIG_IRDA) +static int __init cerf_ucb1400gpio_module_init (void) +{ +#ifdef CONFIG_BLUEZ + cerf_ucb1400gpio_bt_enable(); +#endif + +#ifdef CONFIG_IRDA + cerf_ucb1400gpio_irda_enable(); +#endif + return 0; +} + +static void __exit cerf_ucb1400gpio_module_exit (void) +{ +#ifdef CONFIG_BLUEZ + cerf_ucb1400gpio_bt_disable(); +#endif + +#ifdef CONFIG_IRDA + cerf_ucb1400gpio_irda_disable(); +#endif +} + +module_init(cerf_ucb1400gpio_module_init); +module_exit(cerf_ucb1400gpio_module_exit); +#endif + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/misc/mcp-pxa.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,57 @@ +/* + * linux/drivers/misc/mcp-pxa.c + * + * 2002-01-10 Jeff Sutherland + * + * 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. + * + * NOTE: This is a quick hack to gain access to the aclink codec's + * touch screen facility. Its audio is handled by a separate + * (non-mcp) driver at the present time. + */ + +#include +#include +#include + +#include "mcp.h" + + +extern int pxa_ac97_get(struct ac97_codec **codec); +extern void pxa_ac97_put(void); + + +struct mcp *mcp_get(void) +{ + struct ac97_codec *codec; + if (pxa_ac97_get(&codec) < 0) + return NULL; + return (struct mcp *)codec; +} + +void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) +{ + struct ac97_codec *codec = (struct ac97_codec *)mcp; + codec->codec_write(codec, reg, val); +} + +unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) +{ + struct ac97_codec *codec = (struct ac97_codec *)mcp; + return codec->codec_read(codec, reg); +} + +void mcp_enable(struct mcp *mcp) +{ + /* + * Should we do something here to make sure the aclink + * codec is alive??? + * A: not for now --NP + */ +} + +void mcp_disable(struct mcp *mcp) +{ +} --- linux-2.4.25/drivers/misc/mcp.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/mcp.h 2004-03-31 17:15:11.000000000 +0200 @@ -10,16 +10,22 @@ #ifndef MCP_H #define MCP_H +#ifdef CONFIG_ARCH_SA1100 +#include +#endif + struct mcp { struct module *owner; spinlock_t lock; int use_count; unsigned int sclk_rate; unsigned int rw_timeout; +#ifdef CONFIG_ARCH_SA1100 dma_device_t dma_audio_rd; dma_device_t dma_audio_wr; dma_device_t dma_telco_rd; dma_device_t dma_telco_wr; +#endif void (*set_telecom_divisor)(struct mcp *, unsigned int); void (*set_audio_divisor)(struct mcp *, unsigned int); void (*reg_write)(struct mcp *, unsigned int, unsigned int); --- linux-2.4.25/drivers/misc/ucb1x00-core.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/ucb1x00-core.c 2004-03-31 17:15:11.000000000 +0200 @@ -23,12 +23,18 @@ #include #include #include +#include +#include -#include -#include #include #include + +#ifdef CONFIG_ARCH_SA1100 +#include #include +#endif + +#include #include "ucb1x00.h" @@ -155,6 +161,10 @@ * * If called for a synchronised ADC conversion, it may sleep * with the ADC semaphore held. + * + * See ucb1x00.h for definition of the UCB_ADC_DAT macro. It + * addresses a bug in the ucb1200/1300 which, of course, Philips + * decided to finally fix in the ucb1400 ;-) -jws */ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) { @@ -218,22 +228,75 @@ * Since we need to read an internal register, we must re-enable * SIBCLK to talk to the chip. We leave the clock running until * we have finished processing all interrupts from the chip. + * + * A restriction with interrupts exists when using the ucb1400, as + * the codec read/write routines may sleep while waiting for codec + * access completion and uses semaphores for access control to the + * AC97 bus. A complete codec read cycle could take anywhere from + * 60 to 100uSec so we *definitely* don't want to spin inside the + * interrupt handler waiting for codec access. So, we handle the + * interrupt by scheduling a RT kernel thread to run in process + * context instead of interrupt context. */ -static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs) + +static int ucb1x00_thread(void *_ucb) { - struct ucb1x00 *ucb = devid; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + struct ucb1x00 *ucb = _ucb; struct ucb1x00_irq *irq; unsigned int isr, i; - ucb1x00_enable(ucb); - isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); - ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); - ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + ucb->rtask = tsk; - for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) - if (isr & 1 && irq->fn) - irq->fn(i, irq->devid); - ucb1x00_disable(ucb); + daemonize(); + reparent_to_init(); + tsk->tty = NULL; + tsk->policy = SCHED_FIFO; + tsk->rt_priority = 1; + strcpy(tsk->comm, "kUCB1x00d"); + + /* only want to receive SIGKILL */ + spin_lock_irq(&tsk->sigmask_lock); + siginitsetinv(&tsk->blocked, sigmask(SIGKILL)); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + + add_wait_queue(&ucb->irq_wait, &wait); + set_task_state(tsk, TASK_INTERRUPTIBLE); + complete(&ucb->complete); + + for (;;) { + if (signal_pending(tsk)) + break; + enable_irq(ucb->irq); + schedule(); + + ucb1x00_enable(ucb); + isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + + for (i = 0, irq = ucb->irq_handler; + i < 16 && isr; + i++, isr >>= 1, irq++) + if (isr & 1 && irq->fn) + irq->fn(i, irq->devid); + ucb1x00_disable(ucb); + + set_task_state(tsk, TASK_INTERRUPTIBLE); + } + + remove_wait_queue(&ucb->irq_wait, &wait); + ucb->rtask = NULL; + complete_and_exit(&ucb->complete, 0); +} + +static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs) +{ + struct ucb1x00 *ucb = devid; + disable_irq(irqnr); + wake_up(&ucb->irq_wait); } /** @@ -291,6 +354,11 @@ spin_lock_irqsave(&ucb->lock, flags); ucb1x00_enable(ucb); + + /* This prevents spurious interrupts on the UCB1400 */ + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx); + ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); + if (edges & UCB_RISING) { ucb->irq_ris_enbl |= 1 << idx; ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); @@ -456,6 +524,7 @@ unsigned int irq_gpio_pin = 0; int irq, default_irq = NO_IRQ; +#ifdef CONFIG_ARCH_SA1100 if (machine_is_adsbitsy()) default_irq = IRQ_GPCIN4; @@ -514,12 +583,40 @@ } #endif +#endif /* CONFIG_ARCH_SA1100 */ + +#ifdef CONFIG_ARCH_PXA_IDP + if (machine_is_pxa_idp()) { + default_irq = TOUCH_PANEL_IRQ; + irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ); + GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin); + } +#endif + +#ifdef CONFIG_ARCH_TRIZEPS2 + if (machine_is_trizeps2()) { + default_irq = TOUCH_PANEL_IRQ; + irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ); + GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin); + } +#endif + + +#ifdef CONFIG_PXA_CERF_PDA + if (machine_is_pxa_cerf()) { + irq_gpio_pin = CERF_GPIO_UCB1400_IRQ; + } +#endif + /* * Eventually, this will disappear. */ if (irq_gpio_pin) +#ifdef CONFIG_ARCH_PXA_IDP + set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE); +#else set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE); - +#endif irq = ucb1x00_detect_irq(ucb); if (irq != NO_IRQ) { if (default_irq != NO_IRQ && irq != default_irq) @@ -541,21 +638,7 @@ struct ucb1x00 *my_ucb; -/** - * ucb1x00_get - get the UCB1x00 structure describing a chip - * @ucb: UCB1x00 structure describing chip - * - * Return the UCB1x00 structure describing a chip. - * - * FIXME: Currently very noddy indeed, which currently doesn't - * matter since we only support one chip. - */ -struct ucb1x00 *ucb1x00_get(void) -{ - return my_ucb; -} - -static int __init ucb1x00_init(void) +static int ucb1x00_init_helper(void) { struct mcp *mcp; unsigned int id; @@ -568,23 +651,28 @@ mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); - if (id != UCB_ID_1200 && id != UCB_ID_1300) { + if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_1400) { printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); goto out; } + /* distinguish between UCB1400 revs 1B and 2A */ + if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a) + id = UCB_ID_1400_BUGGY; + my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL); ret = -ENOMEM; if (!my_ucb) goto out; +#ifdef CONFIG_ARCH_SA1100 if (machine_is_shannon()) { /* reset the codec */ GPDR |= SHANNON_GPIO_CODEC_RESET; GPCR = SHANNON_GPIO_CODEC_RESET; GPSR = SHANNON_GPIO_CODEC_RESET; - } +#endif memset(my_ucb, 0, sizeof(struct ucb1x00)); @@ -599,13 +687,12 @@ if (ret) goto out; + init_waitqueue_head(&my_ucb->irq_wait); ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb); if (ret) { printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", my_ucb->irq, ret); - kfree(my_ucb); - my_ucb = NULL; - goto out; + goto irq_err; } #ifdef CONFIG_PM @@ -616,16 +703,55 @@ my_ucb->pmdev->data = my_ucb; #endif + init_completion(&my_ucb->complete); + ret = kernel_thread(ucb1x00_thread, my_ucb, CLONE_FS | CLONE_FILES); + if (ret >= 0) { + wait_for_completion(&my_ucb->complete); + ret = 0; + goto out; + } + + free_irq(my_ucb->irq, my_ucb); +irq_err: + kfree(my_ucb); + my_ucb = NULL; out: mcp_disable(mcp); no_mcp: return ret; } +/** + * ucb1x00_get - get the UCB1x00 structure describing a chip + * @ucb: UCB1x00 structure describing chip + * + * Return the UCB1x00 structure describing a chip. + * + * FIXME: Currently very noddy indeed, which currently doesn't + * matter since we only support one chip. + */ +struct ucb1x00 *ucb1x00_get(void) +{ + if( !my_ucb) ucb1x00_init_helper(); + + return my_ucb; +} + +static int __init ucb1x00_init(void) +{ + /* check if driver is already initialized */ + if( my_ucb) return 0; + + return ucb1x00_init_helper(); +} + static void __exit ucb1x00_exit(void) { + send_sig(SIGKILL, my_ucb->rtask, 1); + wait_for_completion(&my_ucb->complete); free_irq(my_ucb->irq, my_ucb); kfree(my_ucb); + my_ucb = 0; } module_init(ucb1x00_init); --- linux-2.4.25/drivers/misc/ucb1x00-ts.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/ucb1x00-ts.c 2004-03-31 17:15:11.000000000 +0200 @@ -35,7 +35,11 @@ /* * Define this if you want the UCB1x00 stuff to talk to the input layer */ +#ifdef CONFIG_INPUT +#define USE_INPUT +#else #undef USE_INPUT +#endif #ifndef USE_INPUT @@ -73,7 +77,7 @@ struct pm_dev *pmdev; #endif - wait_queue_head_t irq_wait; + struct semaphore irq_wait; struct semaphore sem; struct completion init_exit; struct task_struct *rtask; @@ -259,6 +263,11 @@ input_report_abs(&ts->idev, ABS_PRESSURE, pressure); } +static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) +{ + input_report_abs(&ts->idev, ABS_PRESSURE, 0); +} + static int ucb1x00_ts_open(struct input_dev *idev) { struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev; @@ -304,10 +313,15 @@ */ static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) { - ucb1x00_reg_write(ts->ucb, UCB_TS_CR, - UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | - UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | - UCB_TS_CR_MODE_INT); + if (ts->ucb->id == UCB_ID_1400_BUGGY) + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_INT); + else + ucb1x00_reg_write(ts->ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_INT); } /* @@ -397,13 +411,13 @@ /* * This is a RT kernel thread that handles the ADC accesses * (mainly so we can use semaphores in the UCB1200 core code - * to serialise accesses to the ADC). + * to serialise accesses to the ADC). The UCB1400 access + * functions are expected to be able to sleep as well. */ static int ucb1x00_thread(void *_ts) { struct ucb1x00_ts *ts = _ts; struct task_struct *tsk = current; - DECLARE_WAITQUEUE(wait, tsk); int valid; ts->rtask = tsk; @@ -429,10 +443,8 @@ valid = 0; - add_wait_queue(&ts->irq_wait, &wait); for (;;) { unsigned int x, y, p, val; - signed long timeout; ts->restart = 0; @@ -457,8 +469,6 @@ val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) { - set_task_state(tsk, TASK_INTERRUPTIBLE); - ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); ucb1x00_disable(ts->ucb); @@ -471,7 +481,15 @@ valid = 0; } - timeout = MAX_SCHEDULE_TIMEOUT; + /* + * Since ucb1x00_enable_irq() might sleep due + * to the way the UCB1400 regs are accessed, we + * can't use set_task_state() before that call, + * and not changing state before enabling the + * interrupt is racy. A semaphore solves all + * those issues quite nicely. + */ + down_interruptible(&ts->irq_wait); } else { ucb1x00_disable(ts->ucb); @@ -486,16 +504,13 @@ } set_task_state(tsk, TASK_INTERRUPTIBLE); - timeout = HZ / 100; + schedule_timeout(HZ / 100); } - schedule_timeout(timeout); if (signal_pending(tsk)) break; } - remove_wait_queue(&ts->irq_wait, &wait); - ts->rtask = NULL; ucb1x00_ts_evt_clear(ts); complete_and_exit(&ts->init_exit, 0); @@ -509,7 +524,7 @@ { struct ucb1x00_ts *ts = id; ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); - wake_up(&ts->irq_wait); + up(&ts->irq_wait); } static int ucb1x00_ts_startup(struct ucb1x00_ts *ts) @@ -525,7 +540,7 @@ if (ts->rtask) panic("ucb1x00: rtask running?"); - init_waitqueue_head(&ts->irq_wait); + sema_init(&ts->irq_wait, 0); ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); if (ret < 0) goto out; @@ -585,7 +600,7 @@ * after sleep. */ ts->restart = 1; - wake_up(&ts->irq_wait); + up(&ts->irq_wait); } return 0; } --- linux-2.4.25/drivers/misc/ucb1x00.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/misc/ucb1x00.h 2004-03-31 17:15:11.000000000 +0200 @@ -10,8 +10,47 @@ #ifndef UCB1200_H #define UCB1200_H +#ifdef CONFIG_ARCH_PXA + +/* ucb1400 aclink register mappings: */ + +#define UCB_IO_DATA 0x5a +#define UCB_IO_DIR 0x5c +#define UCB_IE_RIS 0x5e +#define UCB_IE_FAL 0x60 +#define UCB_IE_STATUS 0x62 +#define UCB_IE_CLEAR 0x62 +#define UCB_TS_CR 0x64 +#define UCB_ADC_CR 0x66 +#define UCB_ADC_DATA 0x68 +#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */ + +#define UCB_ADC_DAT(x) ((x) & 0x3ff) + +#else + +/* ucb1x00 SIB register mappings: */ + #define UCB_IO_DATA 0x00 #define UCB_IO_DIR 0x01 +#define UCB_IE_RIS 0x02 +#define UCB_IE_FAL 0x03 +#define UCB_IE_STATUS 0x04 +#define UCB_IE_CLEAR 0x04 +#define UCB_TC_A 0x05 +#define UCB_TC_B 0x06 +#define UCB_AC_A 0x07 +#define UCB_AC_B 0x08 +#define UCB_TS_CR 0x09 +#define UCB_ADC_CR 0x0a +#define UCB_ADC_DATA 0x0b +#define UCB_ID 0x0c +#define UCB_MODE 0x0d + +#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5) + +#endif + #define UCB_IO_0 (1 << 0) #define UCB_IO_1 (1 << 1) @@ -24,10 +63,6 @@ #define UCB_IO_8 (1 << 8) #define UCB_IO_9 (1 << 9) -#define UCB_IE_RIS 0x02 -#define UCB_IE_FAL 0x03 -#define UCB_IE_STATUS 0x04 -#define UCB_IE_CLEAR 0x04 #define UCB_IE_ADC (1 << 11) #define UCB_IE_TSPX (1 << 12) #define UCB_IE_TSMX (1 << 13) @@ -36,11 +71,9 @@ #define UCB_IRQ_TSPX 12 -#define UCB_TC_A 0x05 #define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */ #define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */ -#define UCB_TC_B 0x06 #define UCB_TC_B_VOICE_ENA (1 << 3) #define UCB_TC_B_CLIP (1 << 4) #define UCB_TC_B_ATT (1 << 6) @@ -49,14 +82,11 @@ #define UCB_TC_B_IN_ENA (1 << 14) #define UCB_TC_B_OUT_ENA (1 << 15) -#define UCB_AC_A 0x07 -#define UCB_AC_B 0x08 #define UCB_AC_B_LOOP (1 << 8) #define UCB_AC_B_MUTE (1 << 13) #define UCB_AC_B_IN_ENA (1 << 14) #define UCB_AC_B_OUT_ENA (1 << 15) -#define UCB_TS_CR 0x09 #define UCB_TS_CR_TSMX_POW (1 << 0) #define UCB_TS_CR_TSPX_POW (1 << 1) #define UCB_TS_CR_TSMY_POW (1 << 2) @@ -72,7 +102,6 @@ #define UCB_TS_CR_TSPX_LOW (1 << 12) #define UCB_TS_CR_TSMX_LOW (1 << 13) -#define UCB_ADC_CR 0x0a #define UCB_ADC_SYNC_ENA (1 << 0) #define UCB_ADC_VREFBYP_CON (1 << 1) #define UCB_ADC_INP_TSPX (0 << 2) @@ -87,15 +116,13 @@ #define UCB_ADC_START (1 << 7) #define UCB_ADC_ENA (1 << 15) -#define UCB_ADC_DATA 0x0b #define UCB_ADC_DAT_VAL (1 << 15) -#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5) -#define UCB_ID 0x0c #define UCB_ID_1200 0x1004 #define UCB_ID_1300 0x1005 +#define UCB_ID_1400 0x4304 +#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */ -#define UCB_MODE 0x0d #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) #define UCB_MODE_AUD_OFF_CAN (1 << 13) @@ -115,6 +142,9 @@ unsigned int irq; struct semaphore adc_sem; spinlock_t io_lock; + wait_queue_head_t irq_wait; + struct completion complete; + struct task_struct *rtask; u16 id; u16 io_dir; u16 io_out; --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,12 @@ +mainmenu_option next_comment +comment 'MMC device drivers' +tristate 'Multi Media Card support' CONFIG_MMC +if [ "$CONFIG_MMC" = "y" -o "$CONFIG_MMC" = "m" ]; then + dep_tristate 'PXA250 MMC driver' CONFIG_MMC_PXA $CONFIG_MMC + dep_tristate 'MMC block driver' CONFIG_MMC_BLOCK $CONFIG_MMC + if [ "$CONFIG_MMC_BLOCK" = "y" -o "$CONFIG_MMC_BLOCK" = "m" ]; then + bool ' MMC partitioning support' CONFIG_MMC_PARTITIONS + fi +fi +endmenu + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,14 @@ +# +# Makefile for MMC drivers +# + +export-objs := mmc_core.o + +obj-$(CONFIG_MMC) += mmc_core.o # mmc_test.o +obj-$(CONFIG_MMC_BLOCK) += mmc_block.o +obj-$(CONFIG_MMC_PXA) += mmc_pxa.o +# EXTRA_CFLAGS += -DCONFIG_MMC_DEBUG -DCONFIG_MMC_DEBUG_VERBOSE=2 + +O_TARGET := mmcdrivers.o + +include $(TOPDIR)/Rules.make --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/error.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,70 @@ +/* + * linux/include/linux/mmc/error.h + * + * Author: Vladimir Shebordaev + * Copyright: MontaVista Software Inc. + * + * $Id: error.h,v 0.2 2002/07/11 16:27:01 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MMC_ERROR_H__ +#define __MMC_ERROR_H__ + +/* MMC protocol card error codes */ +#define MMC_CARD_STATUS_OUT_OF_RANGE (1<<31) +#define MMC_CARD_STATUS_ADDRESS_ERROR (1<<30) +#define MMC_CARD_STATUS_BLOCK_LEN_ERROR (1<<29) +#define MMC_CARD_STATUS_ERASE_SEQ_ERROR (1<<28) +#define MMC_CARD_STATUS_ERASE_PARAM (1<<27) +#define MMC_CARD_STATUS_WP_VIOLATION (1<<26) +#define MMC_CARD_STATUS_CARD_IS_LOCKED (1<<25) +#define MMC_CARD_STATUS_LOCK_UNLOCK_FAILED (1<<24) +#define MMC_CARD_STATUS_COM_CRC_ERROR (1<<23) +#define MMC_CARD_STATUS_ILLEGAL_COMMAND (1<<22) +#define MMC_CARD_STATUS_CARD_ECC_FAILED (1<<21) +#define MMC_CARD_STATUS_CC_ERROR (1<<20) +#define MMC_CARD_STATUS_ERROR (1<<19) +#define MMC_CARD_STATUS_UNDERRUN (1<<18) +#define MMC_CARD_STATUS_OVERRUN (1<<17) +#define MMC_CARD_STATUS_CID_CSD_OVERWRITE (1<<16) +#define MMC_CARD_STATUS_ERASE_RESET (1<<13) + +#define MMC_ERROR( fmt, args... ) printk( KERN_ERR "%s(): " fmt, __FUNCTION__, ##args ) + +/* + * Error codes returned by MMC subsystem functions and + * error reporting function prototypes + */ +enum _mmc_error { +/* controller errors */ + MMC_ERROR_GENERIC = -10000, + MMC_ERROR_CRC_WRITE_ERROR = -10001, + MMC_ERROR_CRC_READ_ERROR = -10002, + MMC_ERROR_RES_CRC_ERROR = -10003, + MMC_ERROR_READ_TIME_OUT = -10004, + MMC_ERROR_TIME_OUT_RESPONSE = -10005, + MMC_ERROR_INVAL = -10006, +/* protocol errors reported in card status (R1 response) */ + MMC_ERROR_OUT_OF_RANGE = -10007, + MMC_ERROR_ADDRESS_ERROR = -10008, + MMC_ERROR_BLOCK_LEN_ERROR = -10009, + MMC_ERROR_ERASE_SEQ_ERROR = -10010, + MMC_ERROR_ERASE_PARAM = -10011, + MMC_ERROR_WP_VIOLATION = -10012, + MMC_ERROR_CARD_IS_LOCKED = -10013, + MMC_ERROR_LOCK_UNLOCK_FAILED = -10014, + MMC_ERROR_COM_CRC_ERROR = -10015, + MMC_ERROR_ILLEGAL_COMMAND = -10016, + MMC_ERROR_CARD_ECC_FAILED = -10017, + MMC_ERROR_CC_ERROR = -10018, + MMC_ERROR_ERROR = -10019, + MMC_ERROR_UNDERRUN = -10020, + MMC_ERROR_OVERRUN = -10021, + MMC_ERROR_CID_CSD_OVERWRITE = -10022, + /* FIXME: incomplete */ + MMC_ERROR_ERASE_RESET = -10025 +}; +#endif /* __MMC_ERROR_H__ */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/mmc.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,463 @@ +/* + * linux/drivers/mmc/mmc.h + * + * Author: Vladimir Shebordaev + * Copyright: MontaVista Software Inc. + * + * $Id: mmc.h,v 0.3.1.8 2002/09/18 12:58:00 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MMC_P_H__ +#define __MMC_P_H__ + +#ifdef __KERNEL__ + +#include +#include + +#include + +#ifdef CONFIG_PROC_FS +#include +#endif + +#include +#include +#include + +#include "types.h" + +#include "error.h" + +#define MMC_CONTROLLERS_MAX (4) +#define MMC_CARDS_MAX (16) + +/* test device */ +#define MMC_TEST_MAJOR (240) +#define MMC_TEST_TRANSFER_MODE_DEFAULT MMC_TRANSFER_MODE_BLOCK_SINGLE + +/* block device */ +#define MMC_BLOCK_MAJOR (241) /* FIXME: MMC_MAJOR */ +#define MMC_BLOCK_DEVICES_MAX (1< */ + +/* private kernel specific data */ + mmc_state_t state; /* card's state as per last operation */ + mmc_card_t next; /* link to the stack */ + mmc_controller_t ctrlr; /* back reference to the controller */ + int usage; /* reference count */ + int slot; /* card's number for device reference */ +/* TODO: async I/O queue */ +#ifdef CONFIG_PROC_FS + proc_dir_entry_t proc; + char proc_name[16]; +#endif + unsigned long card_data[0] /* card specific data */ + __attribute__((aligned (sizeof(unsigned long)))); +}; + +struct _mmc_card_stack_rec { + mmc_card_t first; /* first card on the stack */ + mmc_card_t last; /* last card on the stack */ + mmc_card_t selected; /* currently selected card */ + int ncards; +}; + +struct _mmc_controller_rec { + mmc_controller_state_t state; /* found, initialized, unplugged... */ + int usage; /* reference count */ + int slot; /* host's number for device reference */ + semaphore_t io_sem; /* I/O serialization */ + rwsemaphore_t update_sem; /* card stack check/update serialization */ + + mmc_controller_tmpl_t tmpl; /* methods provided by the driver */ + mmc_card_stack_rec_t stack; /* card stack management data */ + + u32 rca_next; /* next RCA to assign */ + int slot_next; /* next slot number to assign */ +#ifdef CONFIG_PROC_FS + char proc_name[16]; + proc_dir_entry_t proc; +#endif + unsigned long host_data[0] /* driver can request some extra space */ + __attribute__((aligned (sizeof(unsigned long)))); +}; + +/* + * MMC core interface + */ +enum _mmc_reg_type { + MMC_REG_TYPE_USER = 1, + MMC_REG_TYPE_HOST, + MMC_REG_TYPE_CARD +}; + +struct _mmc_notifier_rec { + struct _mmc_notifier_rec *next; + mmc_notifier_fn_t add; + mmc_notifier_fn_t remove; +}; + +enum _mmc_response { + MMC_NORESPONSE = 1, + MMC_R1, + MMC_R2, + MMC_R3, + MMC_R4, + MMC_R5 +}; + +#undef EXTERN +#ifndef __MMC_CORE_IMPLEMENTATION__ +#define EXTERN extern +#else +#define EXTERN /* empty */ +#endif + +EXTERN void *mmc_register( mmc_reg_type_t, void *, size_t ); +EXTERN void mmc_unregister( mmc_reg_type_t, void * ); +EXTERN int mmc_update_card_stack( int ); + +EXTERN mmc_card_t mmc_get_card( int, int );/* get reference to the card */ +EXTERN void mmc_put_card( mmc_card_t ); /* release card reference */ + +EXTERN int mmc_notify_add( mmc_card_t ); /* user notification */ +EXTERN int mmc_notify_remove( mmc_card_t ); + +EXTERN ssize_t mmc_read( mmc_card_t, mmc_transfer_mode_t, char *, size_t, loff_t * ); /* generic read */ +EXTERN ssize_t mmc_write( mmc_card_t, mmc_transfer_mode_t, const char *, size_t, loff_t * ); /* generic write */ +EXTERN int mmc_ioctl( mmc_card_t, unsigned int, unsigned long ); /* generic ioctl */ +/* + * TODO: [?m.b. ioctl()] to erase, lock and write protect + * 1) mmc_erase + * 2) mmc_write_prot + * 3) mmc_lock + */ +#undef EXTERN + +static inline mmc_card_t __mmc_card_alloc( size_t extra ) +{ + mmc_card_t ret = kmalloc( sizeof( mmc_card_rec_t ) + extra, GFP_KERNEL ); + + if ( ret ) { + memset( ret, 0, sizeof( mmc_card_rec_t ) + extra ); + } + + return ret; +} + +static inline void __mmc_card_free( mmc_card_t card ) +{ + if ( card ) { + kfree( card ); + } +} + +static inline mmc_card_stack_t __mmc_card_stack_init( mmc_card_stack_t stack ) +{ + mmc_card_stack_t ret = NULL; + if ( stack ) { + memset( stack, 0, sizeof( mmc_card_stack_rec_t ) ); + ret = stack; + } + return ret; +} + +static inline mmc_card_stack_t __mmc_card_stack_add( mmc_card_stack_t stack, mmc_card_t card ) +{ + mmc_card_stack_t ret = NULL; + + if ( stack && card ) { + card->next = NULL; + + if ( stack->first ) { + stack->last->next = card; + stack->last = card; + } else + stack->first = stack->last = card; + + ++stack->ncards; + ret = stack; + } + return ret; +} + +static inline mmc_card_stack_t __mmc_card_stack_remove( mmc_card_stack_t stack, mmc_card_t card ) +{ + mmc_card_stack_t ret = NULL; + register mmc_card_t prev; + int found = FALSE; + + if ( !stack || !card ) + goto error; + + if ( stack->ncards > 0 ) { + if ( stack->first == card ) { + stack->first = stack->first->next; + if ( stack->last == card ) + stack->last = stack->last->next; + found = TRUE; + } else { + for ( prev = stack->first; prev; prev = prev->next ) + if ( prev->next == card ) { + found = TRUE; + break; + } + if ( found ) { + if ( prev->next == stack->last ) + stack->last = prev->next; + prev->next = prev->next->next; + } + } + if ( found ) { + --stack->ncards; + ret = stack; + } + } +error: + return ret; +} + +static inline void __mmc_card_stack_free( mmc_card_stack_t stack ) +{ + mmc_card_t card, next; + + if ( stack && (stack->ncards > 0) ) { + card = stack->first; + while ( card ) { + next = card->next; + kfree( card ); + card = next; + } + __mmc_card_stack_init( stack ); + } +} + +static inline int __mmc_card_stack_foreach( mmc_card_stack_t stack, mmc_notifier_fn_t fn, int unplugged_also ) +{ + int ret = 0; + register mmc_card_t card = NULL; + + if ( stack && fn ) { + for ( card = stack->first; card; card = card->next ) + if ( (card->state != MMC_CARD_STATE_UNPLUGGED) + || unplugged_also ) + if ( fn( card ) ) { + ret = -card->slot; + break; + } + } + + return ret; +} + +/* + * Debugging macros + */ +#ifdef CONFIG_MMC_DEBUG + +#define MMC_DEBUG_LEVEL0 (0) /* major */ +#define MMC_DEBUG_LEVEL1 (1) +#define MMC_DEBUG_LEVEL2 (2) /* device */ +#define MMC_DEBUG_LEVEL3 (3) /* protocol */ +#define MMC_DEBUG_LEVEL4 (4) /* everything */ + +#define MMC_DEBUG(n, args...) \ +if (n <= CONFIG_MMC_DEBUG_VERBOSE) { \ + printk(KERN_INFO __FUNCTION__ "(): " args); \ +} +#define __ENTER0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry\n" ); +#define __LEAVE0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit\n" ); +#define __ENTER( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry: " format "\n", args ); +#define __LEAVE( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit: " format "\n", args ); + +#define MMC_DUMP_CSD( card ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \ +"CSD register:\n" \ +" csd_structure=%u\n" \ +" spec_vers=%u\n" \ +" taac=%x\n" \ +" nsac=%x\n" \ +" tran_speed=%x\n" \ +" ccc=%x\n" \ +" read_bl_len=%u\n" \ +" read_bl_partial=%u\n" \ +" write_blk_misalign=%u\n" \ +" read_blk_misalign=%u\n" \ +" dsr_imp=%u\n" \ +" c_size=%u\n" \ +" vdd_r_curr_min=%u\n" \ +" vdd_r_curr_max=%u\n" \ +" vdd_w_curr_min=%u\n" \ +" vdd_w_curr_max=%u\n" \ +" c_size_mult=%u\n" \ +" erase_grp_size=%u\n" \ +" erase_grp_mult=%u\n" \ +" wp_grp_size=%u\n" \ +" wp_grp_enable=%u\n" \ +" default_ecc=%u\n" \ +" r2w_factor=%u\n" \ +" write_bl_len=%u\n" \ +" write_bl_partial=%u\n" \ +" content_prot_app=%u\n" \ +" file_format_grp=%u\n" \ +" copy=%u\n" \ +" perm_write_protect=%d\n" \ +" tmp_write_protect=%d\n" \ +" file_format=%d\n" \ +" ecc=%d\n", \ +card->info.csd.csd_structure, \ +card->info.csd.spec_vers, \ +card->info.csd.taac, \ +card->info.csd.nsac, \ +card->info.csd.tran_speed, \ +card->info.csd.ccc, \ +card->info.csd.read_bl_len, \ +card->info.csd.read_bl_partial, \ +card->info.csd.write_blk_misalign, \ +card->info.csd.read_blk_misalign, \ +card->info.csd.dsr_imp, \ +card->info.csd.c_size, \ +card->info.csd.vdd_r_curr_min, \ +card->info.csd.vdd_r_curr_max, \ +card->info.csd.vdd_w_curr_min, \ +card->info.csd.vdd_w_curr_max, \ +card->info.csd.c_size_mult, \ +card->info.csd.erase_grp_size, \ +card->info.csd.erase_grp_mult, \ +card->info.csd.wp_grp_size, \ +card->info.csd.wp_grp_enable, \ +card->info.csd.default_ecc, \ +card->info.csd.r2w_factor, \ +card->info.csd.write_bl_len, \ +card->info.csd.write_bl_partial, \ +card->info.csd.content_prot_app, \ +card->info.csd.file_format_grp, \ +card->info.csd.copy, \ +card->info.csd.perm_write_protect, \ +card->info.csd.tmp_write_protect, \ +card->info.csd.file_format, \ +card->info.csd.ecc ); + +#else /* CONFIG_MMC_DEBUG */ +#define MMC_DEBUG(n, args...) /* empty */ +#define __ENTER0( ) /* empty */ +#define __LEAVE0( ) /* empty */ +#define __ENTER( args... ) /* empty */ +#define __LEAVE( args... ) /* empty */ +#define MMC_DUMP_CSD( card ) /* empty */ +#endif /* CONFIG_MMC_DEBUG */ + +/* + * Miscellaneous defines + */ +#ifndef MMC_DUMP_R1 +#define MMC_DUMP_R1( ctrlr ) /* empty */ +#endif +#ifndef MMC_DUMP_R2 +#define MMC_DUMP_R2( ctrlr ) /* empty */ +#endif +#ifndef MMC_DUMP_R3 +#define MMC_DUMP_R3( ctrlr ) /* empty */ +#endif + +#endif /* __KERNEL__ */ + +#endif /* __MMC_P_H__ */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/mmc_block.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,989 @@ +/* + * linux/drivers/mmc/mmc_block.c + * driver for the block device on the MMC card + * + * Author: Vladimir Shebordaev + * Copyright: MontaVista Software Inc. + * + * $Id: mmc_block.c,v 0.3.1.16 2002/09/27 17:36:09 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "types.h" +#include "mmc.h" +#include "error.h" + +#define MAJOR_NR MMC_BLOCK_MAJOR +#define MAJOR_NAME "mmc" +#define DEVICE_NAME "mmc_block" +#define DEVICE_REQUEST mmc_block_request +#define DEVICE_NR(device) (device) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) +#define DEVICE_NO_RANDOM +#include +/* for old kernels... */ +#ifndef QUEUE_EMPTY +#define QUEUE_EMPTY (!CURRENT) +#endif +#if LINUX_VERSION_CODE < 0x20300 +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) +#else +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) +#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT +#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT +#else +#define BLK_INC_USE_COUNT do {} while(0) +#define BLK_DEC_USE_COUNT do {} while(0) +#endif + +#define MMC_BLOCK_RAW_DEVICE( device ) ((device>>MMC_BLOCK_PARTNBITS)<usage = 0; + dev->card = NULL; + dev->host = minor >> MMC_MINOR_HOST_SHIFT; + dev->slot = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS; + dev->rdev = MKDEV( MMC_BLOCK_MAJOR, minor ); +} + +static inline int __mmc_block_validate_device( kdev_t rdev ) +{ + int ret = -1; + int minor = MINOR( rdev ); + + if ( mmc_block_device[minor].card + && (mmc_block_gendisk.part[minor].nr_sects > 0) ) + ret = 0; + + return ret; +} + +static inline int __mmc_block_invalidate_card( mmc_card_t card, int invalidate ) +{ + int ret = 0; + kdev_t start; + int minor; + + __ENTER( "card = 0x%p", card ); + + if ( card && card->ctrlr ) { + register int i; + + start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot ); + minor = MINOR( start ); + + __mmc_block_wrlock_devices(); + for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) { + if ( invalidate ) + invalidate_device( start + i, 0 ); + + __mmc_block_device_init( minor + i ); + + mmc_block_gendisk.part[minor + i].nr_sects = 0; + mmc_block_gendisk.part[minor + i].start_sect = 0; + } + __mmc_block_wrunlock_devices(); + } + + __LEAVE( "ret=%d", ret ); + return ret; +} + +static inline int mmc_block_invalidate_card( int host, int slot, int invalidate ) +{ + int ret = 0; + kdev_t start; + int minor; + + __ENTER( "host=%d slot=%d", host, slot ); + + if ( (host >= 0) && (slot >= 0) ) { + register int i; + mmc_card_t card = NULL; + + start = MMC_BLOCK_MKDEV( host, slot ); + minor = MINOR( start ); + + __mmc_block_wrlock_devices(); + for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) { + if ( !card ) + card = mmc_block_device[minor + i].card; + + if ( invalidate ) + invalidate_device( start + i, 0 ); + + __mmc_block_device_init( minor + i ); + + mmc_block_gendisk.part[minor + i].nr_sects = 0; + mmc_block_gendisk.part[minor + i].start_sect = 0; + } + if ( card ) + mmc_put_card( card ); + __mmc_block_wrunlock_devices(); + } + + __LEAVE( "ret=%d", ret ); + return ret; +} + +/* Get device reference locked for writing */ +static inline mmc_block_device_t __mmc_block_get_device( kdev_t rdev ) +{ + mmc_block_device_t ret = NULL; + u8 minor = MINOR( rdev ); + int host_no, card_no; + + __ENTER( "rdev=%x:%x", MAJOR( rdev ), MINOR( rdev ) ); + + host_no = minor >> MMC_MINOR_HOST_SHIFT; + if ( host_no >= MMC_CONTROLLERS_MAX ) + goto error; + + card_no = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS; + if ( card_no >= MMC_CARDS_MAX ) + goto error; + + __mmc_block_lock_device( rdev ); + if ( __mmc_block_validate_device( rdev ) ) { + __mmc_block_unlock_device( rdev ); + goto error; + } + + ret = &mmc_block_device[minor]; + MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n", + MAJOR( ret->rdev ), MINOR( ret->rdev ), + ret->card, ret->usage ); +error: + __LEAVE( "ret=0x%p", ret ); + return ret; +} + +/* Unlocks the device */ +static inline void __mmc_block_put_device( mmc_block_device_t dev ) +{ + __ENTER0(); + + if ( dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n", + MAJOR( dev->rdev ), MINOR( dev->rdev ), + dev->card, dev->usage ); + __mmc_block_unlock_device( dev->rdev ); + } + + __LEAVE0(); +} + +/* Atomically increases use count of the valid device */ +static inline mmc_block_device_t mmc_block_get_device( kdev_t rdev ) +{ + mmc_block_device_t ret = NULL; + + __ENTER0(); + + ret = __mmc_block_get_device( rdev ); + if ( !ret ) + goto error; + + ret->usage++; + __mmc_block_put_device( ret ); +error: + __LEAVE( "ret=0x%p dusage=%d card=0x%p cusage=%d", + ret, ret ? ret->usage : -1, + ret ? ret->card : NULL, + ret ? (ret->card ? ret->card->usage : -1) : -1 ); + return ret; +} + +/* Check is there references to the card */ +static inline int __mmc_block_check_card( kdev_t rdev ) +{ + int ret = TRUE; + int start = MINOR( MMC_BLOCK_RAW_DEVICE( rdev ) ); + register int i; + + for ( i = 0; i < mmc_block_gendisk.max_p; i++ ) + if ( mmc_block_device[start + i].usage > 0 ) { + ret = FALSE; + break; + } + + return ret; +} + +/* Atomically decreases device use count */ +static inline void mmc_block_put_device( mmc_block_device_t dev ) +{ + __ENTER0(); + + if ( dev ) { + int invalidate = FALSE; + + __mmc_block_get_device( dev->rdev ); + if ( dev->usage > 0 ) + --dev->usage; + + if ( dev->usage ) { + __mmc_block_put_device( dev ); + goto out; + + } else { + int host, slot; + mmc_card_t card = NULL; + + invalidate = __mmc_block_check_card( dev->rdev ); + if ( invalidate ) { + host = dev->card->ctrlr->slot; + slot = dev->card->slot; + + if ( dev->card ) { + card = dev->card; + mmc_put_card( dev->card ); + dev->card = NULL; + } + } + __mmc_block_put_device( dev ); + + if ( invalidate ) + __mmc_block_invalidate_card( card, TRUE ); + } + + } +out: + __LEAVE0(); +} + +static int mmc_block_open( struct inode *inode, struct file *file ) +{ + int ret = -ENODEV; + mmc_block_device_t dev = NULL; + + __ENTER0(); + + if ( !inode || !file ) + goto error; + + BLK_INC_USE_COUNT; + + check_disk_change( inode->i_rdev ); + + dev = mmc_block_get_device( inode->i_rdev ); + if ( !dev ) + goto error; + + dev = __mmc_block_get_device( inode->i_rdev ); + if ( !dev ) + goto error; + + if ( file->f_mode & FMODE_WRITE ) { /* FIXME */ + if ( dev->usage > 1 ) { + ret = -EBUSY; + __mmc_block_put_device( dev ); + mmc_block_put_device( dev ); + goto error; + } + } + + __mmc_block_put_device( dev ); + + if ( file ) + file->private_data = dev; + + ret = 0; + goto out; +error: + BLK_DEC_USE_COUNT; +out: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static int mmc_block_release( struct inode *inode, struct file *file ) +{ + int ret = -EINVAL; + mmc_block_device_t dev = NULL; + + __ENTER( "inode=0x%p file=0x%p rdev=(%x:%x)", inode, file, + inode ? MAJOR( inode->i_rdev ) : 0xff, + inode ? MINOR( inode->i_rdev ) : 0xff ); + + if ( !file && !inode ) + goto error; + + if ( file ) + dev = file->private_data; + else + dev = __mmc_block_get_device( inode->i_rdev ); + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" ); + goto error; + } + + if ( file ) { + mmc_block_put_device( dev ); + file->private_data = NULL; + + } else { + int invalidate = FALSE; + + if ( dev->usage > 0 ) + --dev->usage; + + if ( dev->usage ) { + __mmc_block_put_device( dev ); + goto out; + + } else { + int host, slot; + mmc_card_t card = NULL; + + invalidate = __mmc_block_check_card( dev->rdev ); + if ( invalidate ) { + host = dev->card->ctrlr->slot; + slot = dev->card->slot; + + if ( dev->card ) { + card = dev->card; + mmc_put_card( dev->card ); + dev->card = NULL; + } + } + __mmc_block_put_device( dev ); + + if ( invalidate ) + __mmc_block_invalidate_card( card, TRUE ); + + } + } + +out: + BLK_DEC_USE_COUNT; + ret = 0; +error: + __LEAVE0(); + return ret; +} + +static int mmc_block_check_disk_change( kdev_t rdev ) +{ + int ret = 0; +#if 0 + mmc_block_device_t dev = &mmc_block_device[MINOR( rdev )]; + + __mmc_block_lock_device( rdev ); + if ( !dev->card ) + ret = 1; + __mmc_block_unlock_device( rdev ); +#else + ret = 1; +#endif + return ret; +} + +static int mmc_block_revalidate( kdev_t rdev ) +{ + int ret = 1; + mmc_card_t card; + mmc_block_device_t dev; + kdev_t start = MMC_BLOCK_RAW_DEVICE( rdev ); + int minor = MINOR( start ); + int host, slot; + int i; + + __ENTER0(); + + (void)mmc_update_card_stack( MINOR( start )>>MMC_MINOR_HOST_SHIFT ); + + __mmc_block_wrlock_devices(); + + dev = &mmc_block_device[minor]; + host = dev->host; + slot = dev->slot; + + if ( dev->card ) { /* card has not been changed actually */ + __mmc_block_wrunlock_devices(); + goto out; + + } else { + card = mmc_get_card( host, slot ); + if ( !card ) { + MMC_DEBUG( MMC_DEBUG_LEVEL2, "failed to get card: " + "host=%d, slot=%d\n", host, slot ); + __mmc_block_wrunlock_devices(); + goto error; + } + dev->card = card; + } + __mmc_block_wrunlock_devices(); + /* FIXME */ + __mmc_block_rdlock_devices(); /* handle the request for sector 0 */ + grok_partitions( &mmc_block_gendisk, MINOR( start ), + mmc_block_gendisk.max_p, + card->info.capacity>>9 /* sectors */ + ); + __mmc_block_rdunlock_devices(); + /* FIXME */ + __mmc_block_wrlock_devices(); + for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) { + int minor = MINOR( i ); + + dev = &mmc_block_device[minor]; + if ( mmc_block_gendisk.part[minor].nr_sects > 0 ) + dev->card = card; + } + __mmc_block_wrunlock_devices(); +out: +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static void mmc_block_handle_request( void ) +{ + struct request *request; + mmc_block_device_t dev; + mmc_card_t card; + char *buf; + loff_t pos; + unsigned int result = 0; + + for (;;) { + int minor; + + INIT_REQUEST; + request = CURRENT; + spin_unlock_irq( &io_request_lock ); + + minor = MINOR( request->rq_dev ); + dev = __mmc_block_get_device( request->rq_dev ); + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL2, "invalid device (%x:%x)\n", + MAJOR( request->rq_dev ), minor ); + + goto end_req; + } + + card = dev->card; + (void)__mmc_block_put_device( dev ); + + MMC_DEBUG( MMC_DEBUG_LEVEL2, +// printk( KERN_INFO __FUNCTION__"(): " + "request %p: cmd %i sec %li (nr. %li)\n", + CURRENT, CURRENT->cmd, CURRENT->sector, + CURRENT->current_nr_sectors ); + + if ( request->current_nr_sectors > + mmc_block_gendisk.part[minor].nr_sects ) + goto end_req; + + // Handle the request + // TODO: handle clusterred requests in multiple block transfer mode + buf = request->buffer; + pos = (mmc_block_gendisk.part[minor].start_sect + + request->sector) * MMC_BLOCK_SECT_SIZE; + + switch ( request->cmd ) + { + int i, ret; + + case READ: +#if 0 + ret = mmc_read( card, + (request->current_nr_sectors > 1) ? + MMC_TRANSFER_MODE_BLOCK_MULTIPLE : + MMC_TRANSFER_MODE_BLOCK_SINGLE, + buf, + request->current_nr_sectors + * MMC_BLOCK_SECT_SIZE, /* FIXME */ + &pos ); + if ( ret < 0 ) + goto end_req; + +#else + for ( i = 0; + i < request->current_nr_sectors; + i++ ) { + ret = mmc_read( card, + MMC_TRANSFER_MODE_BLOCK_SINGLE, + buf, + MMC_BLOCK_SECT_SIZE, /* FIXME */ + &pos ); + if ( ret < 0 ) + goto end_req; + else + buf += ret; + } +#endif + result = 1; + break; + + case WRITE: + // TODO: Read only device +#if 0 + ret = mmc_write( card, + (request->current_nr_sectors > 1) ? + MMC_TRANSFER_MODE_BLOCK_MULTIPLE : + MMC_TRANSFER_MODE_BLOCK_SINGLE, + buf, + request->current_nr_sectors + * MMC_BLOCK_SECT_SIZE, /* FIXME */ + &pos ); + if ( ret < 0 ) + goto end_req; + +#else + for ( i = 0; + i < request->current_nr_sectors; + i++ ) { + ret = mmc_write( card, + MMC_TRANSFER_MODE_BLOCK_SINGLE, + buf, + MMC_BLOCK_SECT_SIZE, /* FIXME */ + &pos ); + if ( ret < 0 ) + goto end_req; + else + buf += ret; + } +#endif + result = 1; + break; + } + +end_req: + __LEAVE( "result=%d", result ); + spin_lock_irq( &io_request_lock ); + end_request( result ); + } +} + +static volatile int leaving = 0; +static DECLARE_MUTEX_LOCKED( thread_sem ); +static DECLARE_WAIT_QUEUE_HEAD( thr_wq ); +static pid_t thr_id = -1; + +int mmc_block_thread( void *arg ) +{ + struct task_struct *task = current; + DECLARE_WAITQUEUE(wait, task); + + __ENTER0(); + + task->session = 1; + task->pgrp = 1; + task->flags |= PF_MEMALLOC; + strcpy( task->comm, "mmcblockd" ); + task->tty = NULL; + spin_lock_irq( &task->sigmask_lock ); + sigfillset( &task->blocked ); + recalc_sigpending( task ); + spin_unlock_irq( &task->sigmask_lock ); + exit_mm( task ); + exit_files( task ); + exit_sighand( task ); + exit_fs( task ); + + while ( !leaving ) { + add_wait_queue( &thr_wq, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + spin_lock_irq( &io_request_lock ); + if ( QUEUE_EMPTY || QUEUE_PLUGGED ) { + spin_unlock_irq( &io_request_lock ); + schedule(); + remove_wait_queue( &thr_wq, &wait ); + } else { + remove_wait_queue( &thr_wq, &wait ); + set_current_state( TASK_RUNNING ); + mmc_block_handle_request(); /* handle the request */ + spin_unlock_irq( &io_request_lock ); + } + } + + up( &thread_sem ); + + __LEAVE0(); + return 0; +} + +#if LINUX_VERSION_CODE < 0x20300 +#define RQFUNC_ARG void +#else +#define RQFUNC_ARG request_queue_t *q +#endif + +static void mmc_block_request( RQFUNC_ARG ) +{ + wake_up( &thr_wq ); +} + +static int mmc_block_ioctl( struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg ) +{ + int ret = -ENODEV; + mmc_block_device_t dev; + mmc_card_t card; + int minor; + __ENTER0(); + + if ( !inode || !file ) { + ret = -EINVAL; + goto error; + } + minor = MINOR( inode->i_rdev ); + + dev = __mmc_block_get_device( inode->i_rdev ); + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" ); + goto error; + } + + card = dev->card; + __mmc_block_put_device( dev ); + + switch ( cmd ) { + case BLKGETSIZE: /* Return device size */ + { + unsigned long value; + + __mmc_block_rdlock_devices(); + value = mmc_block_gendisk.part[minor].nr_sects; + __mmc_block_rdunlock_devices(); + + if ( put_user( value, (unsigned long *) arg) ) { + ret = -EFAULT; + goto error; + } + } + break; + +#ifdef BLKGETSIZE64 + case BLKGETSIZE64: + { + unsigned long value; + + __mmc_block_rdlock_devices(); + value = mmc_block_gendisk.part[minor].nr_sects; + __mmc_block_rdunlock_devices(); + + if ( put_user( (u64)value, (u64 *) arg) ) { + ret = -EFAULT; + goto error; + } + } + break; +#endif + + case HDIO_GETGEO: + { + struct hd_geometry geo; + + ret = !access_ok( VERIFY_WRITE, arg, sizeof( geo ) ); + if ( ret ) { + ret = -EFAULT; + goto error; + } + + geo.heads = 1; + geo.sectors = 1; + + __mmc_block_rdlock_devices(); + geo.cylinders = mmc_block_gendisk.part[minor].nr_sects; + geo.start = mmc_block_gendisk.part[minor].start_sect; + __mmc_block_rdunlock_devices(); + + if ( copy_to_user( (int *)arg, &geo, sizeof( geo ) ) ) { + ret = -EFAULT; + goto error; + } + } + break; + + case BLKRRPART: + if ( !capable( CAP_SYS_ADMIN ) ) { + ret = -EACCES; + goto error; + } + (void)mmc_block_revalidate( inode->i_rdev ); + break; + + default: + ret = blk_ioctl( inode->i_rdev, cmd, arg ); + goto out; + } + + ret = 0; +error: +out: + __LEAVE( "ret=%d", ret ); + return ret; +} + +#if LINUX_VERSION_CODE < 0x20326 +static struct file_operations mmc_block_fops = +{ + open: mmc_block_open, + ioctl: mmc_block_ioctl, + release: mmc_block_release, + check_media_change: mmc_block_check_disk_change, + revalidate: mmc_block_revalidate, + read: block_read, + write: block_write +}; +#else +static struct block_device_operations mmc_block_fops = +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14) + owner: THIS_MODULE, +#endif + open: mmc_block_open, + release: mmc_block_release, + ioctl: mmc_block_ioctl, + check_media_change: mmc_block_check_disk_change, + revalidate: mmc_block_revalidate +}; +#endif + + +static int mmc_block_notify_add( mmc_card_t card ) +{ + int ret = -1; + mmc_block_device_t dev; + kdev_t start; + int minor; + + __ENTER0(); + + if ( !card || !card->ctrlr ) + goto error; + + start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot ); + dev = &mmc_block_device[MINOR( start )]; + + __mmc_block_wrlock_devices(); + if ( !dev->card ) { + dev->card = card; + ret = 0; + } + __mmc_block_wrunlock_devices(); + + if ( !ret ) { + int i; + + /* allow to read partition table */ + __mmc_block_rdlock_devices(); + grok_partitions( &mmc_block_gendisk, MINOR( start ), + mmc_block_gendisk.max_p, + card->info.capacity>>9 /* sectors */ + ); + __mmc_block_rdunlock_devices(); + + __mmc_block_wrlock_devices(); + for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) { + minor = MINOR( i ); + dev = &mmc_block_device[minor]; + if ( mmc_block_gendisk.part[minor].nr_sects > 0 ) + dev->card = card; + } + __mmc_block_wrunlock_devices(); + } +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + + +static int mmc_block_notify_remove( mmc_card_t card ) +{ + int ret = -1; + + __ENTER( "card=0x%p", card ); + + if ( card && card->ctrlr ) + ret = __mmc_block_invalidate_card( card, FALSE ); + + __LEAVE( "ret=%d", ret ); + return ret; +} + +static mmc_notifier_rec_t mmc_block_notifier = { + add: mmc_block_notify_add, + remove: mmc_block_notify_remove +}; + +static int __init mmc_block_module_init( void ) +{ + int ret = -ENODEV; + int i; + + __ENTER0(); + + init_rwsem( &mmc_block_device_sem ); + + if ( devfs_register_blkdev( MAJOR_NR, MAJOR_NAME, &mmc_block_fops ) ) { + MMC_ERROR( "Can't allocate major number %d for MMC block devices.\n", MMC_BLOCK_MAJOR ); + ret = -EAGAIN; + goto error; + } + + for ( i = 0; i < (1< +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_PM +#include +#endif + +#include +#include +#include + +#include "types.h" + +#define __MMC_CORE_IMPLEMENTATION__ +#include "mmc.h" + +/* MMC controllers registered in the system */ +static mmc_controller_t mmc_controller[MMC_CONTROLLERS_MAX]; +static int mmc_ncontrollers = 0; +static rwsemaphore_t mmc_controller_sem; /* controller table lock */ +#ifdef CONFIG_PM +static struct pm_dev *mmc_pm_dev = NULL; +#endif + +/* users' notification list */ +static mmc_notifier_t mmc_notifier = NULL; +static rwsemaphore_t mmc_notifier_sem; /* notifiers' list lock */ +#ifdef CONFIG_PROC_FS +static proc_dir_entry_t mmc_proc_dir = NULL; +#endif + +/************************************************ + * service function prototypes and declarations * + ************************************************/ +static inline int mmc_acquire_io( mmc_controller_t ctrlr, mmc_card_t card ) +{ + int ret = -EIO; + + __ENTER0(); + + if ( !card || !ctrlr ) { + ret = -EINVAL; + goto error; + } +#ifdef CONFIG_HOTPLUG +/* TODO: account for controller removal */ +#endif + down( &ctrlr->io_sem ); +#if 0 + down_read( &ctrlr->update_sem ); /* FIXME */ + if ( card->state != MMC_CARD_STATE_UNPLUGGED ) + ret = 0; + up_read( &ctrlr->update_sem ); + + if ( ret ) + up( &ctrlr->io_sem ); +#else + ret = 0; +#endif + +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static inline void mmc_release_io( mmc_controller_t ctrlr, mmc_card_t card ) +{ + __ENTER0(); +#ifdef CONFIG_HOTPLUG +/* TODO: account for controller removal */ +#endif + if ( !card && !ctrlr ) { /* FIXME */ + MMC_DEBUG( MMC_DEBUG_LEVEL2, "bad card reference\n" ); + goto error; + } + up( &ctrlr->io_sem ); +error: + __LEAVE0(); +} + +/* TODO: there should be a separate context to be awaken + * by the card intertion interrupt; called under ctrlr->update_sem + * held down by now */ +static int __mmc_update_card_stack( mmc_controller_t ctrlr ) +{ + int ret = -1; + mmc_card_t card, prev; + + __ENTER0(); + + if ( !ctrlr || !ctrlr->tmpl ) + goto error; + + /* check unplugged cards first... */ + if ( (ret = ctrlr->tmpl->check_card_stack( ctrlr )) ) + goto error; + + /* unregister unplugged cards and free 'em immediately */ + if ( ctrlr->stack.ncards > 0 ) { + prev = ctrlr->stack.first; + /* process the stack tail first */ + if ( prev->next ) { + card = prev->next; + while ( card ) { + if ( card->state == MMC_CARD_STATE_UNPLUGGED ) { + if ( ctrlr->stack.selected == card ) + ctrlr->stack.selected = NULL; +#ifdef CONFIG_PROC_FS + if ( card->proc ) { + remove_proc_entry( card->proc_name, ctrlr->proc ); + card->proc = NULL; + } +#endif + ctrlr->slot_next = card->slot; /* FIXME */ + prev->next = card->next; + if ( ctrlr->stack.last == card ) + ctrlr->stack.last = prev; + /* FIXME: controller use count */ + mmc_notify_remove( card ); + --ctrlr->stack.ncards; + if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) { + --ctrlr->usage; + MMC_DEBUG( MMC_DEBUG_LEVEL2, + "'%s' use count " + "decreased (%d)\n", + ctrlr->tmpl->name, + ctrlr->usage ); + __MOD_DEC_USE_COUNT( + ctrlr->tmpl->owner ); + } + __mmc_card_free( card ); + + card = prev->next; + } + } + } + /* then the head */ + card = ctrlr->stack.first; + if ( card && (card->state == MMC_CARD_STATE_UNPLUGGED) ) { + if ( ctrlr->stack.selected == card ) + ctrlr->stack.selected = NULL; +#ifdef CONFIG_PROC_FS + if ( card->proc ) { + remove_proc_entry( card->proc_name, ctrlr->proc ); + card->proc = NULL; + } +#endif + ctrlr->slot_next = card->slot; /* FIXME */ + mmc_notify_remove( card ); /* FIXME: should unregister here */ + ctrlr->stack.first = card->next; + if ( ctrlr->stack.last == card ) + ctrlr->stack.last = NULL; + /* FIXME: controller use count */ + --ctrlr->stack.ncards; + if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) { + --ctrlr->usage; + MMC_DEBUG( MMC_DEBUG_LEVEL2, "'%s' use count " + "decreased (%d)\n", ctrlr->tmpl->name, + ctrlr->usage ); + __MOD_DEC_USE_COUNT( ctrlr->tmpl->owner ); + } + __mmc_card_free( card ); + } + } + MMC_DEBUG( MMC_DEBUG_LEVEL2, "after stack check: ncards=%d" + " first=0x%x last=0x%x\n", ctrlr->stack.ncards, + ctrlr->stack.first, ctrlr->stack.last ); + /* ...then add newly inserted ones */ + if ( (ret = ctrlr->tmpl->update_acq( ctrlr )) ) + goto error; + /* ret = 0; */ +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +/* + * 1) check error code returned by controller; it's up to + * controller to detect error conditions reported by the card + * and to abort data transfer requests properly (e.g. send + * CMD12(STOP_TRANSMISSION) to abort ADDRESS_ERROR multiple + * block transfers) + * 2) arrange for card stack update when necessary + * (all pending i/o requests must be held pending, + * update procedure must start immediately after + * error has been detected) + */ +static inline int __mmc_check_error( mmc_card_t card, int err ) +{ + int ret = -EIO; + mmc_controller_t ctrlr; + + __ENTER0(); + + if ( !card || !card->ctrlr ) + goto error; + + ctrlr = card->ctrlr; + + if ( err < 0 ) { + switch ( err ) { + /* bus error occurred */ + case MMC_ERROR_CRC_WRITE_ERROR: + case MMC_ERROR_CRC_READ_ERROR: + case MMC_ERROR_RES_CRC_ERROR: + case MMC_ERROR_READ_TIME_OUT: + case MMC_ERROR_TIME_OUT_RESPONSE: + down_write( &ctrlr->update_sem ); /* FIXME */ + if ( !__mmc_update_card_stack( ctrlr ) ) + ret = -ENXIO; + up_write( &ctrlr->update_sem ); + break; + } + } else + ret = err; +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static inline void __mmc_free_controller( mmc_controller_t ctrlr ) +{ + if ( ctrlr ) { + if ( ctrlr->stack.ncards > 0 ) + __mmc_card_stack_free( &ctrlr->stack ); + kfree( ctrlr ); + } +} + +#ifdef CONFIG_PROC_FS +static int mmc_proc_read_card_info( char *page, char **start, off_t off, int count, int *eof, void *data ) +{ + int ret = -EINVAL; + mmc_card_t card = (mmc_card_t)data; + char *cp = page; + + if ( !card ) + goto error; + + down_read( &card->ctrlr->update_sem ); +/* TODO: proc report + * Type: RO, RW or IO (by CCC) + * MID: 0x%02x card->info.cid.mid + * OID: 0x%04x card->info.cid.oid + * PNM: %s card->info.pnm + * PRV: %s card->info.prv + * PSN: 0x%08x card->info.cid.psn + * MDT: %s card->info.mdt + * Capacity: card->info.capacity (Bytes) + */ +#if 1 + cp += sprintf( cp, "Capacity: %dKb.\n\n", (card->info.capacity>>10) ); +#else /* TODO */ + cp += sprintf( cp, "Type : %s\n", card->info.type ); + cp += sprintf( cp, "MID : 0x%02x\n", card->info.cid.mid ); + cp += sprintf( cp, "OID : 0x%04x\n", card->info.cid.oid ); + cp += sprintf( cp, "PNM : %s\n", card->info.pnm ); + cp += sprintf( cp, "PRV : %s\n", card->info.prv ); + cp += sprintf( cp, "PSN : 0x%08x\n", card->info.cid.psn ); + cp += sprintf( cp, "MDT : %s\n", card->info.mdt ); + cp += sprintf( cp, "Capacity: %dKB\n", + (card->info.capacity>>10) ); +#endif + up_read( &card->ctrlr->update_sem ); + + ret = cp - page; +error: + return ret; +} +#endif + +/************************************* + * MMC core interface implementation * + *************************************/ +int mmc_notify_add( mmc_card_t card ) +{ + int ret = 0; + mmc_notifier_t notifier; + + __ENTER0(); + if ( card ) { + for ( notifier = mmc_notifier; notifier; + notifier = notifier->next ) + if ( notifier->add ) + if ( (ret = notifier->add( card )) ) + break; + } + __LEAVE( "ret=%d", ret ); + return ret; +} +EXPORT_SYMBOL( mmc_notify_add ); + +int mmc_notify_remove( mmc_card_t card ) +{ + int ret = 0; + mmc_notifier_t notifier; + + __ENTER0(); + if ( card ) { + for ( notifier = mmc_notifier; notifier; + notifier = notifier->next ) + if ( notifier->remove ) + if ( (ret = notifier->remove( card )) ) + break; + } + __LEAVE( "ret=%d", ret ); + return ret; +} +EXPORT_SYMBOL( mmc_notify_remove ); + +int mmc_update_card_stack( int host ) +{ + int ret = -EINVAL; + mmc_controller_t ctrlr; + + __ENTER0(); + + if ( (host < 0) || (host >= MMC_CONTROLLERS_MAX) ) + goto error; + + down_read( &mmc_controller_sem ); + if ( (ctrlr = mmc_controller[host]) ) { + down_write( &ctrlr->update_sem ); + (void)__mmc_update_card_stack( ctrlr ); + up_write( &ctrlr->update_sem ); + } + up_read( &mmc_controller_sem ); + ret = 0; +error: + __LEAVE( "ret=%d", ret ); + return ret; +} +EXPORT_SYMBOL( mmc_update_card_stack ); + +ssize_t mmc_read( mmc_card_t card, mmc_transfer_mode_t mode, char *buf, size_t size, loff_t *paddr ) +{ + ssize_t ret = -EIO; + mmc_controller_t ctrlr; + mmc_data_transfer_req_rec_t transfer; + + if ( !paddr ) { + ret = -EINVAL; + goto error; + } + + if ( !card ) { + ret = -ENODEV; + goto error; + } + + __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%x", + card, card->usage, mode, buf, size, *paddr ); + + ctrlr = card->ctrlr; + if ( (ret = mmc_acquire_io( ctrlr, card )) ) + goto error; + + memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) ); + transfer.cmd = MMC_READ; + transfer.mode = mode; + transfer.type = MMC_USER; /* FIXME: buffer cache */ + transfer.buf = buf; + transfer.addr = *paddr; + transfer.cnt = size; + +/* max block size defined by CSD[read_bl_len] */ + transfer.blksz = card->info.read_bl_len; + transfer.nob = size / transfer.blksz; + if ( (size - (transfer.nob * transfer.blksz)) > 0 ) + transfer.nob++; + +/* TODO: controller may restrict maximum block size; set block size + * and number of blocks that their accumulated length fit to + * CSD[READ_BL_LEN] not to bother with block misalignment in multiple + * block transfers */ + ctrlr = card->ctrlr; + if ( transfer.blksz > ctrlr->tmpl->block_size_max ) { + ret = -EINVAL; /* FIXME */ + goto error; + } + + if ( ctrlr->stack.selected != card ) { + if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) ) + goto err_mmc; + ctrlr->stack.selected = card; + } + + switch( mode ) { + case MMC_TRANSFER_MODE_STREAM: + if ( !ctrlr->tmpl->stream_read ) { + ret = -ENXIO; + goto err_down; + } +/* TODO: The max clock frequency for stream read operation is given by + the following formula: + max speed = min ( TRAN_SPEED, 8*2^(READ_BL_LEN) - NSAC/TAAC ) + + If the card is not able to sustain data transfer it will set the + UNDERRUN error bit in the status register, abort the transmission + and wait in the Data state for a stop command + */ + ret = ctrlr->tmpl->stream_read( ctrlr, &transfer ); + break; + + case MMC_TRANSFER_MODE_BLOCK_SINGLE: + if ( !ctrlr->tmpl->read_block ) { + ret = -ENXIO; + goto err_down; + } +/* TODO: buffer size and data alignment (v3.4, p.29): + if CSD[READ_BL_PARTIAL] is set, smaller blocks whose starting + and ending address are entirely contained within one physical + block (as defined by CSD[READ_BL_LEN]) may also be transmitted + */ + transfer.type = MMC_KERNEL; /* FIXME */ + ret = ctrlr->tmpl->read_block( ctrlr, &transfer ); + break; + + case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: + if ( !ctrlr->tmpl->read_mblock ) { + ret = -ENXIO; + goto err_down; + } + + if ( transfer.nob > ctrlr->tmpl->nob_max ) { + ret = -EINVAL; + goto error; + } +/* TODO: buffer size and data alignment (v3.4, p.29): + if the host uses patrial blocks whose accumulated length is + not block aligned and block misalignment is not allowed, the + card should detect a block misalignment error condition at the + beginning of the first misaligned block + */ + transfer.type = MMC_KERNEL; /* FIXME */ + ret = ctrlr->tmpl->read_mblock( card->ctrlr, &transfer ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" ); + ret = -EINVAL; + } +err_mmc: + ret = __mmc_check_error( card, ret ); + if ( ret >= 0 ) { + ret = size - transfer.cnt; + *paddr += ret; + } +err_down: + mmc_release_io( ctrlr, card ); +error: + __LEAVE("ret=%d", ret); + return ret; +} +EXPORT_SYMBOL( mmc_read ); + +ssize_t mmc_write( mmc_card_t card, mmc_transfer_mode_t mode, const char *buf, size_t size, loff_t *paddr ) +{ + ssize_t ret = -ESPIPE; + mmc_controller_t ctrlr; + mmc_data_transfer_req_rec_t transfer; + + if ( !paddr ) { + ret = -EINVAL; + goto error; + } + + if ( !card ) { + ret = -ENODEV; + goto error; + } + + __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%llx", + card, card->usage, mode, buf, size, *paddr ); + + ctrlr = card->ctrlr; + if ( (ret = mmc_acquire_io( ctrlr, card )) ) + goto error; + + memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) ); + transfer.cmd = MMC_WRITE; + transfer.mode = mode; + transfer.type = MMC_USER; /* FIXME: buffer cache */ + transfer.buf = (char *)buf; + transfer.addr = *paddr; + transfer.cnt = size; + +/* max block size defined by CSD[write_bl_len] */ + transfer.blksz = card->info.write_bl_len; + transfer.nob = size / transfer.blksz; + if ( (size - (transfer.nob * transfer.blksz)) > 0 ) + transfer.nob++; + +/* TODO: controller may restrict maximum block size; set block size + * and number of blocks that their accumulated length fit to + * CSD[WRITE_BL_LEN] not to bother with block misalignment in multiple + * block transfers */ + ctrlr = card->ctrlr; + if ( transfer.blksz > ctrlr->tmpl->block_size_max ) { + ret = -EINVAL; /* FIXME */ + goto error; + } + + if ( ctrlr->stack.selected != card ) { + if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) ) + goto err_mmc; + ctrlr->stack.selected = card; + } + + transfer.cmd = MMC_WRITE; + transfer.mode = mode; + transfer.type = MMC_USER; + switch( mode ) { + case MMC_TRANSFER_MODE_STREAM: + if ( !ctrlr->tmpl->stream_write ) { + ret = -ENXIO; + goto err_down; + } + ret = ctrlr->tmpl->stream_write( ctrlr, &transfer ); + break; + + case MMC_TRANSFER_MODE_BLOCK_SINGLE: + if ( !ctrlr->tmpl->write_block ) { + ret = -ENXIO; + goto err_down; + } + transfer.type = MMC_KERNEL; /* FIXME */ + ret = ctrlr->tmpl->write_block( ctrlr, &transfer ); + break; + + case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: + if ( !ctrlr->tmpl->write_mblock ) { + ret = -ENXIO; + goto err_down; + } + transfer.type = MMC_KERNEL; /* FIXME */ + ret = ctrlr->tmpl->write_mblock( card->ctrlr, &transfer ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" ); + } + +err_mmc: + ret = __mmc_check_error( card, ret ); /* FIXME */ + if ( ret >= 0 ) { + ret = size - transfer.cnt; + *paddr += ret; + } +err_down: + mmc_release_io( ctrlr, card ); +error: + __LEAVE( "ret=%d", ret ); + return ret; +} +EXPORT_SYMBOL( mmc_write ); + +int mmc_ioctl( mmc_card_t card, unsigned int cmd, unsigned long arg ) +{ + int ret = -EINVAL; + mmc_controller_t ctrlr; + + if ( !card ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" ) + goto error; + } + + ctrlr = card->ctrlr; + if ( mmc_acquire_io( ctrlr, card ) ) { + ret = -ENXIO; + goto error; + } + + switch ( cmd ) { + case IOCMMCGCARDESC: + if ( copy_to_user( (void *)arg, &card->info, sizeof( mmc_card_info_rec_t ) ) ) + ret = -EFAULT; + break; +/* + * 1. TODO: erase region + * 2. TODO: set/unset write protection, lock/password + */ + default: + ret = -ENOIOCTLCMD; + } + + mmc_release_io( ctrlr, card ); +error: + return ret; +} +EXPORT_SYMBOL( mmc_ioctl ); + +/* + * registry stuff + */ +mmc_card_t mmc_get_card( int host, int slot ) +{ + mmc_card_t ret = NULL; + mmc_controller_t ctrlr = NULL; + int found; + + __ENTER( "host=%d, card=%d", host, slot ); + + if ( ((host < 0) || (host >= MMC_CONTROLLERS_MAX)) + && ((slot < 0) || (slot >= MMC_CARDS_MAX)) ) + goto error; + + down_read( &mmc_controller_sem ); + + if ( (ctrlr = mmc_controller[host]) ) { + down_write( &ctrlr->update_sem ); + if ( ctrlr->stack.ncards > 0 ) { + ret = ctrlr->stack.first; + found = FALSE; + while ( ret ) { + if ( (ret->slot == slot) && (ret->state != + MMC_CARD_STATE_UNPLUGGED) ) { + found = TRUE; + break; + } + ret = ret->next; + } + + if ( found ) { + if ( ctrlr->tmpl->owner ) { + ++ctrlr->usage; + MMC_DEBUG( MMC_DEBUG_LEVEL2, + "'%s' use count increased (%d)\n", + ctrlr->tmpl->name, ctrlr->usage ); + __MOD_INC_USE_COUNT( ctrlr->tmpl->owner ); + } + ++ret->usage; + } else + ret = NULL; + } + up_write( &ctrlr->update_sem ); + } + up_read( &mmc_controller_sem ); +error: + __LEAVE("ret=0x%p usage=%d", ret, ret ? ret->usage : -1 ); + return ret; +} +EXPORT_SYMBOL( mmc_get_card ); + +void mmc_put_card( mmc_card_t card ) +{ + mmc_card_t tmp = NULL; + mmc_controller_t ctrlr; + int found; + + __ENTER( "card=0x%p", card ); + + if ( !card ) + goto error; + + ctrlr = card->ctrlr; + + down_read( &mmc_controller_sem ); + if ( !ctrlr || (ctrlr != mmc_controller[ctrlr->slot]) ) { + MMC_ERROR( "bad controller reference: ctrlr=0x%p\n", ctrlr ); + goto err_down; + } + + down_write( &ctrlr->update_sem ); + if ( ctrlr->stack.ncards > 0 ) { + tmp = ctrlr->stack.first; + found = FALSE; + while ( tmp ) { + if ( tmp == card ) { + found = TRUE; + break; + } + tmp = tmp->next; + } + + if ( found ) { + if ( tmp->usage > 0 ) { + --tmp->usage; + MMC_DEBUG( MMC_DEBUG_LEVEL2, "usage=%d" + "owner=0x%p\n", tmp->usage, + ctrlr->tmpl->owner ); + if ( !tmp->usage && (ctrlr->usage > 0) + && ctrlr->tmpl->owner ) { + --ctrlr->usage; + MMC_DEBUG( MMC_DEBUG_LEVEL2, + "'%s' use count " + "decreased (%d)\n", + ctrlr->tmpl->name, + ctrlr->usage ); + __MOD_DEC_USE_COUNT( + ctrlr->tmpl->owner ); + } + } + } else + MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" ); + + } + up_write( &ctrlr->update_sem ); +err_down: + up_read( &mmc_controller_sem ); +error: + __LEAVE( "found=%d", found ); + return; +} +EXPORT_SYMBOL( mmc_put_card ); + +static inline void *mmc_register_user( mmc_notifier_t notifier ) +{ + mmc_notifier_t ret = NULL, last = mmc_notifier; + + MOD_INC_USE_COUNT; + if ( notifier ) { + down_write( &mmc_notifier_sem ); + + notifier->next = NULL; + if ( !last ) { + mmc_notifier = notifier; + ret = notifier; + } else { + while ( last->next ) { + if ( last == notifier ) { + MOD_DEC_USE_COUNT; + break; + } + last = last->next; + } + if ( last != notifier ) { + last->next = notifier; + ret = notifier; + } + } + up_write( &mmc_notifier_sem ); + } +/* notify new user about the cards present in the system */ + if ( ret && ret->add ) { + int i; + + down_read( &mmc_controller_sem ); + for ( i = 0; i < mmc_ncontrollers; i++ ) { + mmc_controller_t ctrlr = mmc_controller[i]; + + down_read( &ctrlr->update_sem ); /* FIXME */ + __mmc_card_stack_foreach( &ctrlr->stack, + ret->add, FALSE ); + up_read( &ctrlr->update_sem ); /* FIXME */ + } + up_read( &mmc_controller_sem ); + } +/* error: */ + __LEAVE( "mmc_notifier=0x%p, mmc_notifier->next=0x%p", + mmc_notifier, mmc_notifier ? mmc_notifier->next : NULL ); + return ret; +} + +static inline mmc_controller_t mmc_register_controller( mmc_controller_tmpl_t tmpl, size_t extra ) +{ + mmc_controller_t ret = NULL; + int found; + int i; + + MOD_INC_USE_COUNT; + + down_write( &mmc_controller_sem ); + + if ( mmc_ncontrollers >= MMC_CONTROLLERS_MAX ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're too many controllers\n" ); + goto error; + } + + found = FALSE; + for ( i = 0; i < MMC_CONTROLLERS_MAX; i++ ) + if ( !mmc_controller[i] ) { + found = TRUE; + break; + } + + if ( !found ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're no empty slots\n" ); + goto error; + } + + if ( !tmpl->init ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init()'\n" ); + goto error; + } + + if ( !tmpl->probe ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'probe()'\n" ); + goto error; + } + + if ( !tmpl->init_card_stack ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init_card_stack()'\n" ); + goto error; + } + + if ( !tmpl->update_acq ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'update_acq()'\n" ); + goto error; + } + + if ( !tmpl->check_card_stack ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'check_card_stack()'\n" ); + goto error; + } + + if ( !tmpl->setup_card ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'setup_card()'\n" ); + goto error; + } + + ret = kmalloc( sizeof( mmc_controller_rec_t ) + extra, GFP_ATOMIC ); /* FIXME: ISA + GFP_DMA */ + if ( !ret ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "out of memory\n" ); + goto error; + } + + memset( ret, 0, sizeof( mmc_controller_rec_t ) + extra ); + + if ( (tmpl->probe( ret ) != 1) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller probe failed\n" ); + goto err_free; + } + + if ( tmpl->init( ret ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller initialization failure\n" ); + goto err_free; + } + + ret->state = MMC_CONTROLLER_FOUND; + ret->slot = i; + ret->tmpl = tmpl; + init_MUTEX( &ret->io_sem ); + init_rwsem( &ret->update_sem ); +#ifdef CONFIG_PROC_FS + if ( mmc_proc_dir ) { + snprintf( ret->proc_name, sizeof( ret->proc_name ), + "host%d", ret->slot ); + ret->proc = proc_mkdir( ret->proc_name, mmc_proc_dir ); + } +#endif + +/* initialize card stack */ + if ( ret->tmpl->init_card_stack( ret ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "card stack initialization failure\n" ); + if ( ret->tmpl->remove ) + ret->tmpl->remove( ret ); /* FIXME */ + goto err_free; + } + + mmc_controller[ret->slot] = ret; + ++mmc_ncontrollers; + +/* notify users */ + if ( ret->stack.ncards > 0 ) { + down_read( &mmc_notifier_sem ); + if ( (i = __mmc_card_stack_foreach( &ret->stack, mmc_notify_add, FALSE ) ) < 0 ) + MMC_ERROR( "device add notification failed at slot %d\n", -i ); + up_read( &mmc_notifier_sem ); + } + goto out; + +err_free: +#ifdef CONFIG_PROC_FS + if ( ret->proc ) + remove_proc_entry( ret->proc_name, mmc_proc_dir ); +#endif + kfree( ret ); +error: + ret = NULL; + MOD_DEC_USE_COUNT; +out: + up_write( &mmc_controller_sem ); + return ret; +} + +static inline mmc_card_t mmc_register_card( mmc_card_t card ) +{ + mmc_card_t ret = NULL; + mmc_controller_t ctrlr; + + if ( !card || !card->ctrlr ) + goto error; + + ctrlr = card->ctrlr; +#ifdef CONFIG_PROC_FS + if ( ctrlr->proc ) { + snprintf( card->proc_name, sizeof( card->proc_name ), + "card%d", card->slot ); + card->proc = create_proc_read_entry( card->proc_name, + 0444, ctrlr->proc, + mmc_proc_read_card_info, card ); + } +#endif + mmc_notify_add( card ); +error: + return ret; +} + +void *mmc_register( mmc_reg_type_t reg_type, void *tmpl, size_t extra ) +{ + void *ret = NULL; + + switch ( reg_type ) { + case MMC_REG_TYPE_CARD: + ret = mmc_register_card( (mmc_card_t)tmpl ); + break; + + case MMC_REG_TYPE_USER: + ret = mmc_register_user( (mmc_notifier_t)tmpl ); + break; + + case MMC_REG_TYPE_HOST: + ret = mmc_register_controller( (mmc_controller_tmpl_t)tmpl, extra ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "register request for unknown type\n" ); + } + + return ret; +} +EXPORT_SYMBOL( mmc_register ); + +static inline void mmc_unregister_user( mmc_notifier_t notifier ) +{ + mmc_notifier_t prev = mmc_notifier; + int found = FALSE; + + if ( notifier ) { + down_write( &mmc_notifier_sem ); + + if ( mmc_notifier == notifier) { + mmc_notifier = prev->next; + found = TRUE; + + } else if ( mmc_notifier ) { + while( prev ) { + if ( prev->next == notifier ) { + found = TRUE; + prev->next = prev->next->next; + break; + } + prev = prev->next; + } + } + + if ( found ) { + if ( notifier->remove ) { + int i; + + down_read( &mmc_controller_sem ); + for ( i = 0; i < mmc_ncontrollers; i++ ) { + mmc_controller_t ctrlr = + mmc_controller[i]; + + down_read( &ctrlr->update_sem ); + __mmc_card_stack_foreach( &ctrlr->stack, notifier->remove, FALSE ); + up_read( &ctrlr->update_sem ); + } + up_read( &mmc_controller_sem ); + } + } + + up_write( &mmc_notifier_sem ); + } + + MOD_DEC_USE_COUNT; +} + +static inline void mmc_unregister_controller( mmc_controller_t ctrlr ) +{ + if ( !ctrlr || (mmc_controller[ctrlr->slot] != ctrlr ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad unregister request\n" ); + goto error; + } + + down_write( &mmc_controller_sem ); + +/* notify users */ + if ( ctrlr->stack.ncards > 0 ) { + int slot; + + down_read( &mmc_notifier_sem ); + if ( (slot = __mmc_card_stack_foreach( &ctrlr->stack, mmc_notify_remove, FALSE ) ) ) + MMC_ERROR( "device remove notification failed at slot %d\n", -slot ); + up_read( &mmc_notifier_sem ); + } + +#ifdef CONFIG_PROC_FS + if ( ctrlr->proc ) + remove_proc_entry( ctrlr->proc_name, mmc_proc_dir ); +#endif + + if ( ctrlr->tmpl && ctrlr->tmpl->remove ) + ctrlr->tmpl->remove( ctrlr ); + + mmc_controller[ctrlr->slot] = NULL; + --mmc_ncontrollers; + + __mmc_free_controller( ctrlr ); + + up_write( &mmc_controller_sem ); + MOD_DEC_USE_COUNT; +error: + return; +} + +void mmc_unregister( mmc_reg_type_t reg_type, void *tmpl ) +{ + switch ( reg_type ) { + case MMC_REG_TYPE_USER: + mmc_unregister_user( (mmc_notifier_t)tmpl ); + break; + + case MMC_REG_TYPE_HOST: + mmc_unregister_controller( (mmc_controller_t)tmpl ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "unregister request for unknown type\n" ); + } +} +EXPORT_SYMBOL( mmc_unregister ); + +#ifdef CONFIG_PM +/* power management support */ +static int mmc_pm_callback( struct pm_dev *pmdev, pm_request_t pmreq, void *pmdata ) +{ + int ret = -EINVAL; + mmc_controller_t ctrlr; + int i; + + __ENTER( "pmreq=%d", pmreq ); + + down_read( &mmc_controller_sem ); + + switch ( pmreq ) { + case PM_SUSPEND: + for ( ret = 0, i = 0; !ret && (i < mmc_ncontrollers); i++ ) { + ctrlr = mmc_controller[i]; + if ( ctrlr->tmpl->suspend ) + ret = ctrlr->tmpl->suspend( ctrlr ); + } + if ( !ret ) + break; + + case PM_RESUME: + for ( i = mmc_ncontrollers - 1; i >= 0; i-- ) { + ctrlr = mmc_controller[i]; + if ( ctrlr->tmpl->resume ) + ctrlr->tmpl->resume( ctrlr ); + } + ret = 0; + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "unsupported PM request %d\n", + pmreq ); + } + + up_read( &mmc_controller_sem ); +/* error: */ + __LEAVE( "ret=%d", ret ); + return ret; +} +#endif + +/* kernel module stuff */ +static int __init mmc_core_module_init( void ) +{ + int ret = -ENODEV; + + memset( &mmc_controller, 0, sizeof( mmc_controller ) ); + + init_rwsem( &mmc_controller_sem ); + init_rwsem( &mmc_notifier_sem ); +#ifdef CONFIG_PM + if ( !(mmc_pm_dev = pm_register( PM_UNKNOWN_DEV, 0, mmc_pm_callback )) ) MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register PM callback\n" ); +#endif +#ifdef CONFIG_PROC_FS + mmc_proc_dir = proc_mkdir( "mmc", NULL ); +#endif + ret = 0; +/* error: */ + return ret; +} + +static void __exit mmc_core_module_cleanup( void ) +{ +#ifdef CONFIG_PROC_FS + if ( mmc_proc_dir ) + remove_proc_entry( "mmc", NULL ); +#endif +#ifdef CONFIG_PM + pm_unregister( mmc_pm_dev ); +#endif +} + +module_init( mmc_core_module_init ); +module_exit( mmc_core_module_cleanup ); + +MODULE_LICENSE( "GPL" ); + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/mmc_pxa.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,1902 @@ +/* + * linux/drivers/mmc/mmc_pxa.c + * driver for Cotulla MMC controller + * + * Authors: Vladimir Shebordaev, Igor Oblakov + * Copyright: MontaVista Software Inc. + * + * $Id: mmc_pxa.c,v 0.3.1.12 2002/09/25 19:25:48 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "types.h" +#include "mmc.h" +#include "mmc_pxa.h" + +static mmc_controller_t host = NULL; + +/* service routines */ +static inline int pxa_mmc_check_state( mmc_controller_t ctrlr, pxa_mmc_state_t state ) +{ + int ret = -1; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + if ( hostdata->state != state ) { + //MMC_DEBUG( MMC_DEBUG_LEVEL3, "state (%s vs %s)\n", PXA_MMC_STATE_LABEL( hostdata->state ), PXA_MMC_STATE_LABEL( state ) ); + goto error; + } + ret = 0; +error: + return ret; +} + +static inline void pxa_mmc_set_state( mmc_controller_t ctrlr, pxa_mmc_state_t state ) +{ + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + hostdata->state = state; +} + +static inline int pxa_mmc_init_completion( mmc_controller_t ctrlr, u32 mask ) +{ + int ret = -1; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + if ( xchg( &hostdata->busy, 1 ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "another interrupt " + "is already been expected\n" ); + goto error; + } + +#if CONFIG_MMC_DEBUG_IRQ + hostdata->irqcnt = 1000; +#endif + init_completion( &hostdata->completion ); + + MMC_I_MASK = MMC_I_MASK_ALL & ~mask; + ret = 0; +error: + return ret; +} + +#if CONFIG_MMC_DEBUG_IRQ +static struct timer_list timer; +static void wait_timeo( unsigned long arg ) { + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)arg; + hostdata->timeo = 1; + complete( &hostdata->completion ); + return; +} +#endif + +static inline int pxa_mmc_wait_for_completion( mmc_controller_t ctrlr, u32 mask ) +{ + int ret = -1; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + if ( !xchg( &hostdata->busy, 1 ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "there were no " + "interrupt awaited for\n" ); + goto error; + } + +#if CONFIG_MMC_DEBUG_IRQ + hostdata->timeo = 0; + del_timer( &timer ); + timer.function = wait_timeo; + timer.expires = jiffies + 1UL*HZ; + timer.data = (unsigned long)hostdata; + add_timer( &timer ); +#endif + wait_for_completion( &hostdata->completion ); +#if CONFIG_MMC_DEBUG_IRQ + del_timer( &timer ); + if ( hostdata->timeo ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "irq timed out: " "mask=%x stat=%x\n", mask, MMC_STAT ); + goto error; + } +#endif + /* verify interrupt */ + if ( (mask == ~0UL) || !( hostdata->mmc_i_reg & ~mask ) ) + ret = 0; + +error: + xchg( &hostdata->busy, 0 ); + return ret; +} + +static inline int pxa_mmc_stop_bus_clock( mmc_controller_t ctrlr ) +{ + int ret = -1; + + if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_CLK_OFF ) ) + goto out; + + if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "BUFFER_IN_TRANSIT\n" ); + goto error; + } + + if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_CLK_IS_OFF ) ) + goto error; + + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + + if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_CLK_IS_OFF ) ) + goto error; + + //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is off\n" ); + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_CLK_OFF ); +out: + ret = 0; +error: + return ret; +} + +static inline int pxa_mmc_start_bus_clock( mmc_controller_t ctrlr ) +{ + int ret = -1; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF) + && (hostdata->state != PXA_MMC_FSM_END_IO) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", PXA_MMC_STATE_LABEL( hostdata->state ) ); + goto error; + } + + MMC_STRPCL = MMC_STRPCL_START_CLK; + wmb(); + //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is on\n" ); + ret = 0; +error: + return ret; +} + +/* +int pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t response ) + +Effects: initializes completion to wait for END_CMD_RES intr, + waits for intr to occur, checks controller and card status +Requiers: controller is in CLK_OFF state +Modifies: moves controller to the END_CMD state +Returns: +*/ +static mmc_error_t pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t format, int send_abort ) +{ + mmc_error_t ret = MMC_ERROR_GENERIC; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + int mask, nwords; + u32 status; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD%d(0x%04x%04x)\n", MMC_CMD & 0x3f, MMC_ARGH, MMC_ARGL); + +/* FIXME: check arguments */ + + if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF) + && (hostdata->state != PXA_MMC_FSM_END_IO) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", + PXA_MMC_STATE_LABEL( hostdata->state ) ); + goto error; + } + + mask = MMC_I_MASK_END_CMD_RES; + if ( pxa_mmc_init_completion( ctrlr, mask ) ) + goto error; + + MMC_PRTBUF = MMC_PRTBUF_BUF_FULL; +/* start the clock */ + if ( pxa_mmc_start_bus_clock( ctrlr ) ) + goto error; + +/* wait for END_CMD_RES intr */ + if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_END_CMD_RES ) ) + goto error; + +/* check status */ + if ( hostdata->mmc_stat & MMC_STAT_TIME_OUT_RESPONSE ) { + // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response timeout\n"); + ret = MMC_ERROR_TIME_OUT_RESPONSE; + goto error; + + } else if ( hostdata->mmc_stat & MMC_STAT_READ_TIME_OUT ) { + // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read timeout\n"); + ret = MMC_ERROR_READ_TIME_OUT; + goto error; + + } else if ( hostdata->mmc_stat & MMC_STAT_RES_CRC_ERROR ) { + // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response crc err\n"); + ret = MMC_ERROR_RES_CRC_ERROR; + goto error; + + } else if ( hostdata->mmc_stat & MMC_STAT_CRC_READ_ERROR ) { + // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read crc err\n"); + ret = MMC_ERROR_CRC_READ_ERROR; + goto error; + + } else if ( hostdata->mmc_stat & MMC_STAT_CRC_WRITE_ERROR ) { + // MMC_DEBUG(MMC_DEBUG_LEVEL3, "write crc err\n"); + ret = MMC_ERROR_CRC_WRITE_ERROR; + goto error; + } + + nwords = (format == MMC_NORESPONSE) ? 0 : + (format == MMC_R1) ? 3 : + (format == MMC_R2) ? 8 : + (format == MMC_R3) ? 3 : + -1; + ret = nwords; + if ( nwords > 0 ) { + register int i; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "nwords=%d\n", nwords ); + for ( i = nwords - 1; i >= 0 ; i-- ) { + u32 res = MMC_RES; + int ibase = i<<1; + + hostdata->mmc_res[ibase] = ((u8 *)&res)[0]; + hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1]; + --ret; + } +#ifdef CONFIG_MMC_DEBUG + switch ( format ) { + case MMC_R1: + MMC_DUMP_R1( ctrlr ); + break; + case MMC_R2: + MMC_DUMP_R2( ctrlr ); + break; + case MMC_R3: + MMC_DUMP_R3( ctrlr ); + break; + default: + MMC_DEBUG( MMC_DEBUG_LEVEL3, + "unknown response format\n" ); + ret = MMC_ERROR_GENERIC; + goto error; + } +#endif + +/* check card status for R1(b) commands */ + if ( format == MMC_R1 ) { + u8 cmd; + + ((u8 *)&status)[0] = hostdata->mmc_res[1]; + ((u8 *)&status)[1] = hostdata->mmc_res[2]; + ((u8 *)&status)[2] = hostdata->mmc_res[3]; + ((u8 *)&status)[3] = hostdata->mmc_res[4]; + cmd = PXA_MMC_RESPONSE( ctrlr, 5 )&0x3f; + MMC_DEBUG( MMC_DEBUG_LEVEL3, + //printk( KERN_INFO __FUNCTION__"(): " + "cmd=%u status: 0x%08x\n", + cmd, status ); + switch ( cmd ) { + case 11: + case 18: + case 20: + case 25: + if ( !(status & 0x00000100) ) /* FIXME */ + goto mmc_error; + default: + break; + } + if ( status & MMC_CARD_STATUS_OUT_OF_RANGE ) { + ret = MMC_ERROR_OUT_OF_RANGE; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ADDRESS_ERROR ) { + ret = MMC_ERROR_ADDRESS_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_BLOCK_LEN_ERROR ) { + ret = MMC_ERROR_ADDRESS_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ERASE_SEQ_ERROR ) { + ret = MMC_ERROR_ERASE_SEQ_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ERASE_PARAM ) { + ret = MMC_ERROR_ERASE_PARAM; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_WP_VIOLATION ) { + ret = MMC_ERROR_WP_VIOLATION; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_CARD_IS_LOCKED ) { + ret = MMC_ERROR_CARD_IS_LOCKED; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_LOCK_UNLOCK_FAILED ) { + ret = MMC_ERROR_LOCK_UNLOCK_FAILED; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_COM_CRC_ERROR ) { + ret = MMC_ERROR_COM_CRC_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ILLEGAL_COMMAND ) { + ret = MMC_ERROR_ILLEGAL_COMMAND; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_CARD_ECC_FAILED ) { + ret = MMC_ERROR_CARD_ECC_FAILED; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_CC_ERROR ) { + ret = MMC_ERROR_CC_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ERROR ) { + ret = MMC_ERROR_ERROR; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_UNDERRUN ) { + ret = MMC_ERROR_UNDERRUN; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_OVERRUN ) { + ret = MMC_ERROR_OVERRUN; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_CID_CSD_OVERWRITE ) { + ret = MMC_ERROR_CID_CSD_OVERWRITE; + goto mmc_error; + } else if ( status & MMC_CARD_STATUS_ERASE_RESET ) { + ret = MMC_ERROR_ERASE_RESET; + goto mmc_error; + } + } + } + + if ( ret >= 0 ) + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_CMD ); + goto out; +mmc_error: +#if 1 + if ( send_abort ) { + /* send CMD12 to abort failed transfer */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ + MMC_CMDAT = MMC_CMDAT_R1; + + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + + ret = -EIO; + goto error; + } +#endif +error: + /* move controller to the IDLE state */ + pxa_mmc_stop_bus_clock( ctrlr ); + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); +out: + return ret; +} + +/* +int pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t cmd, mmc_dir_t dir, mmc_transfer_mode_t mode ) + +Effects: finilizes data transfer request +Reqires: controller is in the END_BUFFER state +Modifies: moves controller to the IDLE state +Returns: zero upon success or error condition code otherwise + */ +static mmc_error_t pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t dir, mmc_transfer_mode_t mode ) +{ + int ret = MMC_ERROR_GENERIC; + + if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_IO ) ) + goto error; + + switch ( mode ) { + case MMC_TRANSFER_MODE_STREAM: /* FIXME */ + if ( dir == MMC_WRITE ) { + /* 1. wait for STOP_CMD intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_STOP_CMD )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_STOP_CMD )) ) + goto error; + } + /* 2. send CMD12 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ + MMC_CMDAT = MMC_CMDAT_R1; + if ( dir == MMC_WRITE ) + MMC_CMDAT |= MMC_CMDAT_BUSY; + + /* 3. wait for CMD12 to complete */ + MMC_DEBUG( MMC_DEBUG_LEVEL3, "ready for CMD12\n" ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + + /* 4. wait for DATA_TRAN_DONE intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_DATA_TRAN_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_DATA_TRAN_DONE )) ) + goto error; + + if ( dir == MMC_WRITE ) { + /* 5. wait for PRG_DONE intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_PRG_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_PRG_DONE )) ) + goto error; + } + break; + case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: + /* 1. wait for DATA_TRAN done intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_DATA_TRAN_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_DATA_TRAN_DONE )) ) + goto error; + + /* 2. send CMD12 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(12); /* STOP_TRANSMISSION */ + MMC_CMDAT = MMC_CMDAT_R1; + if ( dir == MMC_WRITE ) + MMC_CMDAT |= MMC_CMDAT_BUSY; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD12\n" ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + + if ( dir == MMC_WRITE ) { + /* 3. wait for PRG_DONE intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_PRG_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_PRG_DONE )) ) + goto error; + } + break; + case MMC_TRANSFER_MODE_BLOCK_SINGLE: + /* 1. wait for DATA_TRAN_DONE intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_DATA_TRAN_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_DATA_TRAN_DONE )) ) + goto error; + + if ( dir == MMC_WRITE ) { + /* 2. wait for PRG_DONE intr */ + if ( (ret = pxa_mmc_init_completion( ctrlr, + MMC_I_MASK_PRG_DONE )) ) + goto error; + if ( (ret = pxa_mmc_wait_for_completion( ctrlr, + MMC_I_REG_PRG_DONE )) ) + goto error; + } + break; + default: + MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown transfer mode\n" ); + goto error; + } +/* move the controller to the IDLE state */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); + + ret = 0; +error: + return ret; +} + +static inline int pxa_mmc_update_acq( mmc_controller_t ctrlr ) +{ + int ret = -EINVAL; + pxa_mmc_hostdata_t hostdata = NULL; + mmc_card_t card = NULL; + mmc_card_stack_rec_t fake; + mmc_card_stack_t stack = &fake; + u16 argl = 0U, argh = 0U; + int ncards = 0; + + if ( !ctrlr ) + goto error; + + hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + __mmc_card_stack_init( stack ); + + /* max open-drain mode frequency is 400kHZ */ + MMC_CLKRT = MMC_CLKRT_0_3125MHZ; + MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */ + + /* discover and add cards to the stack */ + /* I. bus operation condition setup */ + /* 1) send CMD1 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + argl = 0x0000; + argh = 0x0004; + + MMC_CMD = CMD(1); + MMC_ARGH = argh; + MMC_ARGL = argl; + + MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl ); + ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE ); + if ( !ret ) { + argh = (PXA_MMC_RESPONSE( ctrlr, 4 ) << 8) + | PXA_MMC_RESPONSE( ctrlr, 3 ); + argl = (PXA_MMC_RESPONSE( ctrlr, 2 ) << 8) + | PXA_MMC_RESPONSE( ctrlr, 1 ); + + } else if ( ret != MMC_ERROR_TIME_OUT_RESPONSE ) + goto err_free; + + if ( !argh && !argl ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, + "assuming full voltage range support\n" ); + argh = 0x00ff; + argl = 0xff00; + } + + /* 2) continuously send CMD1 'till there're busy cards */ + for(;;) { + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + MMC_CMD = CMD(1); + MMC_ARGH = argh; + MMC_ARGL = argl; + + MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl ); + ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE ); + if ( ret == MMC_ERROR_TIME_OUT_RESPONSE ) + break; + + else if ( !ret ) { + /* busy state reported by LOW signal level + * (MMC v3.2, p.58) + * + * Thanks to Alexander Samoutin :) + */ + if ( !(PXA_MMC_RESPONSE( ctrlr, 4 ) & 0x80) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "busy state reported\n"); + udelay( 20 ); + continue; + } else + break; + } else + goto err_free; + } + +/* II. card identification: the cards in Ready state + * are the only expected to respond + */ + for (;;) { + argh = 0U; + argl = 0U; + + /* 1) send CMD2 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + MMC_CMD = CMD(2); + MMC_ARGH = 0x0003; + MMC_ARGL = 0xf300; + MMC_CMDAT = MMC_CMDAT_R2; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD2(0x%04x%04x)\n", argh, argl ); + ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE ); + if ( ret == MMC_ERROR_TIME_OUT_RESPONSE ) + break; + + else if ( ret ) /* bus error */ + goto err_free; + + /* TODO: store CID for the card */ + + /* 2) assign RCA */ + if ( !++ctrlr->rca_next ) /* overflow */ + ++ctrlr->rca_next; + argh = ctrlr->rca_next; + + /* 3) send it to the card last responded (CMD3) */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + MMC_CMD = CMD(3); + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD3(0x%04x%04x)\n", argh, argl ); + ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE ); + if ( ret ) /* CMD3 failed */ + goto err_free; + + card = __mmc_card_alloc( sizeof( pxa_mmc_card_data_rec_t ) ); + if ( !card ) { + MMC_ERROR( "out of memory\n" ); + goto err_free; + } + + card->info.rca = argh; + card->slot = ctrlr->slot_next++; /* FIXME: minor encoding */ + card->ctrlr = ctrlr; + + if ( !__mmc_card_stack_add( stack, card ) ) + goto err_free; + + MMC_DEBUG( MMC_DEBUG_LEVEL2, "added card: " + "slot %d, RCA=0x%04x\n", card->slot, argh ); + ++ncards; + } + + if ( ncards ) { +/* III. read CSD registers of all cards; DSR support also reported there */ + for ( card = stack->first; card; card = card->next ) { + pxa_mmc_card_data_t card_data = + (pxa_mmc_card_data_t)card->card_data; + + /* 1) send CMD9 */ + argh = card->info.rca; + argl = 0U; + + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + MMC_CMD = CMD(9); + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R2; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, + "CMD9(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE )) ) + goto err_free; + + memcpy( &card->info.csd, hostdata->mmc_res, 15 ); + MMC_DUMP_CSD( card ); + + card->info.read_bl_len = (1<info.csd.read_bl_len); + card->info.write_bl_len = (1<info.csd.write_bl_len); + card->info.capacity = (card->info.csd.c_size + 1) + * (1<<(card->info.csd.c_size_mult + 2)) + * card->info.read_bl_len; + MMC_DEBUG( MMC_DEBUG_LEVEL2, "card capacity=%dMb\n", + card->info.capacity>>20 ); + card->info.tran_speed = 20*1024; /* FIXME */ + card->info.transfer_mode = MMC_TRANSFER_MODE_BLOCK_SINGLE; + /* 2) set bus operation freq */ + card_data->clkrt = pxa_mmc_clkrt( card->info.tran_speed ); + /* 3) register card with MMC core */ + mmc_register( MMC_REG_TYPE_CARD, card, 0 ); + } +/* IV. set DSR registers of the cards */ +#if 0 /* TODO */ + if ( card->info.csd.dsr_imp ) { + set_dsr = TRUE; + /* calculate DSR */ + } +#endif + } +#if 0 /* TODO */ + if ( set_dsr ) { + /* send CMD4 */ + } +#endif +/* merge list of the newly inserted cards into controller card stack */ + if ( !ctrlr->stack.ncards ) { + ctrlr->stack.first = stack->first; + ctrlr->stack.last = stack->last; + } else + ctrlr->stack.last->next = stack->first; + + ctrlr->stack.ncards += stack->ncards; + + ret = 0; + goto out; +err_free: + __mmc_card_stack_free( stack ); +error: +out: + return ret; +} + +/* MMC protocol macros: v3.4, p.120 */ +static int pxa_mmc_init_card_stack( mmc_controller_t ctrlr ) +{ + int ret = -EIO; + u16 argl = 0U, argh = 0U; + + if ( !ctrlr || ctrlr->stack.ncards ) { + ret = -EINVAL; + goto error; + } + + /* initialize stack */ + /* 1) send CMD0 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + /* max open-drain mode frequency is 400kHZ */ + MMC_CLKRT = MMC_CLKRT_0_3125MHZ; + MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */ + MMC_SPI = MMC_SPI_DISABLE; + + MMC_CMD = CMD(0); /* CMD0 with zero argument */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_INIT; + + //MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, FALSE )) ) + goto error; + + /* update card stack */ + if ( (ret = pxa_mmc_update_acq( ctrlr )) ) + goto err_free; + + /* move the controller to the IDLE state */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto err_free; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); + + ret = 0; + MMC_DEBUG( MMC_DEBUG_LEVEL2, "ncards=%d\n", ctrlr->stack.ncards ); + goto out; + +err_free: + __mmc_card_stack_free( &ctrlr->stack ); +error: +out: + return ret; +} + +static int pxa_mmc_check_card_stack( mmc_controller_t ctrlr ) +{ + int ret = -1; + mmc_card_t card; + + if ( !ctrlr ) + goto error; + + if ( ctrlr->stack.ncards > 0 ) { +/* for each card in the stack: */ + for( card = ctrlr->stack.first; card; card = card->next ) { + u16 argh = card->info.rca; + u16 argl = 0UL; + +/* 1) send CMD9( card->rca ) */ + if ( pxa_mmc_stop_bus_clock( ctrlr ) ) + goto error; + + /* SanDisk's cards do not respond to CMD9 */ + MMC_CMD = CMD(13); + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD13(0x%04x%04x)\n", + argh, argl ); + ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE ); +/* 2) if card responded, it is still there */ + if ( ret ) + card->state = MMC_CARD_STATE_UNPLUGGED; + } + } + ret = 0; +error: + return ret; +} + +/* This procedure links the bus master with a single card + * 1) cross checks with the internal stack management data if a card still + * exists in the slot + * 2) send CMD7( card->public.rca ) + * 3) setup data path and controller options + */ +static int pxa_mmc_setup_card( mmc_controller_t ctrlr, mmc_card_t card ) +{ + int ret = -ENODEV; + pxa_mmc_hostdata_t hostdata; + pxa_mmc_card_data_t card_data; + u16 argh = 0U; +#ifdef CONFIG_MMC_DEBUG + u16 argl = 0U; +#endif + + if ( !ctrlr || !card ) { + ret = -EINVAL; + goto error; + } + + if ( card->ctrlr != ctrlr ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "card is on another bus\n" ); + goto error; + } + + hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + card_data = (pxa_mmc_card_data_t)card->card_data; + + argh = card->info.rca; + +/* select requested card */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(7); + MMC_ARGH = argh; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD7(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + +/* set controller options */ +#ifndef CONFIG_MMC_DEBUG + MMC_CLKRT = card_data->clkrt; +#endif +/* move the controller to the IDLE state */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE ); + + ret = 0; +error: + return ret; +} + +static inline int pxa_mmc_iobuf_init( mmc_controller_t ctrlr, ssize_t cnt ) +{ +#ifdef PIO + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#endif +#ifndef PIO +/* TODO */ +#else + hostdata->iobuf.buf.pos = hostdata->iobuf.iodata; + hostdata->iobuf.buf.cnt = cnt; +#endif + return 0; +} +/* TODO: ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt ) +effects: reads at most cnt bytes from the card to the controller I/O buffer; + takes care of partial data transfers +requieres: +modifies: ctrlr->iobuf +returns: number of bytes actually transferred or negative error code if there were any errors + */ +ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt ) +{ + ssize_t ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#ifndef PIO + register int ndesc; + int chan = hostdata->iobuf.buf.chan; + pxa_dma_desc *desc; +#endif + + if ( (hostdata->state != PXA_MMC_FSM_END_CMD) && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) { + goto error; + } + + if ( cnt > hostdata->iobuf.bufsz ) + cnt = hostdata->iobuf.bufsz; + + if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) ) + goto error; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ); +#ifndef PIO + if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */ + goto error; + + if ( (desc = hostdata->iobuf.buf.last_read_desc) ) { + desc->ddadr &= ~DDADR_STOP; + desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH); + desc->dcmd |= (1<<5); + } +/* 1) setup descriptors for DMA transfer from the device */ + ndesc = (cnt>>5) - 1; /* FIXME: partial read */ + desc = &hostdata->iobuf.buf.read_desc[ndesc]; + hostdata->iobuf.buf.last_read_desc = desc; + /* TODO: partial read */ + desc->ddadr |= DDADR_STOP; + desc->dcmd |= DCMD_ENDIRQEN; +/* 2) start DMA channel */ + DDADR( chan ) = hostdata->iobuf.buf.read_desc_phys_addr; + DCSR( chan ) |= DCSR_RUN; +#else + if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_RXFIFO_RD_REQ ) ) + goto error; +#endif + + if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) ) + goto error; + + if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) ) + goto error; + + if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */ + ret = cnt; +error: + return ret; +} + +ssize_t pxa_mmc_write_buffer( mmc_controller_t ctrlr, ssize_t cnt ) +{ + ssize_t ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#ifndef PIO + register int ndesc; + int chan = hostdata->iobuf.buf.chan; + pxa_dma_desc *desc; +#endif + + if ( (hostdata->state != PXA_MMC_FSM_END_CMD) + && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state (%s)\n", + PXA_MMC_STATE_LABEL( hostdata->state ) ); + goto error; + } + + if ( cnt > hostdata->iobuf.bufsz ) + cnt = hostdata->iobuf.bufsz; + + if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) ) + goto error; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ); +#ifndef PIO + if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */ + goto error; + if ( (desc = hostdata->iobuf.buf.last_write_desc) ) { + desc->ddadr &= ~DDADR_STOP; + desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH); + desc->dcmd |= (1<<5); + } +/* 1) setup descriptors for DMA transfer to the device */ + ndesc = (cnt>>5) - 1; /* FIXME: partial write */ + desc = &hostdata->iobuf.buf.write_desc[ndesc]; + /* TODO: partial write */ + hostdata->iobuf.buf.last_write_desc = desc; + desc->ddadr |= DDADR_STOP; + desc->dcmd |= DCMD_ENDIRQEN; +/* 2) start DMA channel */ + DDADR( chan ) = hostdata->iobuf.buf.write_desc_phys_addr; + DCSR( chan ) |= DCSR_RUN; +#else + if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_TXFIFO_WR_REQ ) ) + goto error; +#endif + if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) ) + goto error; + + if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) ) + goto error; + + if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */ + ret = cnt; +error: + return ret; +} + +/* TODO: ssize_t pxa_mmc_copy_from_buffer( ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt ) +effects: copies at most cnt bytes from the controller I/O buffer to the user or kernel buffer + pointed by buf +requiers: +modifies: +returns: number of bytes actually transferred or negative error code if there were any errors + */ +ssize_t pxa_mmc_copy_from_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt ) +{ + ssize_t ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + +#ifndef PIO +/* TODO: check that DMA channel is not running */ +#endif + switch ( to ) { + case MMC_USER: + if ( copy_to_user( buf, hostdata->iobuf.iodata, cnt ) ) { + ret = -EFAULT; + goto error; + } + break; + case MMC_KERNEL: + memcpy( buf, hostdata->iobuf.iodata, cnt ); + break; + default: + MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" ); + goto error; + } + ret = cnt; +error: + return ret; +} + +ssize_t pxa_mmc_copy_to_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt ) +{ + ssize_t ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#ifndef PIO +/* check that DMA channel is not running */ +#endif + switch ( to ) { + case MMC_USER: + if ( copy_from_user( hostdata->iobuf.iodata, buf, cnt ) ) { + ret = -EFAULT; + goto error; + } + break; + case MMC_KERNEL: + memcpy( hostdata->iobuf.iodata, buf, cnt ); + break; + default: + MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" ); + goto error; + } + ret = cnt; +error: + return ret; +} + +/* This procedure sequentally passes the data from the user buffer to the card */ +static int pxa_mmc_stream_read( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + u16 argh = 0UL, argl = 0UL; + ssize_t size = 0; + + while ( transfer->cnt > 0 ) { + size = (transfer->cnt < hostdata->iobuf.blksz) ? + transfer->cnt : hostdata->iobuf.blksz; + /* 1. send CMD11 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + argh = transfer->addr >> 16; + argl = transfer->addr; + /* 2. setup controller registers to start stream data transfer */ + MMC_CMD = CMD(11); /* READ_DAT_UNTIL_STOP */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_NOB = 0xffff; + MMC_BLKLEN = size; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + /* 3. wait for cmd to complete */ + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD11(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) ) + goto error; + + /* 4. transfer the data to the caller supplied buffer */ + if ( (ret = pxa_mmc_read_buffer( ctrlr, size )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 ) + goto error; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + transfer->buf += ret; + transfer->addr += ret; + transfer->cnt -= ret; + } + ret = 0; +error: + return ret; +} + +/* This procedure reads a data block from a card at a given kernel address */ +static int pxa_mmc_read_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -ENODEV; + u16 argh = 0UL, argl = 0UL; + +/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default + * for the current card */ + if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) { + argh = transfer->blksz >> 16; + argl = transfer->blksz; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(16); /* SET_BLOCK_LEN */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, + "CMD16(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + } + +/* CMD17 (READ_SINGLE_BLOCK) */ + argh = transfer->addr >> 16; + argl = transfer->addr; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(17); /* READ_SINGLE_BLOCK */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN; + MMC_NOB = 1; + MMC_BLKLEN = transfer->blksz; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD17(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + +/* transfer the data to the caller supplied buffer */ + if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->blksz )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 ) + goto error; + + transfer->buf += ret; + transfer->cnt -= ret; + transfer->nob -= 1; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + ret = 0; +error: + return ret; +} + +/* This procedure sequentally reads data blocks from + * a card to the user buffer. Controller options and block size + * are already set by setup_card(). Data alignment and partial + * data accessibility assumed to be checked by mmc_core */ +static int pxa_mmc_read_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -EIO; + u16 argh = 0UL, argl = 0UL; + +/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default + * for the current card */ + if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) { + argh = transfer->blksz >> 16; + argl = transfer->blksz; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(16); /* SET_BLOCK_LEN */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + } + + argh = transfer->addr >> 16; + argl = transfer->addr; +/* 1. stop bus clock */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + +/* 2. setup controller registers to start multiple block transfer */ + MMC_CMD = CMD(18); /* READ_MULTIPLE_BLOCK */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_NOB = transfer->nob; + MMC_BLKLEN = transfer->blksz; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + +/* 3. start clock */ + if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) ) + goto error; + +/* 4. wait for cmd to complete */ + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD18(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) ) + goto error; + +/* 6. transfer the data to the caller supplied buffer */ + while ( transfer->cnt > 0 ) { + if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->cnt )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 ) + goto error; + + transfer->buf += ret; + transfer->cnt -= ret; + } + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + ret = 0; +error: + return ret; +} + +/* Sequentally writes the data from a user buffer to the card */ +static int pxa_mmc_stream_write( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -EIO; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + u16 argh = 0UL, argl = 0UL; + ssize_t size = 0; + + __ENTER( "transfer: cmd=%d mode=%d type=%d blksz=%d " + "nob=%d buf=%p cnt=%d addr=%Lx", transfer->cmd, + transfer->mode, transfer->type, transfer->blksz, + transfer->nob, transfer->buf, transfer->cnt, transfer->addr ); + + argh = transfer->addr >> 16; + argl = transfer->addr; +/* 1. stop bus clock */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + +/* 2. setup controller registers to start stream data transfer */ + MMC_CMD = CMD(20); /* WRITE_DAT_UNTIL_STOP */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_NOB = 0xffff; + MMC_BLKLEN = hostdata->iobuf.blksz; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + +/* 3. wait for cmd to complete */ + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD20(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) ) + goto error; + +/* 4. transfer the data to the caller supplied buffer */ + while ( transfer->cnt > 0 ) { + size = (transfer->cnt < hostdata->iobuf.blksz) ? + transfer->cnt : hostdata->iobuf.blksz; + if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, + transfer->type, transfer->buf, size )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 ) + goto error; + + transfer->buf += ret; + transfer->cnt -= ret; + } + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + ret = 0; +error: + return ret; +} + +/* This procedure writes a data block to a card at a given address */ +static int pxa_mmc_write_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -ENODEV; + u16 argh = 0UL, argl = 0UL; + +/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default + * for the current card */ + if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) { + argh = transfer->blksz >> 16; + argl = transfer->blksz; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(16); /* SET_BLOCK_LEN */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + } + +/* CMD17 (READ_SINGLE_BLOCK) */ + argh = transfer->addr >> 16; + argl = transfer->addr; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(24); /* WRITE_BLOCK */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + MMC_NOB = 1; + MMC_BLKLEN = transfer->blksz; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD24(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + +/* transfer the data to the caller supplied buffer */ + if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type, transfer->buf, transfer->cnt )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 ) + goto error; + + transfer->buf += ret; + transfer->cnt -= ret; + transfer->nob -= 1; + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + ret = 0; +error: + return ret; +} + +/* This procedure sequentally writes data blocks to a card at a given address */ +static ssize_t pxa_mmc_write_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer ) +{ + int ret = -EIO; + u16 argh = 0UL, argl = 0UL; + +/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default + * for the current card */ + if ( transfer->blksz != ctrlr->stack.selected->info.write_bl_len ) { + argh = transfer->blksz >> 16; + argl = transfer->blksz; + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(16); /* SET_BLOCK_LEN */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_CMDAT = MMC_CMDAT_R1; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) ) + goto error; + } + + argh = transfer->addr >> 16; + argl = transfer->addr; +/* 1. stop bus clock */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + +/* 2. setup controller registers to start multiple block transfer */ + MMC_CMD = CMD(25); /* WRITE_MULTIPLE_BLOCK */ + MMC_ARGH = argh; + MMC_ARGL = argl; + MMC_NOB = transfer->nob; + MMC_BLKLEN = transfer->blksz; + MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN; +#ifndef PIO + MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN; +#endif + +/* 3. start clock */ + if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) ) + goto error; + +/* 4. wait for cmd to complete */ + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD25(0x%04x%04x)\n", argh, argl ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) ) + goto error; + +/* 6. transfer the data to the caller supplied buffer */ + while ( transfer->cnt > 0 ) { + if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type, + transfer->buf, transfer->cnt )) < 0 ) + goto error; + + if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 ) + goto error; + + transfer->buf += ret; + transfer->cnt -= ret; + } + + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO ); + + if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) ) + goto error; + + ret = 0; +error: + return ret; +} + +static void pxa_mmc_irq( int irq, void *dev_id, struct pt_regs *regs ) +{ + mmc_controller_t ctrlr = (mmc_controller_t)dev_id; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#ifdef PIO + register int i, cnt; + register char *buf; +#endif + + hostdata->mmc_i_reg = MMC_I_REG; + hostdata->mmc_stat = MMC_STAT; + hostdata->mmc_cmdat = MMC_CMDAT; +#if 0 + if (hostdata->mmc_i_reg != 0x0010) { + printk("IREG %08x", hostdata->mmc_i_reg); + if (hostdata->mmc_i_reg & 0x0001) printk(" DATA_TRAN_DONE"); + if (hostdata->mmc_i_reg & 0x0002) printk(" PRG_DONE"); + if (hostdata->mmc_i_reg & 0x0004) printk(" END_CMD"); + if (hostdata->mmc_i_reg & 0x0008) printk(" STOP_CMD"); + if (hostdata->mmc_i_reg & 0x0010) printk(" CLK_OFF"); + if (hostdata->mmc_i_reg & 0x0020) printk(" RX_FIFO"); + if (hostdata->mmc_i_reg & 0x0040) printk(" TX_FIFO"); + printk("\nSTAT %08x", hostdata->mmc_stat); + if (hostdata->mmc_stat & 0x0001) printk(" READ_TO"); + if (hostdata->mmc_stat & 0x0002) printk(" RESP_TO"); + if (hostdata->mmc_stat & 0x0004) printk(" WR_CRC"); + if (hostdata->mmc_stat & 0x0008) printk(" READ_CRC"); + if (hostdata->mmc_stat & 0x0010) printk(" SPI_RD_TKN"); + if (hostdata->mmc_stat & 0x0020) printk(" RESP_CRC"); + if (hostdata->mmc_stat & 0x0040) printk(" TX_FIFO"); + if (hostdata->mmc_stat & 0x0080) printk(" RX_FIFO"); + if (hostdata->mmc_stat & 0x0100) printk(" CLK"); + if (hostdata->mmc_stat & 0x0800) printk(" DATA_TRAN_DONE"); + if (hostdata->mmc_stat & 0x1000) printk(" PRG_DONE"); + if (hostdata->mmc_stat & 0x2000) printk(" END_CMD"); + printk("\n"); + } +#endif + +#if CONFIG_MMC_DEBUG_IRQ + if ( --hostdata->irqcnt <= 0 ) { + printk( KERN_INFO __FUNCTION__"(): irqcnt exceeded\n" ); + goto complete; + } +#endif + switch ( hostdata->state ) { + case PXA_MMC_FSM_IDLE: + case PXA_MMC_FSM_CLK_OFF: + case PXA_MMC_FSM_END_IO: + case PXA_MMC_FSM_END_BUFFER: + case PXA_MMC_FSM_END_CMD: + goto complete; +#ifdef PIO + case PXA_MMC_FSM_BUFFER_IN_TRANSIT: + if ( hostdata->mmc_stat & MMC_STAT_ERRORS ) + goto complete; + + buf = hostdata->iobuf.buf.pos; + cnt = (hostdata->iobuf.buf.cnt < 32) ? + hostdata->iobuf.buf.cnt : 32; + if ( hostdata->mmc_cmdat & MMC_CMDAT_WRITE ) { + if ( !(hostdata->mmc_stat & MMC_STAT_XMIT_FIFO_EMPTY) ) + break; + for ( i = 0; i < cnt; i++ ) + MMC_TXFIFO = *buf++; + if ( cnt < 32 ) + MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL; + } else { /* i.e. MMC_CMDAT_READ */ + if( !(hostdata->mmc_stat & MMC_STAT_RECV_FIFO_FULL) ) + break; + for( i = 0; i < cnt; i++ ) + *buf++ = MMC_RXFIFO; + } + + hostdata->iobuf.buf.pos = buf; + hostdata->iobuf.buf.cnt -= i; + if ( hostdata->iobuf.buf.cnt <= 0 ) { + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER ); + MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" ); + goto complete; + } + break; +#endif /* PIO */ + default: + MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state %d\n", + hostdata->state ); + goto complete; + } + return; +complete: + MMC_I_MASK = MMC_I_MASK_ALL; + complete( &hostdata->completion ); + return; +} + +#ifndef PIO +static void pxa_mmc_dma_irq( int irq, void *dev_id, struct pt_regs *regs ) +{ + mmc_controller_t ctrlr = (mmc_controller_t)dev_id; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + u32 dcsr; + u32 ddadr; + int chan = hostdata->iobuf.buf.chan; + + ddadr = DDADR( chan ); + dcsr = DCSR( chan ); + DCSR( chan ) = dcsr & ~DCSR_STOPIRQEN; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, + "MMC DMA interrupt: chan=%d ddadr=0x%08x " + "dcmd=0x%08x dcsr=0x%08x\n", + chan, ddadr, DCMD( chan ), dcsr ); +/* bus error */ + if ( dcsr & DCSR_BUSERR ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "bus error on DMA channel %d\n", + chan ); + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_ERROR ); + goto complete; + } +/* data transfer completed */ + if ( dcsr & DCSR_ENDINTR ) { + MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" ); + pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER ); + goto complete; + } + return; +complete: + complete( &hostdata->completion ); + return; +} +#endif + + +static int pxa_mmc_init( mmc_controller_t ctrlr ) +{ + int ret = -ENODEV; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; +#ifndef PIO + register int i; + register pxa_dma_desc *desc; +#endif + +/* hardware initialization */ +/* I. prepare to transfer data */ +/* 1. allocate buffer */ +#ifndef PIO + hostdata->iobuf.buf.read_desc = consistent_alloc( GFP_KERNEL, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + &hostdata->iobuf.buf.read_desc_phys_addr, 0 ); + if ( !hostdata->iobuf.buf.read_desc ) { + ret = -ENOMEM; + goto error; + } + hostdata->iobuf.buf.write_desc = consistent_alloc( GFP_KERNEL, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + &hostdata->iobuf.buf.write_desc_phys_addr, 0 ); + if ( !hostdata->iobuf.buf.write_desc ) { + ret = -ENOMEM; + goto error; + } + hostdata->iobuf.iodata = consistent_alloc( GFP_ATOMIC, + PXA_MMC_IODATA_SIZE, + &hostdata->iobuf.buf.phys_addr, 0 ); +#else + hostdata->iobuf.iodata = kmalloc( PXA_MMC_IODATA_SIZE, GFP_ATOMIC ); +#endif + if ( !hostdata->iobuf.iodata ) { + ret = -ENOMEM; + goto error; + } +/* 2. initialize iobuf */ + hostdata->iobuf.blksz = PXA_MMC_BLKSZ_MAX; + hostdata->iobuf.bufsz = PXA_MMC_IODATA_SIZE; + hostdata->iobuf.nob = PXA_MMC_BLOCKS_PER_BUFFER; +#ifndef PIO + /* request DMA channel */ + if ( (hostdata->iobuf.buf.chan = pxa_request_dma( "MMC", DMA_PRIO_LOW, + pxa_mmc_dma_irq, ctrlr )) < 0 ) { + MMC_ERROR( "failed to request DMA channel\n" ); + goto error; + } + + DRCMRRXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD; + DRCMRTXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD; + + for ( i = 0; i < ((PXA_MMC_IODATA_SIZE>>5) - 1); i++ ) { + desc = &hostdata->iobuf.buf.read_desc[i]; + desc->ddadr = hostdata->iobuf.buf.read_desc_phys_addr + + ((i + 1) * sizeof( pxa_dma_desc )); + desc->dsadr = MMC_RXFIFO_PHYS_ADDR; + desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5); + desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR + |DCMD_WIDTH1|DCMD_BURST32|(1<<5); + + desc = &hostdata->iobuf.buf.write_desc[i]; + desc->ddadr = hostdata->iobuf.buf.write_desc_phys_addr + + ((i + 1) * sizeof( pxa_dma_desc )); + desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5); + desc->dtadr = MMC_TXFIFO_PHYS_ADDR; + desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR + |DCMD_WIDTH1|DCMD_BURST32|(1<<5); + } + desc = &hostdata->iobuf.buf.read_desc[i]; + desc->ddadr = (hostdata->iobuf.buf.read_desc_phys_addr + + (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP; + desc->dsadr = MMC_RXFIFO_PHYS_ADDR; + desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5); + desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR + |DCMD_WIDTH1|DCMD_BURST32|(1<<5); + + desc = &hostdata->iobuf.buf.write_desc[i]; + desc->ddadr = (hostdata->iobuf.buf.write_desc_phys_addr + + (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP; + desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5); + desc->dtadr = MMC_TXFIFO_PHYS_ADDR; + desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR + |DCMD_WIDTH1|DCMD_BURST32|(1<<5); +#endif +/* II. MMC */ +/* 1) request irq */ + if ( request_irq( IRQ_MMC, pxa_mmc_irq, 0, "MMC", ctrlr ) ) { + MMC_ERROR( "failed to request IRQ_MMC\n" ); + goto error; + } + +/* 2) initialize h/w and ctrlr */ + set_GPIO_mode( GPIO6_MMCCLK_MD ); + CKEN |= CKEN12_MMC; /* enable MMC unit clock */ + + ret = 0; + goto out; +error: +#ifndef PIO +/* free DMA resources */ + if ( hostdata->iobuf.buf.chan >= 0 ) { + DRCMRRXMMC = 0; + DRCMRTXMMC = 0; + pxa_free_dma( hostdata->iobuf.buf.chan ); + } + if ( hostdata->iobuf.iodata ) + consistent_free( hostdata->iobuf.iodata, + PXA_MMC_IODATA_SIZE, + hostdata->iobuf.buf.phys_addr ); + if ( hostdata->iobuf.buf.read_desc ) + consistent_free( hostdata->iobuf.buf.read_desc, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + hostdata->iobuf.buf.read_desc_phys_addr ); + if ( hostdata->iobuf.buf.write_desc ) + consistent_free( hostdata->iobuf.buf.write_desc, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + hostdata->iobuf.buf.write_desc_phys_addr ); +#else + kfree( hostdata->iobuf.iodata ); +#endif +out: + return ret; +} + +static void pxa_mmc_remove( mmc_controller_t ctrlr ) +{ + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + +/* 1) free buffer(s) */ +#ifndef PIO + consistent_free( hostdata->iobuf.iodata, PXA_MMC_IODATA_SIZE, + hostdata->iobuf.buf.phys_addr ); + consistent_free( hostdata->iobuf.buf.read_desc, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + hostdata->iobuf.buf.read_desc_phys_addr ); + consistent_free( hostdata->iobuf.buf.write_desc, + (PXA_MMC_IODATA_SIZE>>5) + * sizeof( pxa_dma_desc ), + hostdata->iobuf.buf.write_desc_phys_addr ); +/* 2) release DMA channel */ + if ( hostdata->iobuf.buf.chan >= 0 ) { + DRCMRRXMMC = 0; + DRCMRTXMMC = 0; + pxa_free_dma( hostdata->iobuf.buf.chan ); + } +#else + kfree( hostdata->iobuf.iodata ); +#endif +/* II. MMC */ +/* 1) release irq */ + free_irq( IRQ_MMC, ctrlr ); + CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */ +} + +static int pxa_mmc_probe( mmc_controller_t ctrlr ) +{ + return 1; +} + +#ifdef CONFIG_PM +static int pxa_mmc_suspend( mmc_controller_t ctrlr ) +{ + int ret = -EBUSY; + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + MMC_DEBUG( MMC_DEBUG_LEVEL2, "state=%s\n", + PXA_MMC_STATE_LABEL( hostdata->state ) ); + + if ( hostdata->state == PXA_MMC_FSM_IDLE ) { + /* save registers */ + SAVED_MMC_CLKRT = MMC_CLKRT; + SAVED_MMC_RESTO = MMC_RESTO; + SAVED_MMC_SPI = MMC_SPI; + SAVED_DRCMRRXMMC = DRCMRRXMMC; + SAVED_DRCMRTXMMC = DRCMRTXMMC; + +#if 0 /* FIXME */ + /* send CMD0 */ + if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) ) + goto error; + + MMC_CMD = CMD(0); /* CMD0 with zero argument */ + MMC_ARGH = 0UL; + MMC_ARGL = 0UL; + MMC_CMDAT = 0UL; + + MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", 0UL, 0UL ); + if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, + FALSE )) ) + { + ret = -EIO; + goto error; + } +#endif + + set_GPIO_mode( GPIO6_MMCCLK ); + CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */ + + hostdata->suspended = TRUE; + ret = 0; + } +error: + return ret; +} + +static void pxa_mmc_resume( mmc_controller_t ctrlr ) +{ + pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data; + + if ( hostdata->suspended == TRUE ) { + set_GPIO_mode( GPIO6_MMCCLK_MD ); + CKEN |= CKEN12_MMC; /* enable MMC unit clock */ + + /* restore registers */ + MMC_CLKRT = SAVED_MMC_CLKRT; + MMC_RESTO = SAVED_MMC_RESTO; + MMC_SPI = SAVED_MMC_SPI; + DRCMRRXMMC = SAVED_DRCMRRXMMC; + DRCMRTXMMC = SAVED_DRCMRTXMMC; + + hostdata->suspended = FALSE; + + mmc_update_card_stack( ctrlr->slot ); /* FIXME */ + } + + return; +} +#endif + +static mmc_controller_tmpl_rec_t pxa_mmc_controller_tmpl_rec = { + owner: THIS_MODULE, + name: "PXA250", + block_size_max: PXA_MMC_BLKSZ_MAX, + nob_max: PXA_MMC_NOB_MAX, + probe: pxa_mmc_probe, + init: pxa_mmc_init, + remove: __devexit_p( pxa_mmc_remove ), +#ifdef CONFIG_PM + suspend: pxa_mmc_suspend, + resume: pxa_mmc_resume, +#endif /* CONFIG_PM */ + update_acq: pxa_mmc_update_acq, +// single_card_acq: pxa_mmc_single_card_acq, + init_card_stack: pxa_mmc_init_card_stack, + check_card_stack: pxa_mmc_check_card_stack, + setup_card: pxa_mmc_setup_card, + stream_read: pxa_mmc_stream_read, + read_block: pxa_mmc_read_block, + read_mblock: pxa_mmc_read_mblock, + stream_write: pxa_mmc_stream_write, + write_block: pxa_mmc_write_block, + write_mblock: pxa_mmc_write_mblock + /* TODO + sg_io: pxa_mmc_sg_io + */ + /* TODO: + * erase, + * write protection, + * lock/password management methods + */ +}; + +static int __devinit mmc_pxa_module_init( void ) +{ + int ret = -ENODEV; +#ifdef CONFIG_ARCH_RAMSES + RAMSES_MMC_ON(); + udelay(1000); +#endif + + host = mmc_register( MMC_REG_TYPE_HOST, &pxa_mmc_controller_tmpl_rec, + sizeof( pxa_mmc_hostdata_rec_t ) ); + if ( !host ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, + "failed to register with MMC core\n" ); + goto error; + } + + ret = 0; +error: + return ret; +} + +static void __devexit mmc_pxa_module_cleanup( void ) +{ + mmc_unregister( MMC_REG_TYPE_HOST, host ); +#ifdef CONFIG_ARCH_RAMSES + RAMSES_MMC_OFF(); +#endif +} + +EXPORT_NO_SYMBOLS; + +MODULE_LICENSE( "GPL" ); + +module_init( mmc_pxa_module_init ); +module_exit( mmc_pxa_module_cleanup ); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/mmc_pxa.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,278 @@ +/* + * linux/drivers/mmc/mmc_pxa.h + * + * Author: Vladimir Shebordaev, Igor Oblakov + * Copyright: MontaVista Software Inc. + * + * $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MMC_PXA_P_H__ +#define __MMC_PXA_P_H__ + +#include + +#define PIO + +/* PXA-250 MMC controller registers */ + +/* MMC_STRPCL */ +#define MMC_STRPCL_STOP_CLK (0x0001UL) +#define MMC_STRPCL_START_CLK (0x0002UL) + +/* MMC_STAT */ +#define MMC_STAT_END_CMD_RES (0x0001UL << 13) +#define MMC_STAT_PRG_DONE (0x0001UL << 12) +#define MMC_STAT_DATA_TRAN_DONE (0x0001UL << 11) +#define MMC_STAT_CLK_EN (0x0001UL << 8) +#define MMC_STAT_RECV_FIFO_FULL (0x0001UL << 7) +#define MMC_STAT_XMIT_FIFO_EMPTY (0x0001UL << 6) +#define MMC_STAT_RES_CRC_ERROR (0x0001UL << 5) +#define MMC_STAT_SPI_READ_ERROR_TOKEN (0x0001UL << 4) +#define MMC_STAT_CRC_READ_ERROR (0x0001UL << 3) +#define MMC_STAT_CRC_WRITE_ERROR (0x0001UL << 2) +#define MMC_STAT_TIME_OUT_RESPONSE (0x0001UL << 1) +#define MMC_STAT_READ_TIME_OUT (0x0001UL) + +#define MMC_STAT_ERRORS (MMC_STAT_RES_CRC_ERROR|MMC_STAT_SPI_READ_ERROR_TOKEN\ + |MMC_STAT_CRC_READ_ERROR|MMC_STAT_TIME_OUT_RESPONSE\ + |MMC_STAT_READ_TIME_OUT) + +/* MMC_CLKRT */ +#define MMC_CLKRT_20MHZ (0x0000UL) +#define MMC_CLKRT_10MHZ (0x0001UL) +#define MMC_CLKRT_5MHZ (0x0002UL) +#define MMC_CLKRT_2_5MHZ (0x0003UL) +#define MMC_CLKRT_1_25MHZ (0x0004UL) +#define MMC_CLKRT_0_625MHZ (0x0005UL) +#define MMC_CLKRT_0_3125MHZ (0x0006UL) + +/* MMC_SPI */ +#define MMC_SPI_DISABLE (0x00UL) +#define MMC_SPI_EN (0x01UL) +#define MMC_SPI_CS_EN (0x01UL << 2) +#define MMC_SPI_CS_ADDRESS (0x01UL << 3) +#define MMC_SPI_CRC_ON (0x01UL << 1) + +/* MMC_CMDAT */ +#define MMC_CMDAT_MMC_DMA_EN (0x0001UL << 7) +#define MMC_CMDAT_INIT (0x0001UL << 6) +#define MMC_CMDAT_BUSY (0x0001UL << 5) +#define MMC_CMDAT_STREAM (0x0001UL << 4) +#define MMC_CMDAT_BLOCK (0x0000UL << 4) +#define MMC_CMDAT_WRITE (0x0001UL << 3) +#define MMC_CMDAT_READ (0x0000UL << 3) +#define MMC_CMDAT_DATA_EN (0x0001UL << 2) +#define MMC_CMDAT_R1 (0x0001UL) +#define MMC_CMDAT_R2 (0x0002UL) +#define MMC_CMDAT_R3 (0x0003UL) + +/* MMC_RESTO */ +#define MMC_RES_TO_MAX (0x007fUL) /* [6:0] */ + +/* MMC_RDTO */ +#define MMC_READ_TO_MAX (0x0ffffUL) /* [15:0] */ + +/* MMC_BLKLEN */ +#define MMC_BLK_LEN_MAX (0x03ffUL) /* [9:0] */ + +/* MMC_PRTBUF */ +#define MMC_PRTBUF_BUF_PART_FULL (0x01UL) +#define MMC_PRTBUF_BUF_FULL (0x00UL ) + +/* MMC_I_MASK */ +#define MMC_I_MASK_TXFIFO_WR_REQ (0x01UL << 6) +#define MMC_I_MASK_RXFIFO_RD_REQ (0x01UL << 5) +#define MMC_I_MASK_CLK_IS_OFF (0x01UL << 4) +#define MMC_I_MASK_STOP_CMD (0x01UL << 3) +#define MMC_I_MASK_END_CMD_RES (0x01UL << 2) +#define MMC_I_MASK_PRG_DONE (0x01UL << 1) +#define MMC_I_MASK_DATA_TRAN_DONE (0x01UL) +#define MMC_I_MASK_ALL (0x07fUL) + + +/* MMC_I_REG */ +#define MMC_I_REG_TXFIFO_WR_REQ (0x01UL << 6) +#define MMC_I_REG_RXFIFO_RD_REQ (0x01UL << 5) +#define MMC_I_REG_CLK_IS_OFF (0x01UL << 4) +#define MMC_I_REG_STOP_CMD (0x01UL << 3) +#define MMC_I_REG_END_CMD_RES (0x01UL << 2) +#define MMC_I_REG_PRG_DONE (0x01UL << 1) +#define MMC_I_REG_DATA_TRAN_DONE (0x01UL) +#define MMC_I_REG_ALL (0x007fUL) + +/* MMC_CMD */ +#define MMC_CMD_INDEX_MAX (0x006fUL) /* [5:0] */ +#define CMD(x) (x) + +/* MMC_ARGH */ +/* MMC_ARGL */ +/* MMC_RES */ +/* MMC_RXFIFO */ +#define MMC_RXFIFO_PHYS_ADDR 0x41100040 //MMC_RXFIFO physical address +/* MMC_TXFIFO */ +#define MMC_TXFIFO_PHYS_ADDR 0x41100044 //MMC_TXFIFO physical address + +/* implementation specific declarations */ +#define PXA_MMC_BLKSZ_MAX (1<<9) /* actually 1023 */ +#define PXA_MMC_NOB_MAX ((1<<16)-2) +#define PXA_MMC_BLOCKS_PER_BUFFER (2) + +#define PXA_MMC_IODATA_SIZE (PXA_MMC_BLOCKS_PER_BUFFER*PXA_MMC_BLKSZ_MAX) /* 1K */ + +typedef enum _pxa_mmc_fsm { /* command processing FSM */ + PXA_MMC_FSM_IDLE = 1, + PXA_MMC_FSM_CLK_OFF, + PXA_MMC_FSM_END_CMD, + PXA_MMC_FSM_BUFFER_IN_TRANSIT, + PXA_MMC_FSM_END_BUFFER, + PXA_MMC_FSM_END_IO, + PXA_MMC_FSM_END_PRG, + PXA_MMC_FSM_ERROR +} pxa_mmc_state_t; + +#define PXA_MMC_STATE_LABEL( state ) (\ + (state == PXA_MMC_FSM_IDLE) ? "IDLE" :\ + (state == PXA_MMC_FSM_CLK_OFF) ? "CLK_OFF" :\ + (state == PXA_MMC_FSM_END_CMD) ? "END_CMD" :\ + (state == PXA_MMC_FSM_BUFFER_IN_TRANSIT) ? "IN_TRANSIT" :\ + (state == PXA_MMC_FSM_END_BUFFER) ? "END_BUFFER" :\ + (state == PXA_MMC_FSM_END_IO) ? "END_IO" :\ + (state == PXA_MMC_FSM_END_PRG) ? "END_PRG" : "UNKNOWN" ) + +typedef enum _pxa_mmc_result { + PXA_MMC_NORMAL = 0, + PXA_MMC_INVALID_STATE = -1, + PXA_MMC_TIMEOUT = -2, + PXA_MMC_ERROR = -3 +} pxa_mmc_result_t; + +typedef u32 pxa_mmc_clkrt_t; + +typedef char *pxa_mmc_iodata_t; +#ifdef PIO +typedef struct _pxa_mmc_piobuf_rec { + char *pos; /* current buffer position */ + int cnt; /* byte counter */ +} pxa_mmc_piobuf_rec_t, *pxa_mmc_piobuf_t; +#else /* i.e. DMA */ +typedef struct _pxa_mmc_dmabuf_rec { /* TODO: buffer ring, DMA irq completion */ + int chan; /* dma channel no */ + dma_addr_t phys_addr; /* iodata physical address */ + pxa_dma_desc *read_desc; /* input descriptor array virtual address */ + pxa_dma_desc *write_desc; /* output descriptor array virtual address */ + dma_addr_t read_desc_phys_addr; /* descriptor array physical address */ + dma_addr_t write_desc_phys_addr; /* descriptor array physical address */ + pxa_dma_desc *last_read_desc; /* last input descriptor + * used by the previous transfer + */ + pxa_dma_desc *last_write_desc; /* last output descriptor + * used by the previous transfer + */ +} pxa_mmc_dmabuf_rec_t, *pxa_mmc_dmabuf_t; +#endif + +typedef struct _pxa_mmc_iobuf_rec { + ssize_t blksz; /* current block size in bytes */ + ssize_t bufsz; /* buffer size for each transfer */ + ssize_t nob; /* number of blocks pers buffer */ +#ifndef PIO + pxa_mmc_dmabuf_rec_t buf; /* i.e. DMA buffer ring on the iodata */ +#else /* i.e. DMA */ + pxa_mmc_piobuf_rec_t buf; /* PIO buffer accounting */ +#endif + pxa_mmc_iodata_t iodata; /* I/O data buffer */ +} pxa_mmc_iobuf_rec_t, *pxa_mmc_iobuf_t; + +typedef struct _pxa_mmc_hostdata_rec { + pxa_mmc_state_t state; /* FSM */ +#ifdef CONFIG_PM + int suspended; +#endif + pxa_mmc_iobuf_rec_t iobuf; /* data transfer state */ + + int busy; /* atomic busy flag */ + struct completion completion; /* completion */ +#if CONFIG_MMC_DEBUG_IRQ + int irqcnt; + int timeo; +#endif + +/* cached controller state */ + u32 mmc_i_reg; /* interrupt last requested */ + u32 mmc_i_mask; /* mask to be set by intr handler */ + u32 mmc_stat; /* status register at the last intr */ + u32 mmc_cmdat; /* MMC_CMDAT at the last inr */ + u8 mmc_res[16]; /* response to the last command in host order */ + u32 saved_mmc_clkrt; + u32 saved_mmc_resto; + u32 saved_mmc_spi; + u32 saved_drcmrrxmmc; + u32 saved_drcmrtxmmc; + +/* controller options */ + pxa_mmc_clkrt_t clkrt; /* current bus clock rate */ +} pxa_mmc_hostdata_rec_t, *pxa_mmc_hostdata_t; + +#define PXA_MMC_STATUS( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_stat) +#define PXA_MMC_RESPONSE( ctrlr, idx ) ((((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_res)[idx]) +#define PXA_MMC_CLKRT( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->clkrt) + +#define SAVED_MMC_CLKRT (hostdata->saved_mmc_clkrt) +#define SAVED_MMC_RESTO (hostdata->saved_mmc_resto) +#define SAVED_MMC_SPI (hostdata->saved_mmc_spi) +#define SAVED_DRCMRRXMMC (hostdata->saved_drcmrrxmmc ) +#define SAVED_DRCMRTXMMC (hostdata->saved_drcmrtxmmc ) + +static inline int pxa_mmc_clkrt( int speed ) +{ + return MMC_CLKRT_20MHZ; /* TODO */ +} + +/* PXA MMC controller specific card data */ +typedef struct _pxa_mmc_card_data_rec { + pxa_mmc_clkrt_t clkrt; /* clock rate to be set for the card */ +} pxa_mmc_card_data_rec_t, *pxa_mmc_card_data_t; + +#ifdef CONFIG_MMC_DEBUG +#undef MMC_DUMP_R1 +#undef MMC_DUMP_R2 +#undef MMC_DUMP_R3 +#define MMC_DUMP_R2( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \ +"R2 response: %02x %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", \ +PXA_MMC_RESPONSE( ctrlr, 15 ), \ +PXA_MMC_RESPONSE( ctrlr, 14 ), \ +PXA_MMC_RESPONSE( ctrlr, 13 ), \ +PXA_MMC_RESPONSE( ctrlr, 12 ), \ +PXA_MMC_RESPONSE( ctrlr, 11 ), \ +PXA_MMC_RESPONSE( ctrlr, 10 ), \ +PXA_MMC_RESPONSE( ctrlr, 9 ), \ +PXA_MMC_RESPONSE( ctrlr, 8 ), \ +PXA_MMC_RESPONSE( ctrlr, 7 ), \ +PXA_MMC_RESPONSE( ctrlr, 6 ), \ +PXA_MMC_RESPONSE( ctrlr, 5 ), \ +PXA_MMC_RESPONSE( ctrlr, 4 ), \ +PXA_MMC_RESPONSE( ctrlr, 3 ), \ +PXA_MMC_RESPONSE( ctrlr, 2 ), \ +PXA_MMC_RESPONSE( ctrlr, 1 ), \ +PXA_MMC_RESPONSE( ctrlr, 0 ) ); +#define MMC_DUMP_R1( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \ +"R1(b) response: %02x %02x%02x%02x%02x\n", \ +PXA_MMC_RESPONSE( ctrlr, 5 ), \ +PXA_MMC_RESPONSE( ctrlr, 4 ), \ +PXA_MMC_RESPONSE( ctrlr, 3 ), \ +PXA_MMC_RESPONSE( ctrlr, 2 ), \ +PXA_MMC_RESPONSE( ctrlr, 1 ) ); +#define MMC_DUMP_R3( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \ +"R3 response: %02x %02x%02x%02x%02x\n", \ +PXA_MMC_RESPONSE( ctrlr, 5 ), \ +PXA_MMC_RESPONSE( ctrlr, 4 ), \ +PXA_MMC_RESPONSE( ctrlr, 3 ), \ +PXA_MMC_RESPONSE( ctrlr, 2 ), \ +PXA_MMC_RESPONSE( ctrlr, 1 ) ); + +#endif +#endif /* __MMC_PXA_P_H__ */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/mmc_test.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,538 @@ +/* + * linux/drivers/mmc/mmc_test.c + * + * Author: Vladimir Shebordaev + * Copyright: MontaVista Software Inc. + * + * $Id: mmc_test.c,v 0.4 2002/08/01 12:26:40 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#include + +#include +#include +#include + +#include "types.h" +#include "mmc.h" + +typedef struct _mmc_test_device_rec mmc_test_device_rec_t; +typedef struct _mmc_test_device_rec *mmc_test_device_t; + +struct _mmc_test_device_rec { + mmc_card_t card; + mmc_transfer_mode_t transfer_mode; + int usage; +#ifdef CONFIG_DEVFS_FS + devfs_handle_t devfs_handle; +#endif +}; + +/* MMC device table */ +static mmc_test_device_rec_t mmc_test_device[MMC_CONTROLLERS_MAX][MMC_CARDS_MAX]; +static DECLARE_MUTEX(mmc_test_device_mutex); + +static inline mmc_test_device_t __mmc_test_get_device( kdev_t rdev ) +{ + mmc_test_device_t ret = NULL; + u8 minor = MINOR( rdev ); + int host_no, card_no; + + host_no = minor >> MMC_MINOR_HOST_SHIFT; + if ( host_no >= MMC_CONTROLLERS_MAX ) + goto error; + + card_no = minor & MMC_MINOR_CARD_MASK; + if ( card_no >= MMC_CARDS_MAX ) + goto error; + + ret = &mmc_test_device[host_no][card_no]; + if ( !ret->card ) { + ret->card = mmc_get_card( host_no, card_no ); + if ( !ret->card ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to get card: host=%d, card=%d\n", host_no, card_no ); + ret = NULL; + goto error; + } + + } + ++ret->usage; + +error: + return ret; +} + +static inline void __mmc_test_put_device( mmc_test_device_t dev ) +{ + mmc_put_card( dev->card ); + --dev->usage; +} + +static inline mmc_test_device_t mmc_test_get_device( kdev_t kdev ) +{ + mmc_test_device_t ret = NULL; + + down( &mmc_test_device_mutex ); + ret = __mmc_test_get_device( kdev ); + up( &mmc_test_device_mutex ); + + return ret; +} + +static inline void mmc_test_put_device( mmc_test_device_t dev ) +{ + if ( dev ) { + down( &mmc_test_device_mutex ); + __mmc_test_put_device( dev ); + if ( !dev->usage ) { + if ( dev->card ) { + if ( dev->card->usage ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, + "broken card reference\n" ); + } + memset( dev, 0, sizeof( mmc_test_device_rec_t ) ); + } + } + up( &mmc_test_device_mutex ); + } +} + +static inline int mmc_test_set_transfer_mode( mmc_test_device_t dev, mmc_transfer_mode_t mode ) +{ + int ret = -1; + + if ( dev ) { + down( &mmc_test_device_mutex ); + dev->transfer_mode = mode; + ret = 0; + up( &mmc_test_device_mutex ); + } + return ret; +} + +static inline mmc_transfer_mode_t mmc_test_get_transfer_mode( mmc_test_device_t dev ) +{ + mmc_transfer_mode_t ret = MMC_TRANSFER_MODE_UNDEFINED; + + if ( dev ) { + down( &mmc_test_device_mutex ); + ret = dev->transfer_mode; + up( &mmc_test_device_mutex ); + } + return ret; +} + +static int mmc_test_open( struct inode *inode, struct file *file ) +{ + int ret = -ENODEV; + mmc_test_device_t dev = NULL; + + MOD_INC_USE_COUNT; + + __ENTER0( ); + dev = mmc_test_get_device( inode->i_rdev ); + if ( !dev || !dev->card ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to acquire device\n" ); + goto error; + } + + if ( dev->card->usage > 1 ) { + ret = -EBUSY; + goto error; + } + + dev->transfer_mode = MMC_TEST_TRANSFER_MODE_DEFAULT; /* FIXME: should check card CCC */ + file->private_data = dev; + + __LEAVE0( ); + return 0; +error: + MOD_DEC_USE_COUNT; + mmc_test_put_device( dev ); + __LEAVE( "ret=%d", ret ); + return ret; +} + +static int mmc_test_release( struct inode *inode, struct file *file ) +{ + int ret = -ENODEV; + mmc_test_device_t dev = (mmc_test_device_t)file->private_data; + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" ); + goto error; + } + + __ENTER( "host=%d, card=%d", dev->card->ctrlr->slot, dev->card->slot ); + + file->private_data = NULL; + + mmc_test_put_device( dev ); + MOD_DEC_USE_COUNT; + + ret = 0; +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static ssize_t mmc_test_read( struct file *file, char *buf, size_t size, loff_t *ppos ) +{ + ssize_t ret = -ENODEV; + ssize_t retsize = 0; + mmc_test_device_t dev = (mmc_test_device_t)file->private_data; + + __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size ); + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" ); + goto error; + } + + switch ( dev->transfer_mode ) { + char *mbuf; + + case MMC_TRANSFER_MODE_BLOCK_SINGLE: + mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual read_bl_len or ctrlr->block_size_max whichever is less ), GFP_KERNEL */ + if ( !mbuf ) { + ret = -ENOMEM; + goto error; + } + + while( size > 0 ) { + int lsize = (size > 512) ? 512 : size; + + MMC_DEBUG( MMC_DEBUG_LEVEL4, + "before mmc_read mbuf=0x%x " + "lsize=%d ppos=0x%x *ppos=%d\n", + mbuf, lsize, ppos, *ppos ); + ret = mmc_read( dev->card, + MMC_TRANSFER_MODE_BLOCK_SINGLE, + mbuf, lsize, ppos ); + if ( ret <= 0 ) + break; + + /* Copy to user */ + if ( copy_to_user( buf, mbuf, ret ) ) { + ret = -EFAULT; + break; + } + retsize += ret; + buf += ret; + size -= ret; + } + + if ( retsize > 0 ) + ret = retsize; + kfree(mbuf); + break; + + case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: + mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */ + if ( !mbuf ) { + ret = -ENOMEM; + goto error; + } + + while( size > 0 ) { + int lsize = (size > 1024) ? 1024 : size; + + MMC_DEBUG( MMC_DEBUG_LEVEL4, + "before mmc_read mbuf=0x%x " + "lsize=%d ppos=0x%x *ppos=%d\n", + mbuf, lsize, ppos, *ppos ); + ret = mmc_read( dev->card, + MMC_TRANSFER_MODE_BLOCK_MULTIPLE, + mbuf, lsize, ppos ); + if ( ret <= 0 ) + break; + + /* Copy to user */ + if ( copy_to_user( buf, mbuf, ret ) ) { + ret = -EFAULT; + break; + } + retsize += ret; + buf += ret; + size -= ret; + } + + if ( retsize > 0 ) + ret = retsize; + kfree(mbuf); + break; + + case MMC_TRANSFER_MODE_STREAM: + ret = mmc_read( dev->card, dev->transfer_mode, + buf, size, ppos ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" ); + } +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static ssize_t mmc_test_write( struct file *file, const char *buf, size_t size, loff_t *ppos ) +{ + ssize_t ret = -ENODEV; + mmc_test_device_t dev = (mmc_test_device_t)file->private_data; + int retsize=0; + + __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size ); + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" ); + goto error; + } + + switch ( dev->transfer_mode ) { + char *mbuf; + + case MMC_TRANSFER_MODE_BLOCK_SINGLE: + mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual write_bl_len or ctrlr->block_size_max whichever is less, GFP_KERNEL */ + if ( !mbuf ) { + ret = -ENOMEM; + goto error; + } + + while ( size > 0 ) { + int lsize = ( size > 512 ) ? 512 : size; + + /* Copy from user */ + if ( copy_from_user( mbuf, buf, lsize ) ) { + ret = -EFAULT; + break; + } + + ret = mmc_write( dev->card, + MMC_TRANSFER_MODE_BLOCK_SINGLE, + mbuf, lsize, ppos ); + if( ret <= 0 ) + break; + + retsize += ret; + buf += ret; + size -= ret; + } + + if ( retsize > 0 ) + ret = retsize; + + kfree( mbuf ); + break; + + case MMC_TRANSFER_MODE_BLOCK_MULTIPLE: + mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */ + if ( !mbuf ) { + ret = -ENOMEM; + goto error; + } + + while( size > 0 ) { + int lsize = (size > 1024) ? 1024 : size; + + MMC_DEBUG( MMC_DEBUG_LEVEL4, + "before mmc_read mbuf=0x%x " + "lsize=%d ppos=0x%x *ppos=%d\n", + mbuf, lsize, ppos, *ppos ); + ret = mmc_write( dev->card, + MMC_TRANSFER_MODE_BLOCK_MULTIPLE, + mbuf, lsize, ppos ); + if ( ret <= 0 ) + break; + + /* Copy to user */ + if ( copy_to_user( (char *)buf, mbuf, ret ) ) { + ret = -EFAULT; + break; + } + retsize += ret; + buf += ret; + size -= ret; + } + + if ( retsize > 0 ) + ret = retsize; + kfree(mbuf); + break; + case MMC_TRANSFER_MODE_STREAM: + ret = mmc_write( dev->card, dev->transfer_mode, + buf, size, ppos ); + break; + + default: + MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" ); + } +error: + __LEAVE( "ret=%d", ret ); + return ret; +} + +static loff_t mmc_test_llseek( struct file *file, loff_t offset, int origin ) +{ + loff_t ret = -ESPIPE; + mmc_test_device_t dev = (mmc_test_device_t)file->private_data; + mmc_card_t card; + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" ); + ret = -ENODEV; + goto error; + } + + __ENTER( "host=%d, card=%d, off=%ld, orig=%d", dev->card->ctrlr->slot, dev->card->slot, (long)offset, origin ); + + card = dev->card; + + switch ( origin ) { + case SEEK_CUR: + file->f_pos += offset; + break; + + case SEEK_END: + file->f_pos = card->info.capacity + offset; + break; + + case SEEK_SET: + file->f_pos = offset; + break; + + default: + ret = -EINVAL; + goto error; + } + + ret = file->f_pos; +error: + __LEAVE( "ret=%ld", (long)ret ); + return ret; +} + +static int mmc_test_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) +{ + int ret = -ENODEV; + mmc_test_device_t dev = (mmc_test_device_t)file->private_data; + + if ( !dev ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" ); + goto error; + } + + switch ( cmd ) { + case IOCMMCSTRNSMODE: + if ( get_user( ret, (int *)arg ) ) { + ret = -EFAULT; + goto error; + } + ret = mmc_test_set_transfer_mode( dev, ret ); + break; + + case IOCMMCGTRNSMODE: + ret = mmc_test_get_transfer_mode( dev ); + if ( put_user( ret, (int *)arg ) ) + ret = -EFAULT; + break; + + default: + ret = mmc_ioctl( dev->card, cmd, arg ); + } + +error: + return ret; +} + +struct file_operations mmc_test_fops = { + owner: THIS_MODULE, + open: mmc_test_open, + release: mmc_test_release, + read: mmc_test_read, + write: mmc_test_write, + ioctl: mmc_test_ioctl, + llseek: mmc_test_llseek +}; + +#ifdef CONFIG_DEVFS_FS +static int mmc_test_add_card( mmc_card_t card ) /* TODO */ +{ + int ret = -1; + __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot ); +/* TODO: make kdev; register with devfs */ + __LEAVE0( ); + return ret; +} + +static int mmc_test_remove_card( mmc_card_t card ) /* TODO */ +{ + int ret = -1; + __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot ); +/* TODO: make kdev; unregister with devfs */ + __LEAVE0( ); + return ret; +} + +static mmc_notifier_rec_t mmc_test_notifier = { + add: mmc_test_add_card, + remove: mmc_test_remove_card +}; +#endif /* CONFIG_DEVFS_FS */ + +static int __init mmc_test_module_init( void ) +{ + int ret = -ENODEV; + +#ifdef CONFIG_DEVFS_FS + if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_test_notifier, 0 ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" ); + goto error; + } +#else + mmc_register( MMC_REG_TYPE_USER, NULL, 0 ); + if ( register_chrdev( MMC_TEST_MAJOR, "mmc_test", &mmc_test_fops ) ) { + MMC_DEBUG( MMC_DEBUG_LEVEL0, + "failed to request device major number\n" ); + mmc_unregister( MMC_REG_TYPE_USER, NULL ); + goto error; + } +#endif + + memset( mmc_test_device, 0, sizeof( mmc_test_device ) ); + + ret = 0; +error: + return ret; +} + +static void __exit mmc_test_module_cleanup( void ) +{ +#ifdef CONFIG_DEVFS_FS + mmc_unregister( MMC_REG_TYPE_USER, &mmc_test_notifier ); +#else + mmc_unregister( MMC_REG_TYPE_USER, NULL ); + unregister_chrdev( MMC_TEST_MAJOR, "mmc_test" ); +#endif +} + +EXPORT_NO_SYMBOLS; + +module_init( mmc_test_module_init ); +module_exit( mmc_test_module_cleanup ); + +MODULE_LICENSE("GPL"); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/pm_test.c 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,29 @@ +/* Power Managment Test Module. RTSoft Co. 2002 */ + +/* The necessary header files */ + +/* Standard in kernel modules */ +#include /* We're doing kernel work */ +#include /* Specifically, a module */ +#define CONFIG_PM +#include + + +static int pmdata = -1; + +/* Initialize the module - register the proc file */ + +int init_module() +{ + pm_send_all(PM_SUSPEND,&pmdata); + return(0); +} + + +/* Cleanup - unregister our file from /proc */ +void cleanup_module() +{ + pm_send_all(PM_RESUME,NULL); +} + +MODULE_LICENSE( "GPL" ); --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/mmc/types.h 2004-03-31 17:15:11.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * linux/drivers/mmc/types.h + * + * Author: Vladimir Shebordaev + * Copyright: MontaVista Software Inc. + * + * $Id: types.h,v 0.5 2002/08/13 17:34:02 ted Exp ted $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MMC_TYPES_P_H__ +#define __MMC_TYPES_P_H__ + +#ifdef __KERNEL__ +#include + +typedef enum _mmc_reg_type mmc_reg_type_t; +typedef enum _mmc_response mmc_response_fmt_t; + +/* MMC card private description */ +typedef struct _mmc_card_rec mmc_card_rec_t; +typedef struct _mmc_card_rec *mmc_card_t; +typedef enum _mmc_dir mmc_dir_t; +typedef enum _mmc_buftype mmc_buftype_t; + +/* notifier declarations */ +typedef struct _mmc_notifier_rec mmc_notifier_rec_t; +typedef struct _mmc_notifier_rec *mmc_notifier_t; + +typedef int (*mmc_notifier_fn_t) ( mmc_card_t ); + +/* MMC card stack */ +typedef struct _mmc_card_stack_rec mmc_card_stack_rec_t; +typedef struct _mmc_card_stack_rec *mmc_card_stack_t; + +typedef struct _mmc_data_transfer_req_rec mmc_data_transfer_req_rec_t; +typedef struct _mmc_data_transfer_req_rec *mmc_data_transfer_req_t; + +/* MMC controller */ +typedef struct _mmc_controller_tmpl_rec mmc_controller_tmpl_rec_t; +typedef struct _mmc_controller_tmpl_rec *mmc_controller_tmpl_t; + +typedef enum _mmc_controller_state mmc_controller_state_t; +typedef struct _mmc_controller_rec mmc_controller_rec_t; +typedef struct _mmc_controller_rec *mmc_controller_t; + +/* various kernel types */ +typedef struct semaphore semaphore_t; +typedef struct rw_semaphore rwsemaphore_t; +typedef struct proc_dir_entry proc_dir_entry_rec_t; +typedef struct proc_dir_entry *proc_dir_entry_t; +typedef struct gendisk gendisk_rec_t; +typedef struct gendisk *gendisk_t; +#endif /* __KERNEL__ */ + +#endif /* __MMC_TYPES_P_H__ */ + --- linux-2.4.25/drivers/net/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/net/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -125,6 +125,7 @@ dep_tristate ' SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA dep_tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA dep_tristate ' SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA + tristate ' SMC 91C9x/91C1xx support' CONFIG_SMC91X fi bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then --- linux-2.4.25/drivers/net/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/net/Makefile 2004-03-31 17:15:11.000000000 +0200 @@ -137,6 +137,7 @@ obj-$(CONFIG_SK_G16) += sk_g16.o obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o +obj-$(CONFIG_SMC91X) += smc91x.o obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o --- linux-2.4.25/drivers/net/cirrus.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/net/cirrus.c 2004-03-31 17:15:11.000000000 +0200 @@ -67,6 +67,9 @@ #elif CONFIG_ARCH_CDB89712 # define CIRRUS_DEFAULT_IO ETHER_BASE + 0x300 # define CIRRUS_DEFAULT_IRQ IRQ_EINT3 +#elif CONFIG_ARCH_CSB226 +# define CIRRUS_DEFAULT_IO 0xF8000000 +# define CIRRUS_DEFAULT_IRQ IRQ_GPIO(14) #else # define CIRRUS_DEFAULT_IO 0 # define CIRRUS_DEFAULT_IRQ 0 --- linux-2.4.25/drivers/net/irda/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/net/irda/Config.in 2004-03-31 17:15:11.000000000 +0200 @@ -42,5 +42,7 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL fi - +if [ "$CONFIG_ARCH_PXA" = "y" ]; then + dep_tristate 'Intel PXA2xx Internal IR' CONFIG_PXA_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL +fi endmenu --- linux-2.4.25/drivers/net/irda/Makefile~2.4.25-vrs2-pxa1.patch 2004-02-18 14:36:31.000000000 +0100 +++ linux-2.4.25/drivers/net/irda/Makefile 2004-03-31 17:15:12.000000000 +0200 @@ -16,6 +16,7 @@ obj-$(CONFIG_USB_IRDA) += irda-usb.o obj-$(CONFIG_NSC_FIR) += nsc-ircc.o obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o +obj-$(CONFIG_PXA_FIR) += pxa_ir.o obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o obj-$(CONFIG_TOSHIBA_OLD) += toshoboe.o obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/net/irda/pxa_ir.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,1545 @@ +/* + * linux/drivers/net/irda/pxa_ir.c + * + * Author: + * Alexey Lugovskoy RTSoft. + * lugovskoy@rtsoft.msk.ru + * + * Dmitrij Frasenyak RTSoft. + * sed@mipt.sw.ru + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Infra-red SIR and FIR driver for the PXA 210/250 embedded microprocessors + * Based on linux/drivers/net/irda/sa1100_ir.c + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +static int rx_count = 0; +static int tx_count = 0; + +/* + * Our netdevice. There is only ever one of these. + */ + +static struct net_device *netdev; + +struct pxa250_irda { + + unsigned char open; + + int speed; + int newspeed; + + struct sk_buff *txskb; + struct sk_buff *rxskb; + + + /* => FIR */ + unsigned int fir_irq; + int txdma_ch; + int rxdma_ch; + dma_addr_t txbuf_dma; + dma_addr_t rxbuf_dma; + void* txbuf_dma_virt; + void* rxbuf_dma_virt; + /* <= FIR*/ + struct net_device_stats stats; + struct irlap_cb *irlap; + struct pm_dev *pmdev; + struct qos_info qos; + + /* => SIR */ + iobuff_t tx_buff; + iobuff_t rx_buff; + /* <= SIR */ +}; + +#define IS_FIR(si) ((si)->speed >= 4000000) + +#define HPSIR_MAX_RXLEN 2050 +#define HPSIR_MAX_TXLEN 2050 +#define TXBUFF_MAX_SIZE HPSIR_MAX_TXLEN +#define SET_SIR_MODE STISR = STISR_RCVEIR | STISR_XMITIR | STISR_XMODE + +/* + * If you want to disable debug information + * please uncomment line bellow + */ + +#define PXA_FIR_DUMP_ENABLE +#undef PXA_FIR_DUMP_ENABLE + + +#define PXA_FIR_DEBUG_ENABLE +#undef PXA_FIR_DEBUG_ENABLE + +#define PXA_FIR_IRQ_DEBUG_ENABLE +#undef PXA_FIR_IRQ_DEBUG_ENABLE + +#ifdef PXA_FIR_DEBUG_ENABLE +#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__); +#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__); +#define DBG(args...) printk(KERN_ERR __FUNCTION__"():"args); +#else +#define __ECHO_IN +#define __ECHO_OUT +#define DBG(args...) +#endif + +#ifdef PXA_FIR_IRQ_DEBUG_ENABLE +#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args); +#else +#define DBG_IRQ(args...) +#endif + + +static int pxa250_irda_set_speed(struct net_device *dev,int speed); +static void pxa250_start_rx_dma(struct net_device *dev); + + + +/************************************************************************** + * Misc FIR/SIR functions * + **************************************************************************/ +/* + * Allocate the receive buffer, unless it is already allocated. + */ + +static int pxa250_irda_rx_alloc(struct pxa250_irda *si) +{ + __ECHO_IN; + + if (si->rxskb) + return 0; + + si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC); + + if (!si->rxskb) { + printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n"); + return -ENOMEM; + } + + /* + * Align any IP headers that may be contained + * within the frame. + */ + skb_reserve(si->rxskb, 1); + + __ECHO_OUT; + + return 0; +} + + + +/************************************************************************** + * FIR * + **************************************************************************/ + + + + +static inline void pxa250_dma_stop(int ch) +{ + __ECHO_IN; + + DCSR(ch) &= ~DCSR_RUN; + + __ECHO_OUT; + +} + + +static void pxa250_ficp_rx_start(void) +{ + ICCR0 = 0; + ICCR2 = 1 << 2 | 0 << 3 ; + ICCR0 = ICCR0_ITR ; + ICCR0 |= ICCR0_RIE | ICCR0_RXE ; +} + +/* + * Change Alternative Function encoding + * Enable ICP unit + * Disabe STUART unit + * Enable IRQ unit clock; + * Configure direction of GPIO used by ICP + */ + + +static void pxa250_do_fir_GPIO_config(void) +{ + /* + * Modify GPIO 46 and 47 Alternate Function + */ + + __ECHO_IN; + + /*Switch AF*/ + set_GPIO_mode (GPIO46_ICPRXD_MD); + set_GPIO_mode (GPIO47_ICPTXD_MD); + + if (machine_is_lubbock()) + LUB_MISC_WR |= 1 << 4; + + /*init clock*/ + CKEN |= CKEN13_FICP; + + __ECHO_OUT; +} + +/* + * Low level hardware configuration and startup. + */ + +static int pxa250_fir_irda_startup(struct pxa250_irda *si) +{ + + __ECHO_IN; + + /* + * Disable STUART + */ + + STIER &= ~IER_UUE; + + /*Disable STUART FIFO */ + STFCR = 0; + + /* + * Do low level configuration for HW AF and clock + */ + pxa250_do_fir_GPIO_config(); + + __ECHO_OUT; + return 0; +} + + +/* + * Aieeeeee .. we should never get here :( + */ +static void pxa250_irda_rxdma_irq(int ch,void *id, struct pt_regs *regs) +{ + struct net_device *dev=id; + struct pxa250_irda *si=dev->priv; + u_int dcsr; + + + __ECHO_IN; + + /* + * Make sure that irq is our. + */ + + if ( ch != si->rxdma_ch ) + /*just*/ return; + + /* + * Check status + */ + dcsr = DCSR(ch); + + DBG("DCSR=%x\n",dcsr); + + if (dcsr & DCSR_STOPSTATE ) + { + DBG_IRQ("Chanel %d in stop state\n",ch); + } + + if (dcsr & DCSR_BUSERR ) + { + /* + * BUS Error we must restart reception + */ + + DBG("PXA IrDA: bus error interrupt on channel %d\n", ch); + DCSR(ch) |= DCSR_BUSERR; + } + + if (dcsr & DCSR_ENDINTR ) + { + DBG("PXA IrDA: Normal end of dma channel %d - packet to big\n", ch); + DCSR(ch) |= DCSR_ENDINTR; + } + + /* no mater what restart rx*/ + pxa250_start_rx_dma(dev); + + return ; + +} + + +static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs) +{ + struct net_device *dev=id; + struct pxa250_irda *si=dev->priv; + struct sk_buff *skb = si->txskb; + u_int dcsr; + + + __ECHO_IN; + DBG_IRQ("transmit\n"); + + + /* + * Make sure that irq is our. + */ + + if ( ch != si->txdma_ch ) + /*just*/ return; + + + /* + * Check status + */ + dcsr = DCSR(ch); + + DBG("DCSR=%x",dcsr); + + if (dcsr & DCSR_STOPSTATE ) + { + DBG("Chanel %d in stop state\n",ch); + } + + if (dcsr & DCSR_BUSERR ) + { + DBG("PXA IrDA: bus error interrupt on channel %d\n", ch); + DCSR(ch) |= DCSR_BUSERR; + si->txskb = NULL; + } + + if (dcsr & DCSR_ENDINTR ) + { + DBG("PXA IrDA: Normal end of dma channel %d\n", ch); + DCSR(ch) |= DCSR_ENDINTR; + si->txskb = NULL; + } + + /* + * Account and free the packet. + */ + if (skb) + { + si->stats.tx_packets ++; + si->stats.tx_bytes += skb->len; + dev_kfree_skb_irq(skb); + } + + /*Disable transceiver and enable receiver*/ + + if (si->newspeed) { + pxa250_irda_set_speed(dev, si->newspeed); + si->newspeed = 0; + } + + while (ICSR1 & ICSR1_TBY) + udelay(1); + + ICCR0 &= ~ICCR0_TXE; + + + enable_irq(si->fir_irq); + + ICCR0 |= ICCR0_RXE; + + /* + * Make sure that the TX queue is available for sending + * (for retries). TX has priority over RX at all times. + */ + netif_wake_queue(dev); + + __ECHO_OUT; +} + + +static void pxa250_start_rx_dma(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + int ch=si->rxdma_ch; + + if (!si->rxskb) { + DBG("rx buffer went missing\n"); +/* return; */ + } + + DCSR(ch)=0; + DCSR(ch)=DCSR_NODESC; + DSADR(ch) = __PREG(ICDR); + DTADR(ch) = si->rxbuf_dma; /* phisical address */; + + /* We should never do END_IRQ. !!!*/ + DCMD(ch) = DCMD_ENDIRQEN| DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | HPSIR_MAX_RXLEN; + + /* + * All right information will be available as soon as we set RXE flag + */ + + DCSR(ch) = DCSR_ENDINTR | DCSR_BUSERR; + DCSR(ch) = DCSR_RUN | DCSR_NODESC ; + +} + + + + +static int pxa250_get_rx_len(struct pxa250_irda *si) +{ + /* + * DMA have to be stoped here + */ + + if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) ) + printk("warning dma have to be stoped befor counting len\n"); + + return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) ); + +} + +static void pxa250_irda_fir_error(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + struct sk_buff *skb = si->rxskb; + int len; + int stat,data; + + __ECHO_IN; + + if (!skb) + { + printk("pxa250 fir_error: SKB is NULL!\n"); + return; + } + + /* + * Get the current data position. + */ + + len=pxa250_get_rx_len(si); + DBG("RXLEN=%d\n",len); + memcpy(skb->data, si->rxbuf_dma_virt, len); + + do { + /* + * Read Status, and then Data. + */ + stat = ICSR1; + rmb(); + data = ICDR; + if (stat & (ICSR1_CRE | ICSR1_ROR)) { + si->stats.rx_errors++; + if (stat & ICSR1_CRE) + si->stats.rx_crc_errors++; + if (stat & ICSR1_ROR) + si->stats.rx_frame_errors++; + } else + skb->data[len++] = data; + + /* + * If we hit the end of frame, there's + * no point in continuing. + */ + if (stat & ICSR1_EOF) + break; + } while (ICSR0 & ICSR0_EIF); + + if (stat & ICSR1_EOF) { + si->rxskb = NULL; + + skb_put(skb, len); + skb->dev = dev; + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + si->stats.rx_packets++; + si->stats.rx_bytes += len; + + /* + * Before we pass the buffer up, allocate a new one. + */ + + si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC); + + if (!si->rxskb) { + printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n"); + return; + } + + /* + * Align any IP headers that may be contained + * within the frame. + */ + skb_reserve(si->rxskb, 1); + + netif_rx(skb); + } +} + +/* + * FIR format interrupt service routine. We only have to + * handle RX events; transmit events go via the TX DMA irq handler. + * + * No matter what, we disable RX, process, and then restart RX. + */ + +static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct pxa250_irda *si = dev->priv; + int status; + + /* + * Stop RX + */ + + __ECHO_IN; + + pxa250_dma_stop(si->rxdma_ch); + + + /* + * Framing error - we throw away the packet completely. + * Clearing RXE flushes the error conditions and data + * from the fifo. + */ + status=ICSR0; + + if (status & (ICSR0_FRE | ICSR0_RAB)) { + DBG_IRQ("Framing error or RAB\n"); + + si->stats.rx_errors++; + + if (ICSR0 & ICSR0_FRE) + si->stats.rx_frame_errors++; + + /* Clear RX fifo + * DMA will be cleared when we restart RX + * Should we check RNE after that? + */ + + ICCR0 &= ~ICCR0_RXE; + + /* + * Clear selected status bits now, so we + * don't miss them next time around. + */ + ICSR0 = status & (ICSR0_FRE | ICSR0_RAB); + } + + + /* + * Deal with any receive errors. The any of the lowest + * 8 bytes in the FIFO may contain an error. We must read + * them one by one. The "error" could even be the end of + * packet! + */ + if (ICSR0 & ICSR0_EIF) + pxa250_irda_fir_error(dev); + + /* + * No matter what happens, we must restart reception. + */ + + ICCR0 = 0; + pxa250_start_rx_dma(dev); + pxa250_ficp_rx_start(); + __ECHO_OUT; +} + + + + + +/************************************************************************** + * SIR * + **************************************************************************/ +/* + * HP-SIR format interrupt service routines. + */ +static void pxa250_sir_transmit(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + + if (si->tx_buff.len) + { + /* Disable receiver and enable transmiter*/ + + + + STISR &= ~STISR_RCVEIR; +// STISR |= STISR_XMITIR; + + + + disable_irq(dev->irq); + + do + { + + if (STLSR & LSR_TDRQ) + { + STTHR = *si->tx_buff.data++; + si->tx_buff.len -= 1; + + tx_count++; + } + + + } while (si->tx_buff.len); + + + if (si->tx_buff.len == 0) + { + + + si->stats.tx_packets++; + si->stats.tx_bytes += si->tx_buff.data - + si->tx_buff.head; + + /* + * We need to ensure that the transmitter has + * finished. + */ + + do + { + udelay(1); + + } + while ( ! (STLSR & LSR_TEMT) ); + + + /* + + * Ok, we've finished transmitting. Now enable + * the receiver. Sometimes we get a receive IRQ + * immediately after a transmit... + */ + + if (si->newspeed) + { + pxa250_irda_set_speed(dev, si->newspeed); + si->newspeed = 0; + } + + /* I'm hungry! */ + netif_wake_queue(dev); + } + + enable_irq (dev->irq); + STIER = (IER_RAVIE | IER_UUE | IER_RTIOE); + + STISR |= STISR_RCVEIR; +// STISR &= ~STISR_XMITIR; + } +} + +static void pxa250_irda_hpsir_irq(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + + /* + * Deal with any receive errors first. The bytes in error may be + * the only bytes in the receive FIFO, so we do this first. + */ + __ECHO_IN; + + while (STLSR & LSR_FIFOE) + { + int stat, data; + + stat = STLSR; + data = STRBR; + + + if (stat & (LSR_FE | LSR_OE | LSR_PE)) + + { + si->stats.rx_errors++; + if (stat & LSR_FE) + si->stats.rx_frame_errors++; + if (stat & LSR_OE) + si->stats.rx_fifo_errors++; + + } else + { + rx_count++; + async_unwrap_char(dev, &si->stats, &si->rx_buff, data); + } + + } + + /* + * We must clear certain bits. + */ + + if (STLSR & (LSR_DR)) + { + /* + * Fifo contains at least 1 character. + */ + do + { + int data; + + data = STRBR; + + async_unwrap_char(dev, &si->stats, &si->rx_buff, + data); /* was Ser2UTDR); Clo */ + rx_count++; + + } while (STLSR & LSR_DR); + + dev->last_rx = jiffies; + } + + __ECHO_OUT; +} + +static void pxa250_sir_irda_shutdown(struct pxa250_irda *si) +{ + + STIER = 0; + STFCR = 0; + STISR = 0; + CKEN &= ~CKEN5_STUART; +} + + +/************************************************************************************/ + +/*Low level init/uninstall function PM control and IrDA protocol stack registration */ + +/* + * Set the IrDA communications speed. + * Interrupt have to be disabled here. + */ + +static int pxa250_irda_startup(struct net_device *dev) +{ + + + __ECHO_IN; + + /* + * Ensure that the ports for this device are setup correctly. + */ + + + set_GPIO_mode (GPIO46_STRXD_MD); + set_GPIO_mode (GPIO47_STTXD_MD); + + STMCR = MCR_OUT2; + STLCR = LCR_WLS1 | LCR_WLS0; + + SET_SIR_MODE; + CKEN |= CKEN5_STUART; + /* enable irq from stuart */ + ICMR |= ( 1 << 20 ); + + /*reset FIFO*/ + +/* STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF;// | FCR_ITL_16; + + STIER = IER_UUE | IER_RAVIE | IER_RTOIE; +*/ + __ECHO_OUT; + + return 0; + +} + + +#ifdef CONFIG_PM +/* + * Suspend the IrDA interface. + */ + +static int pxa250_irda_shutdown(struct pxa250_irda *si) +{ + + pxa250_sir_irda_shutdown(si); + return 0; + +} + + +static int pxa250_irda_suspend(struct net_device *dev, int state) +{ + struct pxa250_irda *si = dev->priv; + + if (si && si->open) { + /* + * Stop the transmit queue + */ + if (IS_FIR(si)) + return -1; + + netif_stop_queue(dev); + disable_irq(dev->irq); + disable_irq(si->fir_irq); + pxa250_sir_irda_shutdown(si); + } + + return 0; +} + +/* + * Resume the IrDA interface. + */ + +static int pxa250_irda_resume(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + + __ECHO_IN; + + if (si && si->open) { + /* + * If we missed a speed change, initialise at the new speed + * directly. It is debatable whether this is actually + * required, but in the interests of continuing from where + * we left off it is desireable. The converse argument is + * that we should re-negotiate at 9600 baud again. + */ + if (si->newspeed) { + si->speed = si->newspeed; + si->newspeed = 0; + } + + pxa250_irda_startup(dev); + enable_irq(dev->irq); + + /* + * This automatically wakes up the queue + */ + netif_wake_queue(dev); + pxa250_irda_set_speed(dev,si->speed = 9600); + + } + + __ECHO_OUT; + return 0; +} + +static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + int ret; + + + if (!dev->data) + return -EINVAL; + + + switch (rqst) { + case PM_SUSPEND: + ret = pxa250_irda_suspend((struct net_device *)dev->data, + (int)data); + break; + + case PM_RESUME: + ret = pxa250_irda_resume((struct net_device *)dev->data); + break; + + default: + + ret = -EINVAL; + break; + } + + return ret; +} +#endif + + + + +static void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + + pxa250_irda_hpsir_irq(dev); + +} + + +static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + int speed = irda_get_next_speed(skb); + int mtt; + + __ECHO_IN; + + /* + * Does this packet contain a request to change the interface + * speed? If so, remember it until we complete the transmission + * of this frame. + */ + if (speed != si->speed && speed != -1) + si->newspeed = speed; + + /* + * If this is an empty frame, we can bypass a lot. + */ + if (skb->len == 0) { + if (si->newspeed) { + si->newspeed = 0; + pxa250_irda_set_speed(dev, speed); + } + dev_kfree_skb(skb); + return 0; + } + + + DBG("stop queue\n"); + netif_stop_queue(dev); + + if(!IS_FIR(si)) + { + + si->tx_buff.data = si->tx_buff.head; + si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, + si->tx_buff.truesize); + + + pxa250_sir_transmit(dev); + + + + dev_kfree_skb(skb); + + dev->trans_start = jiffies; + + return 0; + } + else /* FIR */ + { + DBG("Enter FIR transmit\n"); + /* + * We must not be transmitting... + */ + if (si->txskb) + BUG(); + + disable_irq(si->fir_irq); + + netif_stop_queue(dev); + DBG("queue stoped\n"); + si->txskb = skb; + + /* we could not just map so we'll need some triks */ + /* skb->data may be not DMA capable -Sed- */ + + + if (skb->len > TXBUFF_MAX_SIZE) + { + printk (KERN_ERR "skb data too large\n"); + printk (KERN_ERR "len=%d",skb->len); + BUG(); + } + + + DBG("gonna copy %d bytes to txbuf\n",skb->len); + + memcpy (si->txbuf_dma_virt, skb->data , skb->len); + + /* Actual sending ;must not be receiving !!! */ + /* Write data and source address */ + + DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 ); + + /*Disable receiver and enable transifer */ + ICCR0 &= ~ICCR0_RXE; + + if (ICSR1 & ICSR1_TBY) + BUG(); + + ICCR0 |= ICCR0_TXE; + + DBG("FICP status %x\n",ICSR0); + + if (0){ + int i; + + DBG("sending packet\n"); + for (i=0;ilen;i++) + (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ; + DBG(" done\n"); + + } + /* + * If we have a mean turn-around time, impose the specified + * specified delay. We could shorten this by timing from + * the point we received the packet. + */ + + mtt = irda_get_mtt(skb); + if(mtt) + udelay(mtt); + + DCSR(si->txdma_ch)=0; + DCSR(si->txdma_ch)=DCSR_NODESC; + DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */ + DTADR(si->txdma_ch) = __PREG(ICDR); + + DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len; + + DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR; + DCSR(si->txdma_ch) = DCSR_RUN | DCSR_NODESC ; + + DBG("FICP status %x\n",ICSR0); + + return 0; + } + +} + +static int +pxa250_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) +{ + struct if_irda_req *rq = (struct if_irda_req *)ifreq; + struct pxa250_irda *si = dev->priv; + int ret = -EOPNOTSUPP; + + __ECHO_IN; + + switch (cmd) { + case SIOCSBANDWIDTH: + if (capable(CAP_NET_ADMIN)) { + /* + * We are unable to set the speed if the + * device is not running. + */ + if (si->open) { + ret = pxa250_irda_set_speed(dev, + rq->ifr_baudrate); + } else { + printk("pxa250_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n"); + ret = 0; + } + } + break; + + case SIOCSMEDIABUSY: + ret = -EPERM; + if (capable(CAP_NET_ADMIN)) { + irda_device_set_media_busy(dev, TRUE); + ret = 0; + } + break; + + case SIOCGRECEIVING: + rq->ifr_receiving = IS_FIR(si) ? 0 + : si->rx_buff.state != OUTSIDE_FRAME; + break; + + default: + break; + } + + __ECHO_OUT; + + return ret; +} + +static struct net_device_stats *pxa250_irda_stats(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + return &si->stats; +} + +static int pxa250_irda_start(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + int err; + unsigned int flags; + + + MOD_INC_USE_COUNT; + + __ECHO_IN; + si->speed = 9600; + + local_irq_save(flags); + + err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0, dev->name, dev); + if (err) + goto err_fir_irq; + + err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev); + if (err) + goto err_irq; + + /* + * The interrupt must remain disabled for now. + */ + + disable_irq(dev->irq); + disable_irq(si->fir_irq); + + local_irq_restore(flags); + + + /* Allocate DMA channel for receiver (not used) */ + err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev); + if (err < 0 ) + goto err_rx_dma; + si->rxdma_ch=err; + + DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch; + + + /* Allocate DMA channel for transmit */ + err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev); + if (err < 0 ) + goto err_tx_dma; + + si->txdma_ch=err; + + /* + * Make sure that ICP will be able + * to assert the transmit dma request bit + * through the peripherals request bus (PREQ) + */ + + DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch; + + DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch); + + /* allocate consistent buffers for dma access + * buffers have to be aligned and situated in dma capable memory region; + */ + si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma); + if (! si->rxbuf_dma_virt ) + goto err_rxbuf_dma; + + si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN, &si->txbuf_dma); + if (! si->txbuf_dma_virt ) + goto err_txbuf_dma; + + /* Alocate skb for receiver */ + err=pxa250_irda_rx_alloc(si); + if (err) + goto err_rx_alloc; + + /* + * Setup the serial port for the specified config. + */ + err = pxa250_irda_startup(dev); + if (err) + goto err_startup; + + pxa250_irda_set_speed(dev,si->speed = 9600); + + + /* + * Open a new IrLAP layer instance. + */ + si->irlap = irlap_open(dev, &si->qos, "pxa250"); + err = -ENOMEM; + if (!si->irlap) + goto err_irlap; + + /* + * Now enable the interrupt and start the queue + */ + si->open = 1; + enable_irq(dev->irq); + netif_start_queue(dev); + return 0; + +err_irlap: + si->open = 0; + pxa250_sir_irda_shutdown(si); +err_startup: + dev_kfree_skb(si->rxskb); +err_rx_alloc: + consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma); +err_txbuf_dma: + consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma); +err_rxbuf_dma: + pxa_free_dma(si->txdma_ch); +err_tx_dma: + pxa_free_dma(si->rxdma_ch); +err_rx_dma: + free_irq(dev->irq, dev); +err_irq: + free_irq(si->fir_irq, dev); +err_fir_irq: + MOD_DEC_USE_COUNT; + return err; +} + +static int pxa250_irda_stop(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + + printk(KERN_ERR "Irda stop... RX = %d TX = %d\n",rx_count,tx_count); + + disable_irq(dev->irq); + disable_irq(si->fir_irq); +/* pxa250_irda_shutdown(si); */ + + /* + * If we have been doing DMA receive, make sure we + * tidy that up cleanly. + */ + if (si->rxskb) { + dev_kfree_skb(si->rxskb); + si->rxskb = NULL; + } + + /* Stop IrLAP */ + if (si->irlap) { + irlap_close(si->irlap); + si->irlap = NULL; + } + + consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma); + consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma); + pxa_free_dma(si->txdma_ch); + pxa_free_dma(si->rxdma_ch); + + netif_stop_queue(dev); + si->open = 0; + + /* + * Free resources + */ + free_irq(dev->irq, dev); + free_irq(si->fir_irq, dev); + + + MOD_DEC_USE_COUNT; + + return 0; +} + +static int pxa250_irda_init_iobuf(iobuff_t *io, int size) +{ + io->head = kmalloc(size, GFP_KERNEL | GFP_DMA); + if (io->head != NULL) { + io->truesize = size; + io->in_frame = FALSE; + io->state = OUTSIDE_FRAME; + io->data = io->head; + } + return io->head ? 0 : -ENOMEM; +} + + + + +static int pxa250_stop_fir(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + unsigned int flag; + + save_flags(flag); + cli(); + + pxa250_dma_stop(si->txdma_ch); + pxa250_dma_stop(si->rxdma_ch); + + if (si->txskb) + dev_kfree_skb_irq(si->txskb); + + ICCR0 &= ~(ICCR0_RXE | ICCR0_TXE ); + disable_irq(si->fir_irq); + CKEN &= ~CKEN13_FICP; + + restore_flags(flag); + + return 0; +} + + + +static int pxa250_irda_set_speed(struct net_device *dev, int speed) +{ + struct pxa250_irda *si = dev->priv; + int brd, ret = -EINVAL; + static int last_fir_speed=0; + + __ECHO_IN; + + + + switch (speed) { + case 9600: case 19200: case 38400: + case 57600: case 115200: + + /* Baud rate fixed - Clo */ + + /* + * FIXME + */ + if (last_fir_speed) + { + + pxa250_stop_fir(dev); + set_GPIO_mode (GPIO46_STRXD_MD); + set_GPIO_mode (GPIO47_STTXD_MD); + + enable_irq(dev->irq); + netif_wake_queue(dev); + last_fir_speed=0; + } + + + LUB_MISC_WR &= ~(1 << 4); + + brd = 14745600 / (16 * speed); + + STLCR |= LCR_DLAB; + + STDLH = brd >> 8; /* Clo: set Divisor Latch High */ + STDLL = brd & 0xFF; /* Clo: set Devisor Latch Low */ + + STLCR &= ~LCR_DLAB; /* Clo: clear DLAB bit */ + + STMCR = MCR_OUT2; + + CKEN |= CKEN5_STUART; + + ICMR |= ( 1 << 20 ); + + STLCR = LCR_WLS1 | LCR_WLS0; + + SET_SIR_MODE; + + STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF | FCR_ITL_1 ;// | FCR_ITL_16; + + STIER = IER_UUE | IER_RAVIE | IER_RTIOE; + + si->speed = speed; + + ret = 0; + break; + + case 4000000: + + if (last_fir_speed) + goto speed_out; + + disable_irq(dev->irq); + + pxa250_sir_irda_shutdown(si); + pxa250_fir_irda_startup(si); + pxa250_irda_rx_alloc(si); + ICCR0=0; + pxa250_start_rx_dma(dev); + pxa250_ficp_rx_start(); + + enable_irq(si->fir_irq); + DBG("enable FIR \n"); + si->speed = speed; + + netif_wake_queue(dev); + last_fir_speed=1; +speed_out: + + ret=0; + + break; + + default: + break; + } + __ECHO_OUT; + + return ret; +} + + +static int pxa250_irda_net_init(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + unsigned int baudrate_mask; + int err = -ENOMEM; + + si = kmalloc(sizeof(struct pxa250_irda), GFP_KERNEL); + if (!si) + goto out; + + memset(si, 0, sizeof(*si)); + + /* + * Initialise the HP-SIR buffers + */ + + err = pxa250_irda_init_iobuf(&si->rx_buff, 14384); + if (err) + goto out; + err = pxa250_irda_init_iobuf(&si->tx_buff, 4000); + if (err) + goto out_free_rx; + + si->fir_irq = IRQ_ICP; + dev->priv = si; + dev->hard_start_xmit = pxa250_irda_hard_xmit; + dev->open = pxa250_irda_start; + dev->stop = pxa250_irda_stop; + dev->do_ioctl = pxa250_irda_ioctl; + dev->get_stats = pxa250_irda_stats; + + irda_device_setup(dev); + irda_init_max_qos_capabilies(&si->qos); + + /* + * We support original IRDA up to 115k2. (we don't currently + * support 4Mbps). Min Turn Time set to 1ms or greater. + */ + baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + baudrate_mask |= IR_4000000 << 8; + si->qos.baud_rate.bits &= baudrate_mask; + si->qos.min_turn_time.bits = 7; + + irda_qos_bits_to_value(&si->qos); + +#ifdef CONFIG_PM + /* + * Power-Management is optional. + */ + si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, pxa250_irda_pmproc); + if (si->pmdev) + si->pmdev->data = dev; +#endif + + return 0; + + kfree(si->tx_buff.head); +out_free_rx: + kfree(si->rx_buff.head); +out: + kfree(si); + + return err; +} + +/* + * Remove all traces of this driver module from the kernel, so we can't be + * called. Note that the device has already been stopped, so we don't have + * to worry about interrupts or dma. + */ +static void pxa250_irda_net_uninit(struct net_device *dev) +{ + struct pxa250_irda *si = dev->priv; + + dev->hard_start_xmit = NULL; + dev->open = NULL; + dev->stop = NULL; + dev->do_ioctl = NULL; + dev->get_stats = NULL; + dev->priv = NULL; + + pm_unregister(si->pmdev); + + kfree(si->tx_buff.head); + kfree(si->rx_buff.head); + kfree(si); +} + +static int __init pxa250_irda_init(void) +{ + struct net_device *dev; + int err; + + /* STUART */ + err = request_mem_region(__PREG(STRBR), 0x24, "IrDA") ? 0 : -EBUSY; + if (err) + goto err_mem_1; + + /* FIR */ + err = request_mem_region(__PREG(ICCR0), 0x1c, "IrDA") ? 0 : -EBUSY; + if (err) + goto err_mem_2; + + + rtnl_lock(); + dev = dev_alloc("irda%d", &err); + if (dev) { + dev->irq = IRQ_STUART; + dev->init = pxa250_irda_net_init; + dev->uninit = pxa250_irda_net_uninit; + + err = register_netdevice(dev); + + if (err) + kfree(dev); + else + netdev = dev; + } + rtnl_unlock(); + + if (err) { + release_mem_region(__PREG(ICCR0), 0x1c); +err_mem_2: + release_mem_region(__PREG(STRBR), 0x24); + } +err_mem_1: + return err; +} + +static void __exit pxa250_irda_exit(void) +{ + struct net_device *dev = netdev; + + netdev = NULL; + if (dev) { + rtnl_lock(); + unregister_netdevice(dev); + rtnl_unlock(); + } + + release_mem_region(__PREG(ICCR0), 0x1c); + + release_mem_region(__PREG(STRBR), 0x24); + + /* + * We now know that the netdevice is no longer in use, and all + * references to our driver have been removed. The only structure + * which may still be present is the netdevice, which will get + * cleaned up by net/core/dev.c + */ +} + +module_init(pxa250_irda_init); +module_exit(pxa250_irda_exit); + +MODULE_AUTHOR("Alexey Lugovskoy Frasenyak Dmitrij"); +MODULE_DESCRIPTION("PXA250 SIR/FIR"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/net/smc91x.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,2123 @@ +/*------------------------------------------------------------------------ + . smc91x.c + . This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices. + . + . Copyright (C) 1996 by Erik Stahlman + . Copyright (C) 2001 Standard Microsystems Corporation + . Developed by Simple Network Magic Corporation + . Copyright (C) 2003 Monta Vista Software, Inc. + . Unified SMC91x driver by Nicolas Pitre + . + . 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 + . + . Arguments: + . io = for the base address + . irq = for the IRQ + . nowait = 0 for normal wait states, 1 eliminates additional wait states + . + . original author: + . Erik Stahlman + . + . hardware multicast code: + . Peter Cammaert + . + . contributors: + . Daris A Nevil + . Nicolas Pitre + . + . History: + . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet + . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ" + . 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111 + . 08/22/01 Scott Anderson merge changes from smc9194 to smc91111 + . 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111 + . 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support + . 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races, + . more bus abstraction, big cleanup, etc. + ----------------------------------------------------------------------------*/ + +static const char version[] = + "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre \n"; + +/* Debugging level */ +#ifndef SMC_DEBUG +#define SMC_DEBUG 0 +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_PM +#include +#endif + +#include +#include +#include + +#include "smc91x.h" + + +#ifdef CONFIG_ISA +/* + . the LAN91C111 can be at any of the following port addresses. To change, + . for a slightly different card, you can add it to the array. Keep in + . mind that the array must end in zero. +*/ +static unsigned int smc_portlist[] __initdata = { + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, + 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 +}; +#endif /* CONFIG_ISA */ + +#ifndef SMC_IOADDR +# define SMC_IOADDR -1 +#endif +static int io = SMC_IOADDR; + +#ifndef SMC_IRQ +# define SMC_IRQ -1 +#endif +static int irq = SMC_IRQ; + +#ifndef SMC_NOWAIT +# define SMC_NOWAIT 0 +#endif +static int nowait = SMC_NOWAIT; + +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(nowait, "i"); +MODULE_PARM_DESC(io, "I/O base address"); +MODULE_PARM_DESC(irq, "IRQ number"); +MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); + + +/*------------------------------------------------------------------------ + . + . The internal workings of the driver. If you are changing anything + . here with the SMC stuff, you should have the datasheet and know + . what you are doing. + . + -------------------------------------------------------------------------*/ +#define CARDNAME "LAN91x" + +// Use power-down feature of the chip +#define POWER_DOWN 1 + +/* + . Wait time for memory to be free. This probably shouldn't be + . tuned that much, as waiting for this means nothing else happens + . in the system +*/ +#define MEMORY_WAIT_TIME 16 + +/* + . This selects whether TX packets are sent one by one to the SMC91x internal + . memory ans throttled until transmission completes. This may prevent + . RX overruns a litle by keeping much of the memory free for RX packets + . but to the expense of reduced TX throughput and increased IRQ overhead. + . Note this is not a cure for a too slow data bus or too high IRQ latency. + */ +#define THROTTLE_TX_PKTS 0 + + +/* store this information for the driver.. */ +struct smc_local { + + // If I have to wait until memory is available to send + // a packet, I will store the skbuff here, until I get the + // desired memory. Then, I'll send it out and free it. + struct sk_buff *saved_skb; + + // these are things that the kernel wants me to keep, so users + // can find out semi-useless statistics of how well the card is + // performing + struct net_device_stats stats; + + // version/revision of the SMC91x chip + int version; + + // Set to true during the auto-negotiation sequence + int autoneg_active; + + // Address of our PHY port + int phyaddr; + + // Type of PHY + int phytype; + + // Last contents of PHY Register 18 + int lastPhy18; + + // Contains the current active transmission mode + int tcr_cur_mode; + + // Contains the current active receive mode + int rcr_cur_mode; + + // Contains the current active receive/phy mode + int rpc_cur_mode; + int ctl_autoneg; + int ctl_rfduplx; + int ctl_rspeed; + +#ifdef CONFIG_PM + struct pm_dev* pm; +#endif + +}; + + +#if SMC_DEBUG > 2 +#define PRINTK3(args...) printk(args) +#else +#define PRINTK3(args...) do { } while(0) +#endif + +#if SMC_DEBUG > 1 +#define PRINTK2(args...) printk(args) +#else +#define PRINTK2(args...) do { } while(0) +#endif + +#if SMC_DEBUG > 0 +#define PRINTK1(args...) printk(args) +#define PRINTK(args...) printk(args) +#else +#define PRINTK1(args...) do { } while(0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +#if SMC_DEBUG > 3 +static void PRINT_PKT(u_char *buf, int length) +{ + int i; + int remainder; + int lines; + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines ; i ++) { + int cur; + for (cur = 0; cur < 8; cur++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); + } + for (i = 0; i < remainder/2 ; i++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b ); + } + printk("\n"); +} +#else +#define PRINT_PKT(x...) do { } while(0) +#endif + + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + local_irq_save(flags); \ + mask = SMC_GET_INT_MASK(); \ + mask |= (x); \ + SMC_SET_INT_MASK(mask); \ + local_irq_restore(flags); \ +} while (0) + +/* this disables an interrupt from the interrupt mask register */ +#define SMC_DISABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + local_irq_save(flags); \ + mask = SMC_GET_INT_MASK(); \ + mask &= ~(x); \ + SMC_SET_INT_MASK(mask); \ + local_irq_restore(flags); \ +} while (0) + +/* wait while MMU is busy */ +#define SMC_WAIT_MMU_BUSY() do { \ + if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \ + unsigned long timeout = jiffies + 2; \ + while (SMC_GET_MMU_CMD() & MC_BUSY) { \ + if (time_after(jiffies, timeout)) { \ + printk("%s: timeout %s line %d\n", \ + dev->name, __FILE__, __LINE__); \ + break; \ + } \ + } \ + } \ +} while (0) + + +/* this does a soft reset on the device */ +static void +smc_reset(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int phyaddr = lp->phyaddr; + int status; + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + /* This resets the registers mostly to defaults, but doesn't + affect EEPROM. That seems unnecessary */ + SMC_SELECT_BANK( 0 ); + SMC_SET_RCR( RCR_SOFTRST ); + + /* Setup the Configuration Register */ + /* This is necessary because the CONFIG_REG is not affected */ + /* by a soft reset */ + SMC_SELECT_BANK( 1 ); + SMC_SET_CONFIG( CONFIG_DEFAULT ); + + /* Setup for fast accesses if requested */ + /* If the card/system can't handle it then there will */ + /* be no recovery except for a hard reset or power cycle */ + if (nowait) + SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT ); + +#ifdef POWER_DOWN + /* Release from possible power-down state */ + /* Configuration register is not affected by Soft Reset */ + SMC_SELECT_BANK( 1 ); + SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN ); + status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); + status &= ~PHY_CNTL_PDN; + smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); +#endif + + /* this should pause enough for the chip to be happy */ + udelay(1); + + /* Disable transmit and receive functionality */ + SMC_SELECT_BANK( 0 ); + SMC_SET_RCR( RCR_CLEAR ); + SMC_SET_TCR( TCR_CLEAR ); + + /* set the control register to automatically + release successfully transmitted packets, to make the best + use out of our limited memory */ + SMC_SELECT_BANK( 1 ); +#if ! THROTTLE_TX_PKTS + SMC_SET_CTL( SMC_GET_CTL() | CTL_AUTO_RELEASE ); +#else + SMC_SET_CTL( SMC_GET_CTL() & ~CTL_AUTO_RELEASE ); +#endif + + /* Disable all interrupts */ + SMC_SELECT_BANK( 2 ); + SMC_SET_INT_MASK( 0 ); + + /* Reset the MMU */ + SMC_SET_MMU_CMD( MC_RESET ); + SMC_WAIT_MMU_BUSY(); +} + +/* Enable Interrupts, Receive, and Transmit */ +static void +smc_enable(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int mask; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + /* see the header file for options in TCR/RCR DEFAULT*/ + SMC_SELECT_BANK( 0 ); + SMC_SET_TCR( lp->tcr_cur_mode ); + SMC_SET_RCR( lp->rcr_cur_mode ); + + /* now, enable interrupts */ + mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT; + if (lp->version >= 0x70) + mask |= IM_MDINT; + SMC_SELECT_BANK( 2 ); + SMC_SET_INT_MASK( mask ); +} + +/* this puts the device in an inactive state */ +static void +smc_shutdown(struct net_device *dev) +{ + int ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int phyaddr = lp->phyaddr; + int status; + + PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__); + + /* no more interrupts for me */ + SMC_SELECT_BANK( 2 ); + SMC_SET_INT_MASK( 0 ); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK( 0 ); + SMC_SET_RCR( RCR_CLEAR ); + SMC_SET_TCR( TCR_CLEAR ); + +#ifdef POWER_DOWN + status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); + status |= PHY_CNTL_PDN; + smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG); + + /* finally, shut the chip down */ + SMC_SELECT_BANK( 1 ); + SMC_SET_CONFIG( SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN ); +#endif +} + +/* This is the procedure to handle the receipt of a packet. */ +static inline void +smc_rcv(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned int packet_number, status, packet_len; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + packet_number = SMC_GET_RXFIFO(); + if (unlikely(packet_number & RXFIFO_REMPTY)) { + PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name); + return; + } + + /* read from start of packet */ + SMC_SET_PTR( PTR_READ | PTR_RCV | PTR_AUTOINC ); + + /* First two words are status and packet length */ + SMC_GET_PKT_HDR(status, packet_len); + packet_len &= 0x07ff; /* mask off top bits */ + PRINTK2("%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n", + dev->name, packet_number, status, + packet_len, packet_len); + + if (unlikely(status & RS_ERRORS)) { + lp->stats.rx_errors++; + if (status & RS_ALGNERR) + lp->stats.rx_frame_errors++; + if (status & (RS_TOOSHORT | RS_TOOLONG)) + lp->stats.rx_length_errors++; + if (status & RS_BADCRC) + lp->stats.rx_crc_errors++; + } else { + struct sk_buff *skb; + unsigned char *data; + unsigned int data_len; + + /* set multicast stats */ + if (status & RS_MULTICAST) + lp->stats.multicast++; + + /* + * Actual payload is packet_len - 4 (or 3 if odd byte). + * We want skb_reserve(2) and the final ctrl word + * (2 bytes, possibly containing the payload odd byte). + * Ence packet_len - 4 + 2 + 2. + */ + skb = dev_alloc_skb(packet_len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + dev->name); + lp->stats.rx_dropped++; + goto done; + } + + /* Align IP header to 32 bits */ + skb_reserve(skb, 2); + + /* BUG: the LAN91C111 rev A never sets this bit. Force it. */ + if (lp->version == 0x90) + status |= RS_ODDFRAME; + + /* + * If odd length: packet_len - 3, + * otherwise packet_len - 4. + */ + data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4); + data = skb_put(skb, data_len); + SMC_PULL_DATA(data, packet_len - 2); + + PRINT_PKT(data, packet_len - 2); + + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += data_len; + } + +done: + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD( MC_RELEASE ); +} + +/* + * This is called to actually send a packet to the chip. + * Returns non-zero when successful. + */ +static void +smc_hardware_send_packet(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb = lp->saved_skb; + unsigned int packet_no, len; + unsigned char *buf; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + if (unlikely(!skb)) { + printk ("%s: In XMIT with no packet to send\n", dev->name); + return; + } + + packet_no = SMC_GET_AR(); + if (unlikely(packet_no & AR_FAILED)) { + printk("%s: Memory allocation failed.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_fifo_errors++; + dev_kfree_skb_any(skb); + return; + } + + /* point to the beginning of the packet */ + SMC_SET_PN( packet_no ); + SMC_SET_PTR( PTR_AUTOINC ); + + buf = skb->data; + len = skb->len; + PRINTK2("%s: TX PNR 0x%x lENGTH 0x%04x (%d) BUF 9x%p\n", + dev->name, packet_no, len, len, buf); + PRINT_PKT(buf, len); + + /* + * Send the packet length ( +6 for status words, length, and ctl. + * The card will pad to 64 bytes with zeroes if packet is too small. + */ + SMC_PUT_PKT_HDR(0, len + 6); + + /* send the actual data */ + SMC_PUSH_DATA(buf, len & ~1); + + /* Send final ctl word with the last byte if there is one */ + SMC_outw( ((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG ); + + /* and let the chipset deal with it */ + SMC_SET_MMU_CMD( MC_ENQUEUE ); + SMC_ACK_INT( IM_TX_EMPTY_INT ); + + dev->trans_start = jiffies; + dev_kfree_skb_any(skb); + lp->saved_skb = NULL; + lp->stats.tx_packets++; + lp->stats.tx_bytes += len; +} + +/* + . Since I am not sure if I will have enough room in the chip's ram + . to store the packet, I call this routine which either sends it + . now, or set the card to generates an interrupt when ready + . for the packet. + */ +static int +smc_hard_start_xmit( struct sk_buff * skb, struct net_device * dev ) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + unsigned int numPages, poll_count, status, saved_bank; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + if (unlikely(lp->saved_skb != NULL)) { + /* THIS SHOULD NEVER HAPPEN. */ + printk( KERN_CRIT + "%s: Bad Craziness - sent packet while busy.\n", + dev->name ); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + return 1; + } + lp->saved_skb = skb; + + /* + ** The MMU wants the number of pages to be the number of 256 bytes + ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + ** + ** The 91C111 ignores the size bits, but the code is left intact + ** for backwards and future compatibility. + ** + ** Pkt size for allocating is data length +6 (for additional status + ** words, length and ctl!) + ** + ** If odd size then last byte is included in ctl word. + */ + numPages = ((skb->len & ~1) + (6 - 1)) >> 8; + if (unlikely(numPages > 7)) { + printk("%s: Far too big packet error.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + /* now, try to allocate the memory */ + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK( 2 ); + SMC_SET_MMU_CMD( MC_ALLOC | numPages ); + + /* + * Poll the chip for a short amount of time in case the + * allocation succeeds quickly. + */ + poll_count = MEMORY_WAIT_TIME; + do { + status = SMC_GET_INT(); + if (status & IM_ALLOC_INT) { + SMC_ACK_INT( IM_ALLOC_INT ); + break; + } + } while (--poll_count); + + if (!poll_count) { + /* oh well, wait until the chip finds memory later */ + netif_stop_queue(dev); + PRINTK2("%s: TX memory allocation deferred.\n", dev->name); + SMC_ENABLE_INT( IM_ALLOC_INT ); + } else { + /* Send current packet immediately.. */ +#if THROTTLE_TX_PKTS + netif_stop_queue(dev); +#endif + smc_hardware_send_packet(dev); + SMC_ENABLE_INT( IM_TX_INT | IM_TX_EMPTY_INT ); + } + + SMC_SELECT_BANK( saved_bank ); + return 0; +} + +/* + . This handles a TX interrupt, which is only called when an error + . relating to a packet is sent or CTL_AUTO_RELEASE is not set. +*/ +static void +smc_tx(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned int saved_packet, packet_no, tx_status, pkt_len; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + /* If the TX FIFO is empty then nothing to do */ + packet_no = SMC_GET_TXFIFO(); + if (unlikely(packet_no & TXFIFO_TEMPTY)) { + PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name); + return; + } + + /* select packet to read from */ + saved_packet = SMC_GET_PN(); + SMC_SET_PN( packet_no ); + + /* read the first word (status word) from this packet */ + SMC_SET_PTR( PTR_AUTOINC | PTR_READ ); + SMC_GET_PKT_HDR(tx_status, pkt_len); + PRINTK2("%s: TX STATUS 0x%04x PNR 0x%02x\n", + dev->name, tx_status, packet_no); + + if (!(tx_status & TS_SUCCESS)) + lp->stats.tx_errors++; + if (tx_status & TS_LOSTCAR) + lp->stats.tx_carrier_errors++; + if (tx_status & TS_LATCOL) { + printk( KERN_DEBUG + "%s: Late collision occurred on last xmit.\n", + dev->name); + lp->stats.tx_window_errors++; + } + + /* kill the packet */ + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD( MC_FREEPKT ); + + /* Don't restore Packet Number Reg until busy bit is cleared */ + SMC_WAIT_MMU_BUSY(); + SMC_SET_PN( saved_packet ); + + /* re-enable transmit */ + SMC_SELECT_BANK( 0 ); + SMC_SET_TCR( lp->tcr_cur_mode ); + SMC_SELECT_BANK( 2 ); +} + + +//---PHY CONTROL AND CONFIGURATION----------------------------------------- + +/*------------------------------------------------------------ + . Debugging function for viewing MII Management serial bitstream + .-------------------------------------------------------------*/ +#if SMC_DEBUG > 3 +static void +PRINT_MII_STREAM(u_char *bits, int size) +{ + int i; + + printk("BIT#:"); + for (i = 0; i < size; ++i) + printk("%d", i%10); + + printk("\nMDOE:"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDOE) + printk("1"); + else + printk("0"); + } + + printk("\nMDO :"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDO) + printk("1"); + else + printk("0"); + } + + printk("\nMDI :"); + for (i = 0; i < size; ++i) { + if (bits[i] & MII_MDI) + printk("1"); + else + printk("0"); + } + + printk("\n"); +} +#else +#define PRINT_MII_STREAM(x...) +#endif + +/*------------------------------------------------------------ + . Reads a register from the MII Management serial interface + .-------------------------------------------------------------*/ +static int +smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg) +{ + int oldBank; + int i, mask, mii_reg; + u_char bits[64]; + int input_idx, phydata; + int clk_idx = 0; + + // 32 consecutive ones on MDO to establish sync + for (i = 0; i < 32; ++i) + bits[clk_idx++] = MII_MDOE | MII_MDO; + + // Start code <01> + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + // Read command <10> + bits[clk_idx++] = MII_MDOE | MII_MDO; + bits[clk_idx++] = MII_MDOE; + + // Output the PHY address, msb first + mask = 0x10; + for (i = 0; i < 5; ++i) { + if (phyaddr & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + // Shift to next lowest bit + mask >>= 1; + } + + // Output the phy register number, msb first + mask = 0x10; + for (i = 0; i < 5; ++i) { + if (phyreg & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + // Shift to next lowest bit + mask >>= 1; + } + + // Tristate and turnaround (2 bit times) + bits[clk_idx++] = 0; + //bits[clk_idx++] = 0; + + // Input starts at this bit time + input_idx = clk_idx; + + // Will input 16 bits + for (i = 0; i < 16; ++i) + bits[clk_idx++] = 0; + + // Final clock bit + bits[clk_idx++] = 0; + + // Save the current bank + oldBank = SMC_CURRENT_BANK(); + + // Select bank 3 + SMC_SELECT_BANK( 3 ); + + // Get the current MII register value + mii_reg = SMC_GET_MII(); + + // Turn off all MII Interface bits + mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); + + // Clock all 64 cycles + for (i = 0; i < sizeof bits; ++i) { + // Clock Low - output data + SMC_SET_MII( mii_reg | bits[i] ); + udelay(50); + + // Clock Hi - input data + SMC_SET_MII( mii_reg | bits[i] | MII_MCLK ); + udelay(50); + bits[i] |= SMC_GET_MII() & MII_MDI; + } + + // Return to idle state + // Set clock to low, data to low, and output tristated + SMC_SET_MII( mii_reg ); + udelay(50); + + // Restore original bank select + SMC_SELECT_BANK( oldBank ); + + // Recover input data + phydata = 0; + for (i = 0; i < 16; ++i) { + phydata <<= 1; + + if (bits[input_idx++] & MII_MDI) + phydata |= 0x0001; + } + + PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + PRINT_MII_STREAM(bits, sizeof(bits)); + + return phydata; +} + +/*------------------------------------------------------------ + . Writes a register to the MII Management serial interface + .-------------------------------------------------------------*/ +static void +smc_write_phy_register( unsigned long ioaddr, int phyaddr, + int phyreg, int phydata ) +{ + int oldBank; + int i, mask, mii_reg; + u_char bits[65]; + int clk_idx = 0; + + // 32 consecutive ones on MDO to establish sync + for (i = 0; i < 32; ++i) + bits[clk_idx++] = MII_MDOE | MII_MDO; + + // Start code <01> + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + // Write command <01> + bits[clk_idx++] = MII_MDOE; + bits[clk_idx++] = MII_MDOE | MII_MDO; + + // Output the PHY address, msb first + mask = 0x10; + for (i = 0; i < 5; ++i) { + if (phyaddr & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + // Shift to next lowest bit + mask >>= 1; + } + + // Output the phy register number, msb first + mask = 0x10; + for (i = 0; i < 5; ++i) { + if (phyreg & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + // Shift to next lowest bit + mask >>= 1; + } + + // Tristate and turnaround (2 bit times) + bits[clk_idx++] = 0; + bits[clk_idx++] = 0; + + // Write out 16 bits of data, msb first + mask = 0x8000; + for (i = 0; i < 16; ++i) { + if (phydata & mask) + bits[clk_idx++] = MII_MDOE | MII_MDO; + else + bits[clk_idx++] = MII_MDOE; + + // Shift to next lowest bit + mask >>= 1; + } + + // Final clock bit (tristate) + bits[clk_idx++] = 0; + + // Save the current bank + oldBank = SMC_CURRENT_BANK(); + + // Select bank 3 + SMC_SELECT_BANK( 3 ); + + // Get the current MII register value + mii_reg = SMC_GET_MII(); + + // Turn off all MII Interface bits + mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); + + // Clock all cycles + for (i = 0; i < sizeof bits; ++i) { + // Clock Low - output data + SMC_SET_MII( mii_reg | bits[i] ); + udelay(50); + + // Clock Hi - input data + SMC_SET_MII( mii_reg | bits[i] | MII_MCLK ); + udelay(50); + bits[i] |= SMC_GET_MII() & MII_MDI; + } + + // Return to idle state + // Set clock to low, data to low, and output tristated + SMC_SET_MII( mii_reg ); + udelay(50); + + // Restore original bank select + SMC_SELECT_BANK( oldBank ); + + PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + PRINT_MII_STREAM(bits, sizeof(bits)); +} + + +/*------------------------------------------------------------ + . Finds and reports the PHY address + .-------------------------------------------------------------*/ +static int smc_detect_phy(struct net_device* dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + int phy_id1, phy_id2; + int phyaddr; + int found = 0; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + // Scan all 32 PHY addresses if necessary + for (phyaddr = 0; phyaddr < 32; ++phyaddr) { + // Read the PHY identifiers + phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG); + phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG); + + PRINTK3("%s: phy_id1=0x%x, phy_id2=0x%x\n", + dev->name, phy_id1, phy_id2); + + // Make sure it is a valid identifier + if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) && + (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) { + if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) { + // Save the PHY's address + lp->phyaddr = phyaddr; + found = 1; + break; + } + } + } + + if (!found) { + PRINTK("%s: No PHY found\n", dev->name); + return(0); + } + + // Set the PHY type + if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) { + lp->phytype = PHY_LAN83C183; + PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name); + } + + if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) { + lp->phytype = PHY_LAN83C180; + PRINTK("%s: PHY=LAN83C180\n", dev->name); + } + + return 1; +} + +/*------------------------------------------------------------ + . Waits the specified number of milliseconds - kernel friendly + .-------------------------------------------------------------*/ +static void +smc_wait_ms(unsigned int ms) +{ + if (!in_interrupt()) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1 + ms * HZ / 1000); + } else { + /* if this happens it must be fixed */ + printk( KERN_WARNING "%s: busy wait while in interrupt!\n", + __FUNCTION__); + mdelay(ms); + } +} + +/*------------------------------------------------------------ + . Sets the PHY to a configuration as determined by the user + .-------------------------------------------------------------*/ +static int +smc_phy_fixed(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int phyaddr = lp->phyaddr; + int my_fixed_caps, cfg1; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + // Enter Link Disable state + cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG); + cfg1 |= PHY_CFG1_LNKDIS; + smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1); + + // Set our fixed capabilities + // Disable auto-negotiation + my_fixed_caps = 0; + + if (lp->ctl_rfduplx) + my_fixed_caps |= PHY_CNTL_DPLX; + + if (lp->ctl_rspeed == 100) + my_fixed_caps |= PHY_CNTL_SPEED; + + // Write our capabilities to the phy control register + smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps); + + // Re-Configure the Receive/Phy Control register + SMC_SET_RPC( lp->rpc_cur_mode ); + + // Success + return(1); +} + +/*------------------------------------------------------------ + . Configures the specified PHY through the MII management interface + . using Autonegotiation. + . Calls smc_phy_fixed() if the user has requested a certain config. + .-------------------------------------------------------------*/ +static void +smc_phy_configure(struct net_device* dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int timeout; + int phyaddr; + int my_phy_caps; // My PHY capabilities + int my_ad_caps; // My Advertised capabilities + int status; + + PRINTK3("%s:smc_program_phy()\n", dev->name); + + // Set the blocking flag + lp->autoneg_active = 1; + + // Find the address and type of our phy + if (!smc_detect_phy(dev)) + goto smc_phy_configure_exit; + + // Get the detected phy address + phyaddr = lp->phyaddr; + + // Reset the PHY, setting all other bits to zero + smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST); + + // Wait for the reset to complete, or time out + timeout = 6; // Wait up to 3 seconds + while (timeout--) { + if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG) + & PHY_CNTL_RST)) + // reset complete + break; + smc_wait_ms(500); // wait 500 millisecs + if (signal_pending(current)) { // Exit anyway if signaled + PRINTK("%s: PHY reset interrupted by signal\n", + dev->name); + timeout = 0; + break; + } + } + + if (timeout < 1) { + printk("%s: PHY reset timed out\n", dev->name); + goto smc_phy_configure_exit; + } + + // Read PHY Register 18, Status Output + lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG); + + // Enable PHY Interrupts (for register 18) + // Interrupts listed here are disabled + smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG, + PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | + PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | + PHY_INT_SPDDET | PHY_INT_DPLXDET); + + /* Configure the Receive/Phy Control register */ + SMC_SELECT_BANK( 0 ); + SMC_SET_RPC( lp->rpc_cur_mode ); + + // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG + my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); + + // If the user requested no auto neg, then go set his request + if (!(lp->ctl_autoneg)) { + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + if( !( my_phy_caps & PHY_STAT_CAP_ANEG)) + { + printk(KERN_INFO "Auto negotiation NOT supported\n"); + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + my_ad_caps = PHY_AD_CSMA; // I am CSMA capable + + if (my_phy_caps & PHY_STAT_CAP_T4) + my_ad_caps |= PHY_AD_T4; + + if (my_phy_caps & PHY_STAT_CAP_TXF) + my_ad_caps |= PHY_AD_TX_FDX; + + if (my_phy_caps & PHY_STAT_CAP_TXH) + my_ad_caps |= PHY_AD_TX_HDX; + + if (my_phy_caps & PHY_STAT_CAP_TF) + my_ad_caps |= PHY_AD_10_FDX; + + if (my_phy_caps & PHY_STAT_CAP_TH) + my_ad_caps |= PHY_AD_10_HDX; + + // Disable capabilities not selected by our user + if (lp->ctl_rspeed != 100) + my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX); + + if (!lp->ctl_rfduplx) + my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX); + + // Update our Auto-Neg Advertisement Register + smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps); + + // Read the register back. Without this, it appears that when + // auto-negotiation is restarted, sometimes it isn't ready and + // the link does not come up. + status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG); + + PRINTK2("%s: phy caps=%x\n", dev->name, my_phy_caps); + PRINTK2("%s: phy advertised caps=%x\n", dev->name, my_ad_caps); + + // Restart auto-negotiation process in order to advertise my caps + smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG, + PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST ); + + // Wait for the auto-negotiation to complete. This may take from + // 2 to 3 seconds. + // Wait for the reset to complete, or time out + timeout = 20; // Wait up to 10 seconds + while (timeout--) { + status = smc_read_phy_register(ioaddr, phyaddr, PHY_RMT_REG); + if (status & PHY_AD_ACK) + // auto-negotiate complete + break; + + smc_wait_ms(500); // wait 500 millisecs + if (signal_pending(current)) { // Exit anyway if signaled + printk(KERN_DEBUG + "%s: PHY auto-negotiate interrupted by signal\n", + dev->name); + timeout = 0; + break; + } + } + status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); + + if (timeout < 1) { + PRINTK("%s: PHY auto-negotiate timed out\n", dev->name); + } + + // Fail if we detected an auto-negotiate remote fault + if (status & PHY_STAT_REM_FLT) { + PRINTK("%s: PHY remote fault detected\n", dev->name); + } + + // Wait for link. Once the link is up, phy18 should be up to date + timeout = 200; + do + { + udelay(100); + status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); + } while ( ((status & PHY_STAT_LINK)==0) && --timeout); + + if (status & PHY_STAT_LINK) + { + PRINTK("%s: Ethernet Link Detected\n", dev->name); + } + + // The smc_phy_interrupt() routine will be called to update lastPhy18 + + // Set our sysctl parameters to match auto-negotiation results + if ( lp->lastPhy18 & PHY_INT_SPDDET ) { + PRINTK("%s: PHY 100BaseT\n", dev->name); + lp->rpc_cur_mode |= RPC_SPEED; + } else { + PRINTK("%s: PHY 10BaseT\n", dev->name); + lp->rpc_cur_mode &= ~RPC_SPEED; + } + + if ( lp->lastPhy18 & PHY_INT_DPLXDET ) { + PRINTK("%s: PHY Full Duplex\n", dev->name); + lp->rpc_cur_mode |= RPC_DPLX; + lp->tcr_cur_mode |= TCR_SWFDUP; + } else { + PRINTK("%s: PHY Half Duplex\n", dev->name); + lp->rpc_cur_mode &= ~RPC_DPLX; + lp->tcr_cur_mode &= ~TCR_SWFDUP; + } + + // Re-Configure the Receive/Phy Control register and TCR + SMC_SET_RPC( lp->rpc_cur_mode ); + SMC_SET_TCR( lp->tcr_cur_mode ); + +smc_phy_configure_exit: + // Exit auto-negotiation + lp->autoneg_active = 0; +} + +/************************************************************************* + . smc_phy_interrupt + . + . Purpose: Handle interrupts relating to PHY register 18. This is + . called from the "hard" interrupt handler. + . + ************************************************************************/ +static void +smc_phy_interrupt(struct net_device* dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int phyaddr = lp->phyaddr; + int phy18; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + for(;;) { + // Read PHY Register 18, Status Output + phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG); + + // Exit if not more changes + if (phy18 == lp->lastPhy18) + break; + +#if SMC_DEBUG > 1 + PRINTK2("%s: phy18=0x%04x\n", dev->name, phy18); + PRINTK2("%s: lastPhy18=0x%04x\n", dev->name, lp->lastPhy18); + + // Handle events + if ((phy18 & PHY_INT_LNKFAIL) != + (lp->lastPhy18 & PHY_INT_LNKFAIL)) + PRINTK2("%s: PHY Link Fail=%x\n", dev->name, + phy18 & PHY_INT_LNKFAIL); + + if ((phy18 & PHY_INT_LOSSSYNC) != + (lp->lastPhy18 & PHY_INT_LOSSSYNC)) + PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name, + phy18 & PHY_INT_LOSSSYNC); + + if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD)) + PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name, + phy18 & PHY_INT_CWRD); + + if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD)) + PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name, + phy18 & PHY_INT_SSD); + + if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD)) + + PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name, + phy18 & PHY_INT_ESD); + + if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL)) + PRINTK2("%s: PHY Reverse Polarity Detected=%x\n", + dev->name, phy18 & PHY_INT_RPOL); + + if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB)) + PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name, + phy18 & PHY_INT_JAB); + + if ((phy18 & PHY_INT_SPDDET) != + (lp->lastPhy18 & PHY_INT_SPDDET)) + PRINTK2("%s: PHY Speed Detect=%x\n", dev->name, + phy18 & PHY_INT_SPDDET); + + if ((phy18 & PHY_INT_DPLXDET) != + (lp->lastPhy18 & PHY_INT_DPLXDET)) + PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name, + phy18 & PHY_INT_DPLXDET); +#endif + // Update the last phy 18 variable + lp->lastPhy18 = phy18; + } +} + +//--- END PHY CONTROL AND CONFIGURATION------------------------------------- + + +/* + * This is the main routine of the driver, to handle the device when + * it needs some attention. + */ +static void +smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + int status, mask, timeout, card_stats; + int saved_bank, saved_pointer; + + PRINTK3("%s: %s\n", dev->name, __FUNCTION__); + + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(2); + saved_pointer = SMC_GET_PTR(); + mask = SMC_GET_INT_MASK(); + SMC_SET_INT_MASK( 0 ); + + /* set a timeout value, so I don't stay here forever */ + timeout = 8; + + do { + status = SMC_GET_INT(); + + PRINTK2("%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", + dev->name, status, mask, + ({ int meminfo; SMC_SELECT_BANK(0); + meminfo = SMC_GET_MIR(); + SMC_SELECT_BANK(2); meminfo; }), + SMC_GET_FIFO()); + + status &= mask; + if (!status) + break; + + if (status & IM_RCV_INT) { + PRINTK3("%s: RX irq\n", dev->name); + smc_rcv(dev); + } else if (status & IM_TX_INT) { + PRINTK3("%s: TX int\n", dev->name); + smc_tx(dev); + SMC_ACK_INT( IM_TX_INT ); +#if THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_ALLOC_INT) { + PRINTK3("%s: Allocation irq\n", dev->name); + smc_hardware_send_packet(dev); + mask |= (IM_TX_INT | IM_TX_EMPTY_INT); + mask &= ~IM_ALLOC_INT; +#if ! THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_TX_EMPTY_INT) { + PRINTK3("%s: TX empty\n", dev->name); + mask &= ~IM_TX_EMPTY_INT; + + /* update stats */ + SMC_SELECT_BANK( 0 ); + card_stats = SMC_GET_COUNTER(); + SMC_SELECT_BANK( 2 ); + + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + } else if (status & IM_RX_OVRN_INT) { + PRINTK1( "%s: RX overrun\n", dev->name); + SMC_ACK_INT( IM_RX_OVRN_INT ); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } else if (status & IM_EPH_INT) { + PRINTK("%s: UNSUPPORTED: EPH INTERRUPT\n", dev->name); + } else if (status & IM_MDINT) { + SMC_ACK_INT( IM_MDINT ); + smc_phy_interrupt(dev); + } else if (status & IM_ERCV_INT ) { + SMC_ACK_INT( IM_ERCV_INT ); + PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name); + } + } while (--timeout); + + /* restore register states */ + SMC_SET_INT_MASK( mask ); + SMC_SET_PTR( saved_pointer ); + SMC_SELECT_BANK( saved_bank ); + + PRINTK3("%s: Interrupt done\n", dev->name); +} + +/* Our watchdog timed out. Called by the networking layer */ +static void +smc_timeout(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + smc_reset(dev); + smc_enable(dev); + +#if 0 + /* Reconfiguring the PHY doesn't seem like a bad idea here, but + * it introduced a problem. Now that this is a timeout routine, + * we are getting called from within an interrupt context. + * smc_phy_configure() calls smc_wait_ms() which calls + * schedule_timeout() which calls schedule(). When schedule() + * is called from an interrupt context, it prints out + * "Scheduling in interrupt" and then calls BUG(). This is + * obviously not desirable. This was worked around by removing + * the call to smc_phy_configure() here because it didn't seem + * absolutely necessary. Ultimately, if smc_wait_ms() is + * supposed to be usable from an interrupt context (which it + * looks like it thinks it should handle), it should be fixed. + */ + /* Reconfigure the PHY */ + smc_phy_configure(dev); +#endif + + /* clear anything saved */ + if (lp->saved_skb != NULL) { + dev_kfree_skb (lp->saved_skb); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +/* + * Finds the CRC32 of a set of bytes. + * (from Peter Cammaert's code) + */ +static int +crc32(char *s, int length) +{ + /* indices */ + int perByte; + int perBit; + /* crc polynomial for Ethernet */ + const unsigned long poly = 0xedb88320; + /* crc value - preinitialized to all 1's */ + unsigned long crc_value = 0xffffffff; + + for ( perByte = 0; perByte < length; perByte ++ ) { + unsigned char c; + + c = *(s++); + for ( perBit = 0; perBit < 8; perBit++ ) { + crc_value = (crc_value>>1)^ + (((crc_value^c)&0x01)?poly:0); + c >>= 1; + } + } + return crc_value; +} + +/* + . This sets the internal hardware table to filter out unwanted multicast + . packets before they take up memory. + . + . The SMC chip uses a hash table where the high 6 bits of the CRC of + . address are the offset into the table. If that bit is 1, then the + . multicast packet is accepted. Otherwise, it's dropped silently. + . + . To use the 6 bits as an offset into the table, the high 3 bits are the + . number of the 8 bit register, while the low 3 bits are the bit within + . that register. + . + . This routine is based very heavily on the one provided by Peter Cammaert. +*/ +static void +smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs) +{ + int i; + unsigned char multicast_table[ 8 ]; + struct dev_mc_list *cur_addr; + + /* table for flipping the order of 3 bits */ + static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + /* start with a table of all zeros: reject all */ + memset( multicast_table, 0, sizeof( multicast_table ) ); + + cur_addr = addrs; + for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { + int position; + + /* do we have a pointer here? */ + if ( !cur_addr ) + break; + /* make sure this is a multicast address - shouldn't this + be a given if we have it here ? */ + if ( !( *cur_addr->dmi_addr & 1 ) ) + continue; + + /* only use the low order bits */ + position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert3[position&7]] |= + (1<>3)&7]); + + } + /* now, the table can be loaded into the chipset */ + SMC_SELECT_BANK( 3 ); + SMC_SET_MCAST( multicast_table ); +} + +/* + . This routine will, depending on the values passed to it, + . either make it accept multicast packets, go into + . promiscuous mode ( for TCPDUMP and cousins ) or accept + . a select set of multicast packets +*/ +static void smc_set_multicast_list(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + SMC_SELECT_BANK(0); + if ( dev->flags & IFF_PROMISC ) { + PRINTK2("%s: RCR_PRMS\n", dev->name); + lp->rcr_cur_mode |= RCR_PRMS; + SMC_SET_RCR( lp->rcr_cur_mode ); + } + +/* BUG? I never disable promiscuous mode if multicasting was turned on. + Now, I turn off promiscuous mode, but I don't do anything to multicasting + when promiscuous mode is turned on. +*/ + + /* Here, I am setting this to accept all multicast packets. + I don't need to zero the multicast table, because the flag is + checked before the table is + */ + else if (dev->flags & IFF_ALLMULTI) { + lp->rcr_cur_mode |= RCR_ALMUL; + SMC_SET_RCR( lp->rcr_cur_mode ); + PRINTK2("%s: RCR_ALMUL\n", dev->name); + } + + /* We just get all multicast packets even if we only want them + . from one source. This will be changed at some future + . point. */ + else if (dev->mc_count ) { + /* support hardware multicasting */ + + /* be sure I get rid of flags I might have set */ + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR( lp->rcr_cur_mode ); + /* NOTE: this has to set the bank, so make sure it is the + last thing called. The bank is set to zero at the top */ + smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); + } else { + PRINTK2("%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name); + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR( lp->rcr_cur_mode ); + + /* + since I'm disabling all multicast entirely, I need to + clear the multicast list + */ + SMC_SELECT_BANK( 3 ); + SMC_CLEAR_MCAST(); + } +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc .. + */ +static int +smc_open(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + unsigned long ioaddr = dev->base_addr; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + /* clear out all the junk that was put here before... */ + memset(dev->priv, 0, sizeof(struct smc_local)); + + // Setup the default Register Modes + lp->tcr_cur_mode = TCR_DEFAULT; + lp->rcr_cur_mode = RCR_DEFAULT; + lp->rpc_cur_mode = RPC_DEFAULT; + + /* Set default parameters */ +#ifdef CONFIG_ARCH_RAMSES + lp->ctl_autoneg = 0; + lp->ctl_rfduplx = 0; + lp->ctl_rspeed = 10; +#else + lp->ctl_autoneg = 1; + lp->ctl_rfduplx = 1; + lp->ctl_rspeed = 100; +#endif + + SMC_SELECT_BANK(3); + lp->version = SMC_GET_REV() & 0xff; + + /* reset the hardware */ + smc_reset(dev); + smc_enable(dev); + + SMC_SELECT_BANK( 1 ); + SMC_SET_MAC_ADDR(dev->dev_addr); + + /* Configure the PHY */ + if (lp->version >= 0x70) + smc_phy_configure(dev); + + netif_start_queue(dev); + return 0; +} + +/*---------------------------------------------------- + . smc_close + . + . this makes the board clean up everything that it can + . and not talk to the outside world. Caused by + . an 'ifconfig ethX down' + . + -----------------------------------------------------*/ +static int +smc_close(struct net_device *dev) +{ + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + netif_stop_queue(dev); + + /* clear everything */ + smc_shutdown(dev); + + return 0; +} + +/*------------------------------------------------------------ + . Get the current statistics. + . This may be called with the card open or closed. + .-------------------------------------------------------------*/ +static struct net_device_stats * +smc_query_statistics(struct net_device *dev) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + + PRINTK2("%s: %s\n", dev->name, __FUNCTION__); + + return &lp->stats; +} + +/*---------------------------------------------------------------------- + . smc_findirq + . + . This routine has a simple purpose -- make the SMC chip generate an + . interrupt, so an auto-detect routine can detect it, and find the IRQ, + ------------------------------------------------------------------------ +*/ +int __init +smc_findirq( unsigned long ioaddr ) +{ + int timeout = 20; + unsigned long cookie; + + PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__); + + cookie = probe_irq_on(); + + /* + * What I try to do here is trigger an ALLOC_INT. This is done + * by allocating a small chunk of memory, which will give an interrupt + * when done. + */ + + /* enable ALLOCation interrupts ONLY */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK( IM_ALLOC_INT ); + + /* + . Allocate 512 bytes of memory. Note that the chip was just + . reset so all the memory is available + */ + SMC_SET_MMU_CMD( MC_ALLOC | 1 ); + + /* + . Wait until positive that the interrupt has been generated + */ + do { + int int_status; + udelay(10); + int_status = SMC_GET_INT(); + if (int_status & IM_ALLOC_INT) + break; /* got the interrupt */ + } while (--timeout); + + /* there is really nothing that I can do here if timeout fails, + as autoirq_report will return a 0 anyway, which is what I + want in this case. Plus, the clean up is needed in both + cases. */ + + /* and disable all interrupts again */ + SMC_SET_INT_MASK( 0 ); + + /* and return what I found */ + return probe_irq_off(cookie); +} + +/*---------------------------------------------------------------------- + . Function: smc_probe( unsigned long ioaddr ) + . + . Purpose: + . Tests to see if a given ioaddr points to an SMC91x chip. + . Returns a 0 on success + . + . Algorithm: + . (1) see if the high byte of BANK_SELECT is 0x33 + . (2) compare the ioaddr with the base register's address + . (3) see if I recognize the chip ID in the appropriate register + . + .--------------------------------------------------------------------- + */ +/*--------------------------------------------------------------- + . Here I do typical initialization tasks. + . + . o Initialize the structure if needed + . o print out my vanity message if not done so already + . o print out what type of hardware is detected + . o print out the ethernet address + . o find the IRQ + . o set up my private data + . o configure the dev structure with my subroutines + . o actually GRAB the irq. + . o GRAB the region + .----------------------------------------------------------------- +*/ +static int __init +smc_probe(struct net_device *dev, unsigned long ioaddr) +{ + struct smc_local *lp = (struct smc_local *)dev->priv; + static int version_printed = 0; + int i, retval; + unsigned int val, revision_register; + const char *version_string; + + PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__); + + /* Grab the region so that no one else tries to probe our ioports. */ + if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) + return -EBUSY; + + /* First, see if the high byte is 0x33 */ + val = SMC_CURRENT_BANK(); + PRINTK2("%s: bank signature probe returned 0x%04x\n", CARDNAME, val); + if ( (val & 0xFF00) != 0x3300 ) { + if ( (val & 0xFF) == 0x33 ) { + printk( KERN_WARNING + "%s: Detected possible byte-swapped interface" + " at IOADDR 0x%lx\n", CARDNAME, ioaddr); + } + retval = -ENODEV; + goto err_out; + } + + /* The above MIGHT indicate a device, but I need to write to further + test this. */ + SMC_SELECT_BANK(0); + val = SMC_CURRENT_BANK(); + if ( (val & 0xFF00 ) != 0x3300 ) { + retval = -ENODEV; + goto err_out; + } + + /* well, we've already written once, so hopefully another time won't + hurt. This time, I need to switch the bank register to bank 1, + so I can access the base address register */ + SMC_SELECT_BANK(1); + val = SMC_GET_BASE(); + val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT; + if ( (ioaddr & ((PAGE_SIZE-1)<> 4) & 0xF]; + if (!version_string || (revision_register & 0xff00) != 0x3300) { + /* I don't recognize this chip, so... */ + printk( "%s: IO 0x%lx: Unrecognized revision register 0x%04x" + ", Contact author.\n", CARDNAME, + ioaddr, revision_register); + + retval = -ENODEV; + goto err_out; + } + + /* At this point I'll assume that the chip is an SMC91x. */ + if (version_printed++ == 0) + printk("%s", version); + + /* set the private data to zero by default */ + memset(lp, 0, sizeof(struct smc_local)); + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + lp->version = revision_register & 0xff; + + /* Get the MAC address */ + SMC_SELECT_BANK( 1 ); + SMC_GET_MAC_ADDR(dev->dev_addr); + + /* now, reset the chip, and put it into a known state */ + smc_reset( dev ); + + /* + . If dev->irq is 0, then the device has to be banged on to see + . what the IRQ is. + . + . This banging doesn't always detect the IRQ, for unknown reasons. + . a workaround is to reset the chip and try again. + . + . Interestingly, the DOS packet driver *SETS* the IRQ on the card to + . be what is requested on the command line. I don't do that, mostly + . because the card that I have uses a non-standard method of accessing + . the IRQs, and because this _should_ work in most configurations. + . + . Specifying an IRQ is done with the assumption that the user knows + . what (s)he is doing. No checking is done!!!! + . + */ + if ( dev->irq < 1 ) { + int trials; + + trials = 3; + while ( trials-- ) { + dev->irq = smc_findirq( ioaddr ); + if ( dev->irq ) + break; + /* kick the card and try again */ + smc_reset( dev ); + } + } + if (dev->irq == 0 ) { + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", + dev->name); + retval = -ENODEV; + goto err_out; + } + dev->irq = irq_cannonicalize(dev->irq); + + /* now, print out the card info, in a short format.. */ + printk( "%s: %s (rev %d) at %#lx IRQ %d%s%s\n", + dev->name, version_string, revision_register & 0x0f, + ioaddr, dev->irq, nowait ? " [nowait]" : "", + THROTTLE_TX_PKTS ? " [throttle_tx]" : "" ); + + /* Print the Ethernet address */ + printk("%s: Ethernet addr: ", dev->name); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i] ); + printk("%2.2x\n", dev->dev_addr[5] ); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + /* Grab the IRQ */ + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + if (retval) { + goto err_out; + } + + dev->open = smc_open; + dev->stop = smc_close; + dev->hard_start_xmit = smc_hard_start_xmit; + dev->tx_timeout = smc_timeout; + dev->watchdog_timeo = HZ/10; + dev->get_stats = smc_query_statistics; + dev->set_multicast_list = smc_set_multicast_list; + + return 0; + +err_out: + release_region(ioaddr, SMC_IO_EXTENT); + return retval; +} + +/*------------------------------------------------------------------------- + | + | smc_init( void ) + | Input parameters: + | dev->base_addr == 0, try to find all possible locations + | dev->base_addr > 0x1ff, this is the address to check + | dev->base_addr == , return failure code + | + | Output: + | 0 --> there is a device + | anything else, error + | + --------------------------------------------------------------------------- +*/ +static struct net_device *global_dev = NULL; /* needs to be fixed */ + +#ifdef CONFIG_PM + +static int smc_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + unsigned long ioaddr = global_dev->base_addr; + struct smc_local *lp = (struct smc_local *)global_dev->priv; + + switch (rqst) { + case PM_SUSPEND: + smc_shutdown(global_dev); + break; + case PM_RESUME: + smc_reset(global_dev); + smc_enable(global_dev); + SMC_SELECT_BANK( 1 ); + SMC_SET_MAC_ADDR(global_dev->dev_addr); + if (lp->version >= 0x70) + smc_phy_configure(global_dev); + break; + } + return 0; +} + +#endif + +static int __init +smc_init(void) +{ + int ret; + + PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__); + +#ifdef MODULE + if (io == -1) + printk( KERN_WARNING + "%s: You shouldn't use auto-probing with insmod!\n", + CARDNAME ); +#endif + + if (global_dev) { + printk("%s: already initialized.\n", CARDNAME); + return -EBUSY; + } + + global_dev = init_etherdev(0, sizeof(struct smc_local)); + if (!global_dev) { + printk("%s: could not allocate device.\n", CARDNAME); + return -ENOMEM; + } + SET_MODULE_OWNER(global_dev); + + /* copy the parameters from insmod into the device structure */ + if (io != -1) + global_dev->base_addr = io; + if (irq != -1) + global_dev->irq = irq; + +#ifdef CONFIG_ISA + /* try a specific location */ + if (global_dev->base_addr > 0x1ff) + ret = smc_probe(global_dev, global_dev->base_addr); + else if (global_dev->base_addr != 0) + ret = -ENXIO; + else { + int i; + + /* check every ethernet address */ + for (i = 0; smc_portlist[i]; i++) { + ret = smc_probe(global_dev, smc_portlist[i]); + if (ret == 0) + break; + } + } +#elif defined(CONFIG_ARCH_LUBBOCK) + { + int ioaddr = LUBBOCK_ETH_VIRT + (0x300 << 2); + volatile int *attaddr = (int *)(LUBBOCK_ETH_VIRT + 0x100000); + unsigned long flags; + + /* first reset, then enable the device. Sequence is critical */ + local_irq_save(flags); + attaddr[ECOR] |= ECOR_RESET; + udelay(100); + attaddr[ECOR] &= ~ECOR_RESET; + attaddr[ECOR] |= ECOR_ENABLE; + + /* force 16-bit mode */ + attaddr[ECSR] &= ~ECSR_IOIS8; + mdelay(1); + local_irq_restore(flags); + + global_dev->irq = LUBBOCK_ETH_IRQ; + ret = smc_probe(global_dev, ioaddr); + } +#elif defined(CONFIG_ARCH_PXA_IDP) + { + int ioaddr = IDP_ETH_BASE + 0x300; + global_dev->irq = SMC_IRQ; + ret = smc_probe(global_dev, ioaddr); + } +#elif defined(CONFIG_ARCH_RAMSES) + { + int ioaddr = RAMSES_ETH_BASE + 0x300; + global_dev->irq = SMC_IRQ; + ret = smc_probe(global_dev, ioaddr); + } +#else + if (global_dev->base_addr == -1) { + printk(KERN_WARNING"%s: SMC91X_BASE_ADDR not set!\n", CARDNAME); + ret = -ENXIO; + } else { + void *ioaddr = ioremap(global_dev->base_addr, SMC_IO_EXTENT); + ret = smc_probe(global_dev, (unsigned long)ioaddr); + if (ret != 0) + iounmap(ioaddr); + } +#endif + +#ifdef SMC_USE_PXA_DMA + if (ret == 0) { + int dma = pxa_request_dma(global_dev->name, DMA_PRIO_LOW, + smc_pxa_dma_irq, NULL); + if (dma >= 0) { + global_dev->dma = dma; + PRINTK("%s: using DMA channel %d\n", global_dev->name, dma); + } else { + global_dev->dma = -1; + } + } +#endif + +#ifdef CONFIG_PM + if (ret == 0) { + struct smc_local *lp = (struct smc_local *)global_dev->priv; + lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback); + } +#endif + + if (ret != 0) { + printk("%s: not found.\n", CARDNAME); + kfree(global_dev->priv); + unregister_netdev(global_dev); + kfree(global_dev); + } + + return ret; +} + +static void __exit +smc_cleanup(void) +{ + unregister_netdev(global_dev); +#ifdef CONFIG_PM + { + struct smc_local *lp = (struct smc_local *)global_dev->priv; + pm_unregister(lp->pm); + } +#endif + free_irq(global_dev->irq, global_dev); + release_region(global_dev->base_addr, SMC_IO_EXTENT); + +#ifndef CONFIG_ISA + iounmap((void *)global_dev->base_addr); +#endif + + kfree(global_dev); + global_dev = NULL; +} + +module_init(smc_init); +module_exit(smc_cleanup); + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/net/smc91x.h 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,835 @@ +/*------------------------------------------------------------------------ + . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device. + . + . Copyright (C) 1996 by Erik Stahlman + . Copyright (C) 2001 Standard Microsystems Corporation + . Developed by Simple Network Magic Corporation + . Copyright (C) 2003 Monta Vista Software, Inc. + . Unified SMC91x driver by Nicolas Pitre + . + . 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 + . + . Information contained in this file was obtained from the LAN91C111 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Erik Stahlman + . Daris A Nevil + . Nicolas Pitre + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC91X_H_ +#define _SMC91X_H_ + + +/* + * Define your architecture specific configuration parameters here. + */ + +#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \ + defined(CONFIG_SA1100_PFS168) || \ + defined(CONFIG_SA1100_FLEXANET) || \ + defined(CONFIG_SA1100_GRAPHICSMASTER) || \ + defined(CONFIG_ARCH_LUBBOCK) + +/* We can only do 16-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +/* The first two address lines aren't connected... */ +#define SMC_IO_SHIFT 2 + +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) + +#ifdef CONFIG_ARCH_LUBBOCK +#define SMC_IOADDR LUBBOCK_ETH_PHYS +#endif + +#elif defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_ARCH_PXA_IDP) || defined(CONFIG_ARCH_RAMSES) + +#ifdef CONFIG_ARCH_MAINSTONE +#include +#define SMC_IOADDR (MST_ETH_PHYS + 0x300) +#define SMC_IRQ MAINSTONE_IRQ(3) + +#elif CONFIG_ARCH_PXA_IDP +#include +#define SMC_IOADDR (IDP_ETH_PHYS + 0x300) +#define SMC_IRQ ETHERNET_IRQ + +#elif CONFIG_ARCH_RAMSES +#include +#define SMC_IOADDR (RAMSES_ETH_PHYS + 0x300) +#define SMC_IRQ ETHERNET_IRQ +#endif + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) insl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) outsl((a) + (r), p, l) + +/* We actually can't write halfwords properly if not word aligned */ +static inline void +SMC_outw(u16 val, unsigned long ioaddr, int reg) +{ + if (reg & 2) { + unsigned int v = val << 16; + v |= readl(ioaddr + (reg & ~2)) & 0xffff; + writel(v, ioaddr + (reg & ~2)); + } else { + writew(val, ioaddr + reg); + } +} + +#elif defined(CONFIG_ISA) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 + +#define SMC_inb(a, r) inb((a) + (r)) +#define SMC_inw(a, r) inw((a) + (r)) +#define SMC_outb(v, a, r) outb(v, (a) + (r)) +#define SMC_outw(v, a, r) outw(v, (a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) + +#endif + + +#ifdef SMC_USE_PXA_DMA +/* + * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is + * always happening in irq context so no need to worry about races. TX is + * different and probably not worth it for that reason, and not as critical + * as RX which can overrun memory and lose packets. + */ +#include +#include + +#ifdef SMC_insl +#undef SMC_insl +#define SMC_insl(a, r, p, l) smc_pxa_dma_insl(a, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insl(u_long ioaddr, int reg, int dma, u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == -1) { + insl(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + *((u32 *)buf)++ = SMC_inl(ioaddr, reg); + len--; + } + + len *= 4; + dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = SMC_IOADDR + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH4 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE); +} +#endif + +#ifdef SMC_insw +#undef SMC_insw +#define SMC_insw(a, r, p, l) smc_pxa_dma_insw(a, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insw(u_long ioaddr, int reg, int dma, u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == -1) { + insw(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + *((u16 *)buf)++ = SMC_inw(ioaddr, reg); + len--; + } + + len *= 2; + dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = SMC_IOADDR + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH2 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE); +} +#endif + +static void +smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) +{ + DCSR(dma) = 0; +} +#endif /* SMC_USE_PXA_DMA */ + + +/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ +#ifndef SMC_IO_SHIFT +#define SMC_IO_SHIFT 0 +#endif +#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) + + +/* + . Bank Select Register: + . + . yyyy yyyy 0000 00xx + . xx = bank number + . yyyy yyyy = 0x33, for identification purposes. +*/ +#define BANK_SELECT (14 << SMC_IO_SHIFT) + + +// Transmit Control Register +/* BANK 0 */ +#define TCR_REG SMC_REG(0x0000, 0) +#define TCR_ENABLE 0x0001 // When 1 we can transmit +#define TCR_LOOP 0x0002 // Controls output pin LBK +#define TCR_FORCOL 0x0004 // When 1 will force a collision +#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0 +#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames +#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier +#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation +#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error +#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback +#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode + +#define TCR_CLEAR 0 /* do NOTHING */ +/* the default settings for the TCR register : */ +#define TCR_DEFAULT (TCR_ENABLE | TCR_PAD_EN) + + +// EPH Status Register +/* BANK 0 */ +#define EPH_STATUS_REG SMC_REG(0x0002, 0) +#define ES_TX_SUC 0x0001 // Last TX was successful +#define ES_SNGL_COL 0x0002 // Single collision detected for last tx +#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx +#define ES_LTX_MULT 0x0008 // Last tx was a multicast +#define ES_16COL 0x0010 // 16 Collisions Reached +#define ES_SQET 0x0020 // Signal Quality Error Test +#define ES_LTXBRD 0x0040 // Last tx was a broadcast +#define ES_TXDEFR 0x0080 // Transmit Deferred +#define ES_LATCOL 0x0200 // Late collision detected on last tx +#define ES_LOSTCARR 0x0400 // Lost Carrier Sense +#define ES_EXC_DEF 0x0800 // Excessive Deferral +#define ES_CTR_ROL 0x1000 // Counter Roll Over indication +#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin +#define ES_TXUNRN 0x8000 // Tx Underrun + + +// Receive Control Register +/* BANK 0 */ +#define RCR_REG SMC_REG(0x0004, 0) +#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted +#define RCR_PRMS 0x0002 // Enable promiscuous mode +#define RCR_ALMUL 0x0004 // When set accepts all multicast frames +#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets +#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets +#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision +#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier +#define RCR_SOFTRST 0x8000 // resets the chip + +/* the normal settings for the RCR register : */ +#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) +#define RCR_CLEAR 0x0 // set it to a base state + + +// Counter Register +/* BANK 0 */ +#define COUNTER_REG SMC_REG(0x0006, 0) + + +// Memory Information Register +/* BANK 0 */ +#define MIR_REG SMC_REG(0x0008, 0) + + +// Receive/Phy Control Register +/* BANK 0 */ +#define RPC_REG SMC_REG(0x000A, 0) +#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. +#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode +#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode +#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb +#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb +#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect +#define RPC_LED_RES (0x01) // LED = Reserved +#define RPC_LED_10 (0x02) // LED = 10Mbps link detect +#define RPC_LED_FD (0x03) // LED = Full Duplex Mode +#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred +#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_TX (0x06) // LED = TX packet occurred +#define RPC_LED_RX (0x07) // LED = RX packet occurred +#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) + + +/* Bank 0 0x0C is reserved */ + +// Bank Select Register +/* All Banks */ +#define BSR_REG 0x000E + + +// Configuration Reg +/* BANK 1 */ +#define CONFIG_REG SMC_REG(0x0000, 1) +#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy +#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL +#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus +#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode. + +// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low +#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) + + +// Base Address Register +/* BANK 1 */ +#define BASE_REG SMC_REG(0x0002, 1) + + +// Individual Address Registers +/* BANK 1 */ +#define ADDR0_REG SMC_REG(0x0004, 1) +#define ADDR1_REG SMC_REG(0x0006, 1) +#define ADDR2_REG SMC_REG(0x0008, 1) + + +// General Purpose Register +/* BANK 1 */ +#define GP_REG SMC_REG(0x000A, 1) + + +// Control Register +/* BANK 1 */ +#define CTL_REG SMC_REG(0x000C, 1) +#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received +#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically +#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt +#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt +#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt +#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store +#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers +#define CTL_STORE 0x0001 // When set stores registers into EEPROM + + +// MMU Command Register +/* BANK 2 */ +#define MMU_CMD_REG SMC_REG(0x0000, 2) +#define MC_BUSY 1 // When 1 the last release has not completed +#define MC_NOP (0<<5) // No Op +#define MC_ALLOC (1<<5) // OR with number of 256 byte packets +#define MC_RESET (2<<5) // Reset MMU to initial state +#define MC_REMOVE (3<<5) // Remove the current rx packet +#define MC_RELEASE (4<<5) // Remove and release the current rx packet +#define MC_FREEPKT (5<<5) // Release packet in PNR register +#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit +#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs + + +// Packet Number Register +/* BANK 2 */ +#define PN_REG SMC_REG(0x0002, 2) + + +// Allocation Result Register +/* BANK 2 */ +#define AR_REG SMC_REG(0x0003, 2) +#define AR_FAILED 0x80 // Alocation Failed + + +// TX FIFO Ports Register +/* BANK 2 */ +#define TXFIFO_REG SMC_REG(0x0004, 2) +#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty + +// RX FIFO Ports Register +/* BANK 2 */ +#define RXFIFO_REG SMC_REG(0x0005, 2) +#define RXFIFO_REMPTY 0x80 // RX FIFO Empty + +#define FIFO_REG SMC_REG(0x0004, 2) + +// Pointer Register +/* BANK 2 */ +#define PTR_REG SMC_REG(0x0006, 2) +#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area +#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access +#define PTR_READ 0x2000 // When 1 the operation is a read + + +// Data Register +/* BANK 2 */ +#define DATA_REG SMC_REG(0x0008, 2) + + +// Interrupt Status/Acknowledge Register +/* BANK 2 */ +#define INT_REG SMC_REG(0x000C, 2) + + +// Interrupt Mask Register +/* BANK 2 */ +#define IM_REG SMC_REG(0x000D, 2) +#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt +#define IM_ERCV_INT 0x40 // Early Receive Interrupt +#define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section +#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns +#define IM_ALLOC_INT 0x08 // Set when allocation request is completed +#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty +#define IM_TX_INT 0x02 // Transmit Interrupt +#define IM_RCV_INT 0x01 // Receive Interrupt + + +// Multicast Table Registers +/* BANK 3 */ +#define MCAST_REG1 SMC_REG(0x0000, 3) +#define MCAST_REG2 SMC_REG(0x0002, 3) +#define MCAST_REG3 SMC_REG(0x0004, 3) +#define MCAST_REG4 SMC_REG(0x0006, 3) + + +// Management Interface Register (MII) +/* BANK 3 */ +#define MII_REG SMC_REG(0x0008, 3) +#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup +#define MII_MDOE 0x0008 // MII Output Enable +#define MII_MCLK 0x0004 // MII Clock, pin MDCLK +#define MII_MDI 0x0002 // MII Input, pin MDI +#define MII_MDO 0x0001 // MII Output, pin MDO + + +// Revision Register +/* BANK 3 */ +/* ( hi: chip id low: rev # ) */ +#define REV_REG SMC_REG(0x000A, 3) + + +// Early RCV Register +/* BANK 3 */ +/* this is NOT on SMC9192 */ +#define ERCV_REG SMC_REG(0x000C, 3) +#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received +#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask + + +// External Register +/* BANK 7 */ +#define EXT_REG SMC_REG(0x0000, 7) + + +#define CHIP_9192 3 +#define CHIP_9194 4 +#define CHIP_9195 5 +#define CHIP_9196 6 +#define CHIP_91100 7 +#define CHIP_91100FD 8 +#define CHIP_91111FD 9 + +static const char * chip_ids[ 16 ] = { + NULL, NULL, NULL, + /* 3 */ "SMC91C90/91C92", + /* 4 */ "SMC91C94", + /* 5 */ "SMC91C95", + /* 6 */ "SMC91C96", + /* 7 */ "SMC91C100", + /* 8 */ "SMC91C100FD", + /* 9 */ "SMC91C11xFD", + NULL, NULL, NULL, + NULL, NULL, NULL}; + + +/* + . Transmit status bits +*/ +#define TS_SUCCESS 0x0001 +#define TS_LOSTCAR 0x0400 +#define TS_LATCOL 0x0200 +#define TS_16COL 0x0010 + +/* + . Receive status bits +*/ +#define RS_ALGNERR 0x8000 +#define RS_BRODCAST 0x4000 +#define RS_BADCRC 0x2000 +#define RS_ODDFRAME 0x1000 +#define RS_TOOLONG 0x0800 +#define RS_TOOSHORT 0x0400 +#define RS_MULTICAST 0x0001 +#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) + + +// PHY Types +enum { + PHY_LAN83C183 = 1, // LAN91C111 Internal PHY + PHY_LAN83C180 +}; + + +// PHY Register Addresses (LAN91C111 Internal PHY) + +// PHY Control Register +#define PHY_CNTL_REG 0x00 +#define PHY_CNTL_RST 0x8000 // 1=PHY Reset +#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback +#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs +#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation +#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode +#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled +#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate +#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex +#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test + +// PHY Status Register +#define PHY_STAT_REG 0x01 +#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable +#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable +#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable +#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable +#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable +#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble +#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed +#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected +#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable +#define PHY_STAT_LINK 0x0004 // 1=valid link +#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition +#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented + +// PHY Identifier Registers +#define PHY_ID1_REG 0x02 // PHY Identifier 1 +#define PHY_ID2_REG 0x03 // PHY Identifier 2 + +// PHY Auto-Negotiation Advertisement Register +#define PHY_AD_REG 0x04 +#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page +#define PHY_AD_ACK 0x4000 // 1=got link code word from remote +#define PHY_AD_RF 0x2000 // 1=advertise remote fault +#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4 +#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX +#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX +#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX +#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX +#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA + +// PHY Auto-negotiation Remote End Capability Register +#define PHY_RMT_REG 0x05 +// Uses same bit definitions as PHY_AD_REG + +// PHY Configuration Register 1 +#define PHY_CFG1_REG 0x10 +#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled +#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled +#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down +#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler +#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable +#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled +#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) +#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db +#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust +#define PHY_CFG1_TLVL_MASK 0x003C +#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time + + +// PHY Configuration Register 2 +#define PHY_CFG2_REG 0x11 +#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled +#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled +#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) +#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo + +// PHY Status Output (and Interrupt status) Register +#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) +#define PHY_INT_INT 0x8000 // 1=bits have changed since last read +#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected +#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync +#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx +#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx +#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx +#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected +#define PHY_INT_JAB 0x0100 // 1=Jabber detected +#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode +#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex + +// PHY Interrupt/Status Mask Register +#define PHY_MASK_REG 0x13 // Interrupt Mask +// Uses the same bit definitions as PHY_INT_REG + + +/* + * SMC91C96 ethernet config and status registers. + * These are in the "attribute" space. + */ +#define ECOR 0x8000 +#define ECOR_RESET 0x80 +#define ECOR_LEVEL_IRQ 0x40 +#define ECOR_WR_ATTRIB 0x04 +#define ECOR_ENABLE 0x01 + +#define ECSR 0x8002 +#define ECSR_IOIS8 0x20 +#define ECSR_PWRDWN 0x04 +#define ECSR_INT 0x02 + + +/* + * Macros to abstract register access according to the data bus + * capabilities. Please try to use those and not the in/out primitives. + * Note: the following macros do *not* select the bank -- this must + * be done separately as needed in the main code. The SMC_REG() macro + * only uses the bank argument for debugging purposes. + */ + +#if SMC_DEBUG > 0 +#define SMC_REG(reg, bank) \ + ({ \ + int __b = SMC_CURRENT_BANK(); \ + if ((__b & ~0xf0) != (0x3300 | bank)) { \ + printk( "%s: bank reg screwed (0x%04x)\n", \ + CARDNAME, __b ); \ + BUG(); \ + } \ + reg<> 8) +#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF) +#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8) +#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF) +#define SMC_ACK_INT(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \ + SMC_outw( __mask | (x), ioaddr, INT_REG ); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_GET_INT_MASK() (SMC_inw( ioaddr, INT_REG ) >> 8) +#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG ) +#endif + +#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT ) +#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT ) +#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG ) +#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG ) +#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG ) +#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG ) +#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG ) +#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG ) +#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG ) +#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG ) +#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG ) +#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG ) +#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG ) +#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG ) +#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG ) +#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG ) +#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG ) +#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG ) +#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG ) +#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG ) +#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG ) +#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG ) +#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG ) +#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG ) +#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG ) + +#ifndef SMC_GET_MAC_ADDR +#define SMC_GET_MAC_ADDR(addr) \ + do { \ + unsigned int __v; \ + __v = SMC_inw( ioaddr, ADDR0_REG ); \ + addr[0] = __v; addr[1] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR1_REG ); \ + addr[2] = __v; addr[3] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR2_REG ); \ + addr[4] = __v; addr[5] = __v >> 8; \ + } while (0) +#endif + +#define SMC_SET_MAC_ADDR(addr) \ + do { \ + SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \ + SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \ + SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \ + } while (0) + +#define SMC_CLEAR_MCAST() \ + do { \ + SMC_outw( 0, ioaddr, MCAST_REG1 ); \ + SMC_outw( 0, ioaddr, MCAST_REG2 ); \ + SMC_outw( 0, ioaddr, MCAST_REG3 ); \ + SMC_outw( 0, ioaddr, MCAST_REG4 ); \ + } while (0) +#define SMC_SET_MCAST(x) \ + do { \ + unsigned char *mt = (x); \ + SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \ + SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \ + SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \ + SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \ + } while (0) + +#if SMC_CAN_USE_32BIT +/* + * Some setups just can't write 8 or 16 bits reliably when not aligned + * to a 32 bit boundary. I tell you that exists! + * We do the ones that can have their low parts written to 0 here. + */ +#undef SMC_SELECT_BANK +#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<> 16; \ + } while (0) +#else +#define SMC_PUT_PKT_HDR(status, length) \ + do { \ + SMC_outw( status, ioaddr, DATA_REG ); \ + SMC_outw( length, ioaddr, DATA_REG ); \ + } while (0) +#define SMC_GET_PKT_HDR(status, length) \ + do { \ + (status) = SMC_inw( ioaddr, DATA_REG ); \ + (length) = SMC_inw( ioaddr, DATA_REG ); \ + } while (0) +#endif + +#if SMC_CAN_USE_32BIT +#define SMC_PUSH_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if (__len >= 2 && (long)__ptr & 2) { \ + __len -= 2; \ + SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\ + } \ + SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + if (__len & 2) { \ + __ptr += (__len & ~3); \ + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ + } \ + } while (0) +#define SMC_PULL_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if ((long)__ptr & 2) { \ + /* \ + * We want 32bit alignment here. \ + * Since some buses perform a full 32bit \ + * fetch even for 16bit data we can't use \ + * SMC_inw() here. Back both source (on chip \ + * and destination) pointers of 2 bytes. \ + */ \ + (long)__ptr &= ~2; \ + __len += 2; \ + SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ + } \ + __len += 2; \ + SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + } while (0) +#elif SMC_CAN_USE_16BIT +#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 ) +#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 ) +#elif SMC_CAN_USE_8BIT +#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l ) +#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l ) +#endif + +#if ! SMC_CAN_USE_16BIT +#define SMC_outw(x, ioaddr, reg) \ + do { \ + unsigned int __val16 = (x); \ + SMC_outb( __val16, ioaddr, reg ); \ + SMC_outb( __val16 >> 8, ioaddr, reg + 1 ); \ + } while (0) +#define SMC_inw(ioaddr, reg) \ + ({ \ + unsigned int __val16; \ + __val16 = SMC_inb( ioaddr, reg ); \ + __val16 |= SMC_inb( ioaddr, reg + 1 ) << 8; \ + __val16; \ + }) +#endif + + +#endif /* _SMC91X_H_ */ --- linux-2.4.25/drivers/pcmcia/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/Config.in 2004-03-31 17:15:12.000000000 +0200 @@ -45,6 +45,7 @@ if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA + dep_tristate ' PXA250/210 support' CONFIG_PCMCIA_PXA $CONFIG_ARCH_PXA $CONFIG_PCMCIA fi endmenu --- linux-2.4.25/drivers/pcmcia/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/Makefile 2004-03-31 17:15:12.000000000 +0200 @@ -94,6 +94,11 @@ obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o +subdir-$(CONFIG_PCMCIA_PXA) += pxa +ifeq ($(CONFIG_PCMCIA_PXA),y) + obj-y += pxa/pxa_cs.o +endif + include $(TOPDIR)/Rules.make pcmcia_core.o: $(pcmcia_core-objs) --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/Makefile 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,18 @@ +# +# Makefile for the Intel PXA250/210 PCMCIA driver +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +O_TARGET := pxa_cs.o + +obj-y := pxa.o +obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o +obj-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o +obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o +obj-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o + +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/lubbock.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,329 @@ +/* + * linux/drivers/pcmcia/pxa/lubbock.c + * + * Author: George Davis + * Created: Jan 10, 2002 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c + * + * Lubbock PCMCIA specific routines. + * + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* + * I'd really like to move the INTPOL stuff to arch/arm/mach-sa1100/sa1111.c + * ... and maybe even arch/arm/mach-pxa/sa1111.c now too! : ) + */ +#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START)) +#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32)) + +static int lubbock_pcmcia_init(struct pcmcia_init *init){ + int return_val=0; + + /* Set PCMCIA Socket 0 power to standby mode. + */ + PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); + + /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller. + * Note that this is done only after first initializing GPIO_A<3:0> + * output state above to be certain that we drive signals to the same + * state as the pull-downs connected to these lines. The pull-downs are + * req'd to make sure PCMCIA power is OFF until we can get around to + * setting up the GPIO_A<3:0> state and direction. + */ + PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); + + /* Set CF Socket 1 power to standby mode. */ + LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14)); + + INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) | + SA1111_IRQMASK_HI(S1_READY_NINT) | + SA1111_IRQMASK_HI(S0_CD_VALID) | + SA1111_IRQMASK_HI(S1_CD_VALID) | + SA1111_IRQMASK_HI(S0_BVD1_STSCHG) | + SA1111_IRQMASK_HI(S1_BVD1_STSCHG); + +#warning what if a request_irq fails? + return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT, + "Lubbock PCMCIA (0) CD", NULL); + return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT, + "Lubbock CF (1) CD", NULL); + return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT, + "Lubbock PCMCIA (0) BVD1", NULL); + return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT, + "Lubbock CF (1) BVD1", NULL); + + return (return_val<0) ? -1 : 2; +} + +static int lubbock_pcmcia_shutdown(void){ + + free_irq(S0_CD_VALID, NULL); + free_irq(S1_CD_VALID, NULL); + free_irq(S0_BVD1_STSCHG, NULL); + free_irq(S1_BVD1_STSCHG, NULL); + + INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | + SA1111_IRQMASK_HI(S1_CD_VALID) | + SA1111_IRQMASK_HI(S0_BVD1_STSCHG) | + SA1111_IRQMASK_HI(S1_BVD1_STSCHG)); + + return 0; +} + +static int lubbock_pcmcia_socket_state(struct pcmcia_state_array + *state_array){ + unsigned long status; + int return_val=1; + + if(state_array->size<2) return -1; + + memset(state_array->state, 0, + (state_array->size)*sizeof(struct pcmcia_state)); + + status=PCSR; + + state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0; + + state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1; + + state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1; + + state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1; + + state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1; + + state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0; + + state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0; + + state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0; + + state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1; + + state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1; + + state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1; + + state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1; + + state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0; + + state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0; + + return return_val; +} + +static int lubbock_pcmcia_get_irq_info(struct pcmcia_irq_info *info){ + + switch(info->sock){ + case 0: + info->irq=S0_READY_NINT; + break; + + case 1: + info->irq=S1_READY_NINT; + break; + + default: + return -1; + } + + return 0; +} + +static int +lubbock_pcmcia_configure_socket(unsigned int sock, socket_state_t *state) +{ + unsigned long flags, pccr, gpio, misc_wr, status; + int ret=1; + + local_irq_save(flags); + + pccr=PCCR; + gpio=PA_DWR; + misc_wr = LUB_MISC_WR; + + /* Lubbock uses the Maxim MAX1602, with the following connections: + * + * Socket 0 (PCMCIA): + * MAX1602 Lubbock Register + * Pin Signal + * ----- ------- ---------------------- + * A0VPP S0_PWR0 SA-1111 GPIO A<0> + * A1VPP S0_PWR1 SA-1111 GPIO A<1> + * A0VCC S0_PWR2 SA-1111 GPIO A<2> + * A1VCC S0_PWR3 SA-1111 GPIO A<3> + * VX VCC + * VY +3.3V + * 12IN +12V + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + * Socket 1 (CF): + * MAX1602 Lubbock Register + * Pin Signal + * ----- ------- ---------------------- + * A0VPP GND VPP is not connected + * A1VPP GND VPP is not connected + * A0VCC S1_PWR0 MISC_WR<14> + * A1VCC S1_PWR0 MISC_WR<15> + * VX VCC + * VY +3.3V + * 12IN GND VPP is not connected + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + */ + +again: + switch(sock){ + case 0: + + switch(state->Vcc){ + case 0: + pccr = (pccr & ~PCCR_S0_FLT); + gpio &= ~(GPIO_bit(2) | GPIO_bit(3)); + break; + + case 33: + pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN; + gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3); + break; + + case 50: + pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN); + gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2); + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); + ret = -1; + break; + } + + switch(state->Vpp){ + case 0: + gpio &= ~(GPIO_bit(0) | GPIO_bit(1)); + break; + + case 120: + gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1); + break; + + default: + /* REVISIT: I'm not sure about this? Is this correct? + Is it always safe or do we have potential problems + with bogus combinations of Vcc and Vpp settings? */ + if(state->Vpp == state->Vcc) + gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0); + else { + printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp); + ret = -1; + break; + } + } + + pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S0_RST) : (pccr&~PCCR_S0_RST); + + break; + + case 1: + switch(state->Vcc){ + case 0: + pccr = (pccr & ~PCCR_S1_FLT); + misc_wr &= ~((1 << 15) | (1 << 14)); + break; + + case 33: + pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN; + misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14); + gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2); + break; + + case 50: + pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN); + misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14); + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); + ret = -1; + break; + } + + if(state->Vpp!=state->Vcc && state->Vpp!=0){ + printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp); + ret = -1; + break; + } + + pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S1_RST) : (pccr&~PCCR_S1_RST); + + break; + + default: + ret = -1; + } + + if (ret >= 0) { + PCCR = pccr; + LUB_MISC_WR = misc_wr; + PA_DWR = gpio; + } + + if (ret > 0) { + ret = 0; + /* + * HACK ALERT: + * We can't sense the voltage properly on Lubbock before actually + * applying some power to the socket (catch 22). + * Resense the socket Voltage Sense pins after applying socket power. + */ + if (sock == 0) + status = PCSR & (PCSR_S0_VS1 | PCSR_S0_VS2); + else + status = PCSR & (PCSR_S1_VS1 | PCSR_S1_VS2); + + if ((status == (PCSR_S0_VS1 | PCSR_S0_VS2)) && (state->Vcc == 33)) { + /* Switch to 5V, Configure socket 0 with 5V voltage */ + PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); + PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); + state->Vcc = 50; + state->Vpp = 50; + goto again; + } + if ((status == (PCSR_S1_VS1 | PCSR_S1_VS2)) && (state->Vcc == 33)) { + /* Switch to 5V, Configure socket 1 with 5V voltage */ + LUB_MISC_WR &= ~((1 << 15) | (1 << 14)); + state->Vcc = 50; + state->Vpp = 50; + goto again; + } + } + + local_irq_restore(flags); + return ret; +} + +struct pcmcia_low_level lubbock_pcmcia_ops = { + lubbock_pcmcia_init, + lubbock_pcmcia_shutdown, + lubbock_pcmcia_socket_state, + lubbock_pcmcia_get_irq_info, + lubbock_pcmcia_configure_socket +}; --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/pxa.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,1247 @@ +/* + * linux/drivers/pcmcia/pxa/pxa.c + * + * Author: George Davis + * Created: Jan 10, 2002 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Originally based upon linux/drivers/pcmcia/sa1100_generic.c + * + */ + +/*====================================================================== + + Device driver for the PCMCIA control functionality of Intel + PXA250/210 microprocessors. + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is John G. Dorsey + . Portions created by John G. Dorsey are + Copyright (C) 1999 John G. Dorsey. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pxa.h" + +#ifdef PCMCIA_DEBUG +static int pc_debug; +#endif + +MODULE_AUTHOR("George Davis "); +MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA250/210 Socket Controller"); + +/* This structure maintains housekeeping state for each socket, such + * as the last known values of the card detect pins, or the Card Services + * callback value associated with the socket: + */ +static struct pxa_pcmcia_socket +pxa_pcmcia_socket[PXA_PCMCIA_MAX_SOCK]; + +static int pxa_pcmcia_socket_count; + + +/* Returned by the low-level PCMCIA interface: */ +static struct pcmcia_low_level *pcmcia_low_level; + +/* Event poll timer structure */ +static struct timer_list poll_timer; + + +/* Prototypes for routines which are used internally: */ + +static int pxa_pcmcia_driver_init(void); +static void pxa_pcmcia_driver_shutdown(void); +static void pxa_pcmcia_task_handler(void *data); +static void pxa_pcmcia_poll_event(unsigned long data); +static void pxa_pcmcia_interrupt(int irq, void *dev, + struct pt_regs *regs); +static struct tq_struct pxa_pcmcia_task; + +#ifdef CONFIG_PROC_FS +static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos, + int count, int *eof, void *data); +#endif + + +/* Prototypes for operations which are exported to the + * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core: + */ + +static int pxa_pcmcia_init(unsigned int sock); +static int pxa_pcmcia_suspend(unsigned int sock); +static int pxa_pcmcia_register_callback(unsigned int sock, + void (*handler)(void *, + unsigned int), + void *info); +static int pxa_pcmcia_inquire_socket(unsigned int sock, + socket_cap_t *cap); +static int pxa_pcmcia_get_status(unsigned int sock, u_int *value); +static int pxa_pcmcia_get_socket(unsigned int sock, + socket_state_t *state); +static int pxa_pcmcia_set_socket(unsigned int sock, + socket_state_t *state); +static int pxa_pcmcia_get_io_map(unsigned int sock, + struct pccard_io_map *io); +static int pxa_pcmcia_set_io_map(unsigned int sock, + struct pccard_io_map *io); +static int pxa_pcmcia_get_mem_map(unsigned int sock, + struct pccard_mem_map *mem); +static int pxa_pcmcia_set_mem_map(unsigned int sock, + struct pccard_mem_map *mem); +#ifdef CONFIG_PROC_FS +static void pxa_pcmcia_proc_setup(unsigned int sock, + struct proc_dir_entry *base); +#endif + +static struct pccard_operations pxa_pcmcia_operations = { + pxa_pcmcia_init, + pxa_pcmcia_suspend, + pxa_pcmcia_register_callback, + pxa_pcmcia_inquire_socket, + pxa_pcmcia_get_status, + pxa_pcmcia_get_socket, + pxa_pcmcia_set_socket, + pxa_pcmcia_get_io_map, + pxa_pcmcia_set_io_map, + pxa_pcmcia_get_mem_map, + pxa_pcmcia_set_mem_map, +#ifdef CONFIG_PROC_FS + pxa_pcmcia_proc_setup +#endif +}; + +#ifdef CONFIG_CPU_FREQ +/* forward declaration */ +static struct notifier_block pxa_pcmcia_notifier_block; +#endif + + +/* pxa_pcmcia_driver_init() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * + * This routine performs a basic sanity check to ensure that this + * kernel has been built with the appropriate board-specific low-level + * PCMCIA support, performs low-level PCMCIA initialization, registers + * this socket driver with Card Services, and then spawns the daemon + * thread which is the real workhorse of the socket driver. + * + * Please see linux/Documentation/arm/SA1100/PCMCIA for more information + * on the low-level kernel interface. + * + * Returns: 0 on success, -1 on error + */ +static int __init pxa_pcmcia_driver_init(void){ + servinfo_t info; + struct pcmcia_init pcmcia_init; + struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK]; + struct pcmcia_state_array state_array; + unsigned int i, clock; + unsigned long mecr; + + printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE); + + CardServices(GetCardServicesInfo, &info); + + if(info.Revision!=CS_RELEASE_CODE){ + printk(KERN_ERR "Card Services release codes do not match\n"); + return -1; + } + + /* Setup GPIOs for PCMCIA/CF alternate function mode. + * + * It would be nice if set_GPIO_mode included support + * for driving GPIO outputs to default high/low state + * before programming GPIOs as outputs. Setting GPIO + * outputs to default high/low state via GPSR/GPCR + * before defining them as outputs should reduce + * the possibility of glitching outputs during GPIO + * setup. This of course assumes external terminators + * are present to hold GPIOs in a defined state. + * + * In the meantime, setup default state of GPIO + * outputs before we enable them as outputs. + */ + + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | + GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | + GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + set_GPIO_mode(GPIO48_nPOE_MD); + set_GPIO_mode(GPIO49_nPWE_MD); + set_GPIO_mode(GPIO50_nPIOR_MD); + set_GPIO_mode(GPIO51_nPIOW_MD); + set_GPIO_mode(GPIO52_nPCE_1_MD); + set_GPIO_mode(GPIO53_nPCE_2_MD); + set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */ + set_GPIO_mode(GPIO55_nPREG_MD); + set_GPIO_mode(GPIO56_nPWAIT_MD); + set_GPIO_mode(GPIO57_nIOIS16_MD); + + + if(machine_is_lubbock()){ +#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_CSB226) + pcmcia_low_level=&lubbock_pcmcia_ops; +#endif + } else if (machine_is_pxa_idp()) { + pcmcia_low_level=&pxa_idp_pcmcia_ops; + } else if( machine_is_pxa_cerf()){ + pcmcia_low_level=&cerf_pcmcia_ops; + } else if (machine_is_trizeps2()){ +#ifdef CONFIG_ARCH_TRIZEPS2 + pcmcia_low_level=&trizeps2_pcmcia_ops; +#endif + } + + if (!pcmcia_low_level) { + printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n"); + return -ENODEV; + } + + pcmcia_init.handler=pxa_pcmcia_interrupt; + + if((pxa_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){ + printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n"); + return -EIO; + } + + state_array.size=pxa_pcmcia_socket_count; + state_array.state=state; + + /* Configure MECR based on the number of sockets present. */ + if (pxa_pcmcia_socket_count == 2) { + MECR |= GPIO_bit(0); + } else { + MECR &= ~GPIO_bit(0); + } + + if(pcmcia_low_level->socket_state(&state_array)<0){ + printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); + return -EIO; + } + + /* Well, it looks good to go. So we can now enable the PCMCIA + * controller. + */ + MECR |= GPIO_bit(1); + + /* We need to initialize the MCXX registers to default values + * here because we're not guaranteed to see a SetIOMap operation + * at runtime. + */ + + clock = get_lclk_frequency_10khz(); + + for(i=0; ishutdown(); + flush_scheduled_tasks(); + + DEBUG(1, "pxa_cs: shutdown complete\n"); +} + +module_exit(pxa_pcmcia_driver_shutdown); + + +/* pxa_pcmcia_init() + * ^^^^^^^^^^^^^^^^^^^^ + * We perform all of the interesting initialization tasks in + * pxa_pcmcia_driver_init(). + * + * Returns: 0 + */ +static int pxa_pcmcia_init(unsigned int sock){ + + DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock); + + return 0; +} + + +/* pxa_pcmcia_suspend() + * ^^^^^^^^^^^^^^^^^^^^^^^ + * We don't currently perform any actions on a suspend. + * + * Returns: 0 + */ +static int pxa_pcmcia_suspend(unsigned int sock) +{ + socket_state_t st; + int ret; + + DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock); + + st.Vcc = 0; + st.Vpp = 0; + st.flags = SS_RESET; + + ret = pcmcia_low_level->configure_socket(sock, &st); + + if (ret == 0) + pxa_pcmcia_socket[sock].cs_state = dead_socket; + + return ret; +} + + +/* pxa_pcmcia_events() + * ^^^^^^^^^^^^^^^^^^^^^^ + * Helper routine to generate a Card Services event mask based on + * state information obtained from the kernel low-level PCMCIA layer + * in a recent (and previous) sampling. Updates `prev_state'. + * + * Returns: an event mask for the given socket state. + */ +static inline unsigned pxa_pcmcia_events(struct pcmcia_state *state, + struct pcmcia_state *prev_state, + unsigned int mask, + unsigned int flags){ + unsigned int events=0; + + if(state->detect!=prev_state->detect){ + + DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect); + + events|=mask&SS_DETECT; + } + + if(state->ready!=prev_state->ready){ + + DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready); + + events|=mask&((flags&SS_IOCARD)?0:SS_READY); + } + + if(state->bvd1!=prev_state->bvd1){ + + DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1); + + events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD; + } + + if(state->bvd2!=prev_state->bvd2){ + + DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2); + + events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN; + } + + DEBUG(2, "events: %s%s%s%s%s%s\n", + (events==0)?"":"", + (events&SS_DETECT)?"DETECT ":"", + (events&SS_READY)?"READY ":"", + (events&SS_BATDEAD)?"BATDEAD ":"", + (events&SS_BATWARN)?"BATWARN ":"", + (events&SS_STSCHG)?"STSCHG ":""); + + *prev_state=*state; + + return events; + +} /* pxa_pcmcia_events() */ + + +/* pxa_pcmcia_task_handler() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Processes serviceable socket events using the "eventd" thread context. + * + * Event processing (specifically, the invocation of the Card Services event + * callback) occurs in this thread rather than in the actual interrupt + * handler due to the use of scheduling operations in the PCMCIA core. + */ +static void pxa_pcmcia_task_handler(void *data) { + struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK]; + struct pcmcia_state_array state_array; + int i, events, all_events, irq_status; + + DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); + + state_array.size=pxa_pcmcia_socket_count; + state_array.state=state; + + do { + + DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__); + + if((irq_status=pcmcia_low_level->socket_state(&state_array))<0) + printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n"); + + all_events=0; + + if(irq_status>0){ + + for(i=0; i=pxa_pcmcia_socket_count){ + printk(KERN_ERR "pxa_cs: socket %u not configured\n", sock); + return -1; + } + + /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the + * force_low argument to validate_mem() in rsrc_mgr.c -- since in + * general, the mapped * addresses of the PCMCIA memory regions + * will not be within 0xffff, setting force_low would be + * undesirable. + * + * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory + * resource database; we instead pass up physical address ranges + * and allow other parts of Card Services to deal with remapping. + * + * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but + * not 32-bit CardBus devices. + */ + cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD); + + irq_info.sock=sock; + irq_info.irq=-1; + + if(pcmcia_low_level->get_irq_info(&irq_info)<0){ + printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n", + sock); + return -1; + } + + cap->irq_mask=0; + cap->map_size=PAGE_SIZE; + cap->pci_irq=irq_info.irq; + cap->io_offset=pxa_pcmcia_socket[sock].virt_io; + + return 0; + +} /* pxa_pcmcia_inquire_socket() */ + + +/* pxa_pcmcia_get_status() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the get_status() operation for the in-kernel PCMCIA + * service (formerly SS_GetStatus in Card Services). Essentially just + * fills in bits in `status' according to internal driver state or + * the value of the voltage detect chipselect register. + * + * As a debugging note, during card startup, the PCMCIA core issues + * three set_socket() commands in a row the first with RESET deasserted, + * the second with RESET asserted, and the last with RESET deasserted + * again. Following the third set_socket(), a get_status() command will + * be issued. The kernel is looking for the SS_READY flag (see + * setup_socket(), reset_socket(), and unreset_socket() in cs.c). + * + * Returns: 0 + */ +static int pxa_pcmcia_get_status(unsigned int sock, + unsigned int *status){ + struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK]; + struct pcmcia_state_array state_array; + + DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock); + + state_array.size=pxa_pcmcia_socket_count; + state_array.state=state; + + if((pcmcia_low_level->socket_state(&state_array))<0){ + printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); + return -1; + } + + pxa_pcmcia_socket[sock].k_state=state[sock]; + + *status=state[sock].detect?SS_DETECT:0; + + *status|=state[sock].ready?SS_READY:0; + + /* The power status of individual sockets is not available + * explicitly from the hardware, so we just remember the state + * and regurgitate it upon request: + */ + *status|=pxa_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0; + + if(pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD) + *status|=state[sock].bvd1?SS_STSCHG:0; + else { + if(state[sock].bvd1==0) + *status|=SS_BATDEAD; + else if(state[sock].bvd2==0) + *status|=SS_BATWARN; + } + + *status|=state[sock].vs_3v?SS_3VCARD:0; + + *status|=state[sock].vs_Xv?SS_XVCARD:0; + + DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n", + (*status&SS_DETECT)?"DETECT ":"", + (*status&SS_READY)?"READY ":"", + (*status&SS_BATDEAD)?"BATDEAD ":"", + (*status&SS_BATWARN)?"BATWARN ":"", + (*status&SS_POWERON)?"POWERON ":"", + (*status&SS_STSCHG)?"STSCHG ":"", + (*status&SS_3VCARD)?"3VCARD ":"", + (*status&SS_XVCARD)?"XVCARD ":""); + + return 0; + +} /* pxa_pcmcia_get_status() */ + + +/* pxa_pcmcia_get_socket() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the get_socket() operation for the in-kernel PCMCIA + * service (formerly SS_GetSocket in Card Services). Not a very + * exciting routine. + * + * Returns: 0 + */ +static int pxa_pcmcia_get_socket(unsigned int sock, + socket_state_t *state){ + + DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock); + + /* This information was given to us in an earlier call to set_socket(), + * so we're just regurgitating it here: + */ + *state=pxa_pcmcia_socket[sock].cs_state; + + return 0; +} + + +/* pxa_pcmcia_set_socket() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the set_socket() operation for the in-kernel PCMCIA + * service (formerly SS_SetSocket in Card Services). We more or + * less punt all of this work and let the kernel handle the details + * of power configuration, reset, &c. We also record the value of + * `state' in order to regurgitate it to the PCMCIA core later. + * + * Returns: 0 + */ +static int pxa_pcmcia_set_socket(unsigned int sock, + socket_state_t *state){ + + DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock); + + DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n" + "\tVcc %d Vpp %d irq %d\n", + (state->csc_mask==0)?"":"", + (state->csc_mask&SS_DETECT)?"DETECT ":"", + (state->csc_mask&SS_READY)?"READY ":"", + (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"", + (state->csc_mask&SS_BATWARN)?"BATWARN ":"", + (state->csc_mask&SS_STSCHG)?"STSCHG ":"", + (state->flags==0)?"":"", + (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"", + (state->flags&SS_IOCARD)?"IOCARD ":"", + (state->flags&SS_RESET)?"RESET ":"", + (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"", + (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"", + state->Vcc, state->Vpp, state->io_irq); + + if(pcmcia_low_level->configure_socket(sock, state)<0){ + printk(KERN_ERR "Unable to configure socket %u\n", sock); + return -1; + } + + pxa_pcmcia_socket[sock].cs_state=*state; + + return 0; + +} /* pxa_pcmcia_set_socket() */ + + +/* pxa_pcmcia_get_io_map() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the get_io_map() operation for the in-kernel PCMCIA + * service (formerly SS_GetIOMap in Card Services). Just returns an + * I/O map descriptor which was assigned earlier by a set_io_map(). + * + * Returns: 0 on success, -1 if the map index was out of range + */ +static int pxa_pcmcia_get_io_map(unsigned int sock, + struct pccard_io_map *map){ + + DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); + + if(map->map>=MAX_IO_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, + map->map); + return -1; + } + + *map=pxa_pcmcia_socket[sock].io_map[map->map]; + + return 0; +} + + +/* pxa_pcmcia_set_io_map() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the set_io_map() operation for the in-kernel PCMCIA + * service (formerly SS_SetIOMap in Card Services). We configure + * the map speed as requested, but override the address ranges + * supplied by Card Services. + * + * Returns: 0 on success, -1 on error + */ +static int pxa_pcmcia_set_io_map(unsigned int sock, + struct pccard_io_map *map){ + unsigned int clock, speed; + unsigned long mecr, start; + + DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); + + DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n" + "\tflags: %s%s%s%s%s%s%s%s\n", + map->map, map->speed, map->start, map->stop, + (map->flags==0)?"":"", + (map->flags&MAP_ACTIVE)?"ACTIVE ":"", + (map->flags&MAP_16BIT)?"16BIT ":"", + (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", + (map->flags&MAP_0WS)?"0WS ":"", + (map->flags&MAP_WRPROT)?"WRPROT ":"", + (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"", + (map->flags&MAP_PREFETCH)?"PREFETCH ":""); + + if(map->map>=MAX_IO_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, + map->map); + return -1; + } + + if(map->flags&MAP_ACTIVE){ + + speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS; + + clock = get_lclk_frequency_10khz(); + + pxa_pcmcia_socket[sock].speed_io=speed; + + if (sock == 0) { + MCIO0 = ((pxa_mcxx_setup(speed, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(speed, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(speed, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } else { + MCIO1 = ((pxa_mcxx_setup(speed, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(speed, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(speed, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } + + DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", + __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, + MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), + sock, MECR_BSIO_GET(mecr, sock)); + + } + + start=map->start; + + if(map->stop==1) + map->stop=PAGE_SIZE-1; + + map->start=pxa_pcmcia_socket[sock].virt_io; + map->stop=map->start+(map->stop-start); + + pxa_pcmcia_socket[sock].io_map[map->map]=*map; + + return 0; + +} /* pxa_pcmcia_set_io_map() */ + + +/* pxa_pcmcia_get_mem_map() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the get_mem_map() operation for the in-kernel PCMCIA + * service (formerly SS_GetMemMap in Card Services). Just returns a + * memory map descriptor which was assigned earlier by a + * set_mem_map() request. + * + * Returns: 0 on success, -1 if the map index was out of range + */ +static int pxa_pcmcia_get_mem_map(unsigned int sock, + struct pccard_mem_map *map){ + + DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); + + if(map->map>=MAX_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, + map->map); + return -1; + } + + *map=pxa_pcmcia_socket[sock].mem_map[map->map]; + + return 0; +} + + +/* pxa_pcmcia_set_mem_map() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the set_mem_map() operation for the in-kernel PCMCIA + * service (formerly SS_SetMemMap in Card Services). We configure + * the map speed as requested, but override the address ranges + * supplied by Card Services. + * + * Returns: 0 on success, -1 on error + */ +static int pxa_pcmcia_set_mem_map(unsigned int sock, + struct pccard_mem_map *map){ + unsigned int clock, speed; + unsigned long mecr, start; + + DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); + + DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n" + "\tsys_stop %#lx\n\tcard_start %#x\n" + "\tflags: %s%s%s%s%s%s%s%s\n", + map->map, map->speed, map->sys_start, map->sys_stop, + map->card_start, (map->flags==0)?"":"", + (map->flags&MAP_ACTIVE)?"ACTIVE ":"", + (map->flags&MAP_16BIT)?"16BIT ":"", + (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", + (map->flags&MAP_0WS)?"0WS ":"", + (map->flags&MAP_WRPROT)?"WRPROT ":"", + (map->flags&MAP_ATTRIB)?"ATTRIB ":"", + (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); + + if(map->map>=MAX_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, + map->map); + return -1; + } + + if(map->flags&MAP_ACTIVE){ + /* When clients issue RequestMap, the access speed is not always + * properly configured: + */ + if(map->speed > 0) + speed = map->speed; + else + switch(pxa_pcmcia_socket[sock].cs_state.Vcc){ + case 33: + speed = PXA_PCMCIA_3V_MEM_ACCESS; + break; + default: + speed = PXA_PCMCIA_5V_MEM_ACCESS; + } + + clock = get_lclk_frequency_10khz(); + + if(map->flags&MAP_ATTRIB){ + if (sock == 0) { + MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } else { + MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } + pxa_pcmcia_socket[sock].speed_attr=speed; + } else { + if (sock == 0) { + MCMEM0 = ((pxa_mcxx_setup(speed, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(speed, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(speed, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } else { + MCMEM1 = ((pxa_mcxx_setup(speed, clock) + & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) + | ((pxa_mcxx_asst(speed, clock) + & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) + | ((pxa_mcxx_hold(speed, clock) + & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); + } + pxa_pcmcia_socket[sock].speed_mem=speed; + } + DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n", + __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock, + MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), + sock, MECR_BSIO_GET(mecr, sock)); + } + + start=map->sys_start; + + if(map->sys_stop==0) + map->sys_stop=PAGE_SIZE-1; + + map->sys_start=(map->flags & MAP_ATTRIB)?\ + pxa_pcmcia_socket[sock].phys_attr:\ + pxa_pcmcia_socket[sock].phys_mem; + + map->sys_stop=map->sys_start+(map->sys_stop-start); + + pxa_pcmcia_socket[sock].mem_map[map->map]=*map; + + return 0; + +} /* pxa_pcmcia_set_mem_map() */ + + +#if defined(CONFIG_PROC_FS) + +/* pxa_pcmcia_proc_setup() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the proc_setup() operation for the in-kernel PCMCIA + * service (formerly SS_ProcSetup in Card Services). + * + * Returns: 0 on success, -1 on error + */ +static void pxa_pcmcia_proc_setup(unsigned int sock, + struct proc_dir_entry *base){ + struct proc_dir_entry *entry; + + DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock); + + if((entry=create_proc_entry("status", 0, base))==NULL){ + printk(KERN_ERR "Unable to install \"status\" procfs entry\n"); + return; + } + + entry->read_proc=pxa_pcmcia_proc_status; + entry->data=(void *)sock; +} + + +/* pxa_pcmcia_proc_status() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Implements the /proc/bus/pccard/??/status file. + * + * Returns: the number of characters added to the buffer + */ +static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos, + int count, int *eof, void *data){ + char *p=buf; + unsigned int sock=(unsigned int)data; + unsigned int clock = get_lclk_frequency_10khz(); + unsigned long mecr = MECR; + + p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", + pxa_pcmcia_socket[sock].k_state.detect?"detect ":"", + pxa_pcmcia_socket[sock].k_state.ready?"ready ":"", + pxa_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"", + pxa_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"", + pxa_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"", + pxa_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"", + pxa_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":""); + + p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", + pxa_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"", + pxa_pcmcia_socket[sock].k_state.ready?"SS_READY ":"", + pxa_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"", + pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ + "SS_IOCARD ":"", + (pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD && + pxa_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"", + ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && + (pxa_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"", + ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && + (pxa_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"", + pxa_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"", + pxa_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":""); + + p+=sprintf(p, "mask : %s%s%s%s%s\n", + pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\ + "SS_DETECT ":"", + pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\ + "SS_READY ":"", + pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\ + "SS_BATDEAD ":"", + pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\ + "SS_BATWARN ":"", + pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\ + "SS_STSCHG ":""); + + p+=sprintf(p, "cs_flags : %s%s%s%s%s\n", + pxa_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\ + "SS_PWR_AUTO ":"", + pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ + "SS_IOCARD ":"", + pxa_pcmcia_socket[sock].cs_state.flags&SS_RESET?\ + "SS_RESET ":"", + pxa_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\ + "SS_SPKR_ENA ":"", + pxa_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\ + "SS_OUTPUT_ENA ":""); + + p+=sprintf(p, "Vcc : %d\n", pxa_pcmcia_socket[sock].cs_state.Vcc); + + p+=sprintf(p, "Vpp : %d\n", pxa_pcmcia_socket[sock].cs_state.Vpp); + + p+=sprintf(p, "irq : %d\n", pxa_pcmcia_socket[sock].cs_state.io_irq); + + p+=sprintf(p, "I/O : %u (%u)\n", pxa_pcmcia_socket[sock].speed_io, + sock ? + pxa_pcmcia_cmd_time(clock, + ((MCIO1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : + pxa_pcmcia_cmd_time(clock, + ((MCIO0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); + + p+=sprintf(p, "attribute: %u (%u)\n", pxa_pcmcia_socket[sock].speed_attr, + sock ? + pxa_pcmcia_cmd_time(clock, + ((MCATT1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : + pxa_pcmcia_cmd_time(clock, + ((MCATT0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); + + p+=sprintf(p, "common : %u (%u)\n", pxa_pcmcia_socket[sock].speed_mem, + sock ? + pxa_pcmcia_cmd_time(clock, + ((MCMEM1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) : + pxa_pcmcia_cmd_time(clock, + ((MCMEM0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK))); + + return p-buf; +} + +#endif /* defined(CONFIG_PROC_FS) */ + + +#ifdef CONFIG_CPU_FREQ + +/* pxa_pcmcia_update_mecr() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * When pxa_pcmcia_notifier() decides that a MECR adjustment (due + * to a core clock frequency change) is needed, this routine establishes + * new BS_xx values consistent with the clock speed `clock'. + */ +static void pxa_pcmcia_update_mecr(unsigned int clock){ + unsigned int sock; + + for(sock = 0; sock < PXA_PCMCIA_MAX_SOCK; ++sock){ + + // REVISIT: MCXX macros needed here + // MECR_BSIO_SET(mecr, sock, +// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_io, +// clock)); + // MECR_BSA_SET(mecr, sock, +// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_attr, +// clock)); + // MECR_BSM_SET(mecr, sock, +// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_mem, +// clock)); + } +} + +/* pxa_pcmcia_notifier() + * ^^^^^^^^^^^^^^^^^^^^^^^^ + * When changing the processor core clock frequency, it is necessary + * to adjust the MECR timings accordingly. We've recorded the timings + * requested by Card Services, so this is just a matter of finding + * out what our current speed is, and then recomputing the new MECR + * values. + * + * Returns: 0 on success, -1 on error + */ +static int pxa_pcmcia_notifier(struct notifier_block *nb, + unsigned long val, void *data){ + struct cpufreq_info *ci = data; + + switch(val){ + case CPUFREQ_MINMAX: + + break; + + case CPUFREQ_PRECHANGE: + + if(ci->new_freq > ci->old_freq){ + DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n", + __FUNCTION__, + ci->new_freq / 1000, (ci->new_freq / 100) % 10, + ci->old_freq / 1000, (ci->old_freq / 100) % 10); + pxa_pcmcia_update_mecr(ci->new_freq); + } + + break; + + case CPUFREQ_POSTCHANGE: + + if(ci->new_freq < ci->old_freq){ + DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n", + __FUNCTION__, + ci->new_freq / 1000, (ci->new_freq / 100) % 10, + ci->old_freq / 1000, (ci->old_freq / 100) % 10); + pxa_pcmcia_update_mecr(ci->new_freq); + } + + break; + + default: + printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__, + val); + return -1; + + } + + return 0; + +} + +static struct notifier_block pxa_pcmcia_notifier_block = { + notifier_call: pxa_pcmcia_notifier +}; + +#endif + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/pxa.h 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,233 @@ +/* + * linux/drivers/pcmcia/pxa/pxa.h + * + * Author: George Davis + * Created: Jan 10, 2002 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Originally based upon linux/drivers/pcmcia/sa1100_generic.h + * + */ + +/*====================================================================== + + Device driver for the PCMCIA control functionality of Intel + PXA250/210 microprocessors. + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is John G. Dorsey + . Portions created by John G. Dorsey are + Copyright (C) 1999 John G. Dorsey. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#if !defined(_PCMCIA_PXA_H) +# define _PCMCIA_PXA_H + +#include +#include +#include +#include +#include "../cs_internal.h" + +#include + + +/* MECR: Expansion Memory Configuration Register + * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24) + * + * MECR layout is: + * + * FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0> + * + * (This layout is actually true only for the SA-1110; the FASTn bits are + * reserved on the SA-1100.) + */ + +#define MCXX_SETUP_MASK (0x7f) +#define MCXX_ASST_MASK (0x1f) +#define MCXX_HOLD_MASK (0x3f) +#define MCXX_SETUP_SHIFT (0) +#define MCXX_ASST_SHIFT (7) +#define MCXX_HOLD_SHIFT (14) + + +#define MECR_SET(mecr, sock, shift, mask, bs) \ +((mecr)=((mecr)&~(((mask)<<(shift))<<\ + ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\ + (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))) + +#define MECR_GET(mecr, sock, shift, mask) \ +((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\ + (shift))&(mask)) + +#define MECR_BSIO_SET(mecr, sock, bs) \ +MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs)) + +#define MECR_BSIO_GET(mecr, sock) \ +MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK) + +#define MECR_BSA_SET(mecr, sock, bs) \ +MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs)) + +#define MECR_BSA_GET(mecr, sock) \ +MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK) + +#define MECR_BSM_SET(mecr, sock, bs) \ +MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs)) + +#define MECR_BSM_GET(mecr, sock) \ +MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK) + +#define MECR_FAST_SET(mecr, sock, fast) \ +MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast)) + +#define MECR_FAST_GET(mecr, sock) \ +MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK) + + +/* This function implements the BS value calculation for setting the MECR + * using integer arithmetic: + */ +static inline unsigned int pxa_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns, + unsigned int cpu_clock_khz){ + unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000; + return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1); +} + +static inline u_int pxa_mcxx_hold(u_int pcmcia_cycle_ns, + u_int mem_clk_10khz){ + u_int code = pcmcia_cycle_ns * mem_clk_10khz; + return (code / 300000) + ((code % 300000) ? 1 : 0); +} + +static inline u_int pxa_mcxx_asst(u_int pcmcia_cycle_ns, + u_int mem_clk_10khz){ + u_int code = pcmcia_cycle_ns * mem_clk_10khz; + return (code / 300000) + ((code % 300000) ? 1 : 0); +} + +static inline u_int pxa_mcxx_setup(u_int pcmcia_cycle_ns, + u_int mem_clk_10khz){ + u_int code = pcmcia_cycle_ns * mem_clk_10khz; + return (code / 100000) + ((code % 100000) ? 1 : 0) + 1; +} + +/* This function returns the (approxmiate) command assertion period, in + * nanoseconds, for a given CPU clock frequency and MCXX_ASST value: + */ + +static inline u_int pxa_pcmcia_cmd_time(u_int mem_clk_10khz, + u_int pcmcia_mcxx_asst){ + return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz); +} + + +/* SA-1100 PCMCIA Memory and I/O timing + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * The SA-1110 Developer's Manual, section 10.2.5, says the following: + * + * "To calculate the recommended BS_xx value for each address space: + * divide the command width time (the greater of twIOWR and twIORD, + * or the greater of twWE and twOE) by processor cycle time; divide + * by 2; divide again by 3 (number of BCLK's per command assertion); + * round up to the next whole number; and subtract 1." + * + * The PC Card Standard, Release 7, section 4.13.4, says that twIORD + * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has + * a minimum value of 165ns, as well. Section 4.7.2 (describing + * common and attribute memory write timing) says that twWE has a + * minimum value of 150ns for a 250ns cycle time (for 5V operation; + * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V + * operation, also section 4.7.4). Section 4.7.3 says that taOE + * has a maximum value of 150ns for a 300ns cycle time (for 5V + * operation), or 300ns for a 600ns cycle time (for 3.3V operation). + * + * When configuring memory maps, Card Services appears to adopt the policy + * that a memory access time of "0" means "use the default." The default + * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute + * and memory command width time is 150ns; the PCMCIA 3.3V attribute and + * memory command width time is 300ns. + */ + +/* The PXA 250 and PXA 210 Application Processors Developer's Manual + * was used to determine correct PXA_PCMCIA_IO_ACCES time + */ + +#define PXA_PCMCIA_IO_ACCESS (165) + +/* Default PC Card Common Memory timings*/ + +#define PXA_PCMCIA_5V_MEM_ACCESS (250) +#define PXA_PCMCIA_3V_MEM_ACCESS (250) + +/* Atrribute Memory timing - must be constant via PC Card standart*/ + +#define PXA_PCMCIA_ATTR_MEM_ACCESS (300) + + +/* The socket driver actually works nicely in interrupt-driven form, + * so the (relatively infrequent) polling is "just to be sure." + */ +#define PXA_PCMCIA_POLL_PERIOD (2*HZ) + + +/* This structure encapsulates per-socket state which we might need to + * use when responding to a Card Services query of some kind. + */ +struct pxa_pcmcia_socket { + socket_state_t cs_state; + struct pcmcia_state k_state; + unsigned int irq; + void (*handler)(void *, unsigned int); + void *handler_info; + pccard_io_map io_map[MAX_IO_WIN]; + pccard_mem_map mem_map[MAX_WIN]; + ioaddr_t virt_io, phys_attr, phys_mem; + unsigned short speed_io, speed_attr, speed_mem; +}; + + +/* I/O pins replacing memory pins + * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75) + * + * These signals change meaning when going from memory-only to + * memory-or-I/O interface: + */ +#define iostschg bvd1 +#define iospkr bvd2 + + +/* + * Declaration for all implementation specific low_level operations. + */ +extern struct pcmcia_low_level lubbock_pcmcia_ops; +extern struct pcmcia_low_level pxa_idp_pcmcia_ops; +extern struct pcmcia_low_level cerf_pcmcia_ops; +extern struct pcmcia_low_level trizeps2_pcmcia_ops; + +#endif /* !defined(_PCMCIA_PXA_H) */ --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/pxa_idp.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,297 @@ +/* + * linux/drivers/pcmcia/pxa/pxa_idp.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved + * + * Platform specific routines for the Accelent PXA250 IDP, based on those + * first done for the Lubbock. + * + * Version 1.0 2002-05-02 Jeff Sutherland + * + */ + +#include +#include + +#include + +#include +#include +#include +#include + +static int +pxa_idp_pcmcia_init(struct pcmcia_init *init) +{ + int return_val = 0; + + /* Set PCMCIA Socket 0 power to standby mode. + * PXA IDP has dedicated CPLD pins for all this stuff :-) + */ + + /* both slots disabled, reset NOT active */ + IDP_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE; + + IDP_CPLD_PCCARD_PWR = 0; //all power to both slots off + + GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID)) &= + ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID)); + GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID)) &= + ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID)); + + set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID), + GPIO_BOTH_EDGES); + set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID), + GPIO_BOTH_EDGES); + + /* irq's for slots: */ + GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT)) &= + ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT)); + GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT)) &= + ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT)); + + set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT), + GPIO_FALLING_EDGE); + set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT), + GPIO_FALLING_EDGE); + + return_val = + request_irq(PCMCIA_S0_CD_VALID, init->handler, SA_INTERRUPT, + "PXA PCMCIA CD0", NULL); + + if (return_val < 0) + return -1; + + return_val += + request_irq(PCMCIA_S1_CD_VALID, init->handler, SA_INTERRUPT, + "PXA PCMCIA CD1", NULL); + + if (return_val < 0) { + free_irq(PCMCIA_S0_CD_VALID, NULL); + return -1; + } + + return 2; +} + +static int +pxa_idp_pcmcia_shutdown(void) +{ + + free_irq(PCMCIA_S0_CD_VALID, NULL); + free_irq(PCMCIA_S1_CD_VALID, NULL); + + IDP_CPLD_PCCARD_EN = 0x03; //disable slots + udelay(200); + IDP_CPLD_PCCARD_PWR = 0; //shut off all power + + return 0; +} + +static int +pxa_idp_pcmcia_socket_state(struct pcmcia_state_array *state_array) +{ + unsigned long status; + int return_val = 1; + int i; + volatile unsigned long *stat_regs[2] = { &IDP_CPLD_PCCARD0_STATUS, + &IDP_CPLD_PCCARD1_STATUS + }; + + if (state_array->size < 2) + return -1; + + memset(state_array->state, 0, + (state_array->size) * sizeof (struct pcmcia_state)); + + for (i = 0; i < 2; i++) { + + status = *stat_regs[i]; + + /* this one is a gpio */ + state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1; + + state_array->state[i].ready = + ((status & _PCC_IRQ) == 0) ? 0 : 1; + state_array->state[i].bvd1 = (status & PCC_BVD1) ? 0 : 1; + state_array->state[i].bvd2 = (status & PCC_BVD2) ? 0 : 1; + state_array->state[i].wrprot = + (status & _PCC_WRPROT) ? 1 : 0; + state_array->state[i].vs_3v = (status & PCC_VS1) ? 0 : 1; + state_array->state[i].vs_Xv = (status & PCC_VS2) ? 0 : 1; + } + + return return_val; +} + +static int +pxa_idp_pcmcia_get_irq_info(struct pcmcia_irq_info *info) +{ + switch (info->sock) { + case 0: + info->irq = PCMCIA_S0_RDYINT; + break; + + case 1: + info->irq = PCMCIA_S1_RDYINT; + break; + + default: + return -1; + } + + return 0; +} + +static int +pxa_idp_pcmcia_configure_socket(unsigned int sock, socket_state_t *state) +{ + /* The PXA Idp uses the Maxim MAX1602, with the following connections: + * + * Socket 0 (PCMCIA): + * MAX1602 PXA_IDP Register + * Pin Signal IDP_CPLD_PCCARD_PWR: + * ----- ------- ---------------------- + * A0VPP PCC0_PWR0 bit0 + * A1VPP PCC0_PWR1 bit1 + * A0VCC PCC0_PWR2 bit2 + * A1VCC PCC0_PWR3 bit3 + * VX VCC + * VY +3.3V + * 12IN +12V + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + * Socket 1 (PCMCIA): + * MAX1602 PXA_IDP Register + * Pin Signal IDP_CPLD_PCCARD_PWR: + * ----- ------- ---------------------- + * A0VPP PCC1_PWR0 bit4 + * A1VPP PCC1_PWR1 bit5 + * A0VCC PCC1_PWR2 bit6 + * A1VCC PCC1_PWR3 bit7 + * VX VCC + * VY +3.3V + * 12IN +12V + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + */ + + switch (sock) { + case 0: + switch (state->Vcc) { + case 0: + IDP_CPLD_PCCARD_EN |= PCC0_ENABLE; // disable socket + udelay(200); + IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3); + break; + + case 33: + IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3); + IDP_CPLD_PCCARD_PWR |= PCC0_PWR3; + IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE; //turn it on + break; + + case 50: + IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3); + IDP_CPLD_PCCARD_PWR |= PCC0_PWR2; + IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE; + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + return -1; + } + + switch (state->Vpp) { + case 0: + IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1); + break; + + case 120: + IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1); + IDP_CPLD_PCCARD_PWR |= PCC0_PWR1; + break; + + default: + if (state->Vpp == state->Vcc) + IDP_CPLD_PCCARD_PWR = + (IDP_CPLD_PCCARD_PWR & + ~(PCC0_PWR0 | PCC0_PWR1)) | PCC0_PWR0; + else { + printk(KERN_ERR "%s(): unrecognized Vpp %u\n", + __FUNCTION__, state->Vpp); + return -1; + } + } + + IDP_CPLD_PCCARD_EN = + (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC0_RESET) + : (IDP_CPLD_PCCARD_EN & ~PCC0_RESET); + break; + + case 1: + switch (state->Vcc) { + case 0: + IDP_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket + udelay(200); + IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); + break; + + case 33: + IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); + IDP_CPLD_PCCARD_PWR |= PCC1_PWR3; + IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on + break; + + case 50: + IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3); + IDP_CPLD_PCCARD_PWR |= PCC1_PWR2; + IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE; + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + return -1; + } + + switch (state->Vpp) { + case 0: + IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1); + break; + + case 120: + IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1); + IDP_CPLD_PCCARD_PWR |= PCC1_PWR1; + break; + + default: + if (state->Vpp == state->Vcc) + IDP_CPLD_PCCARD_PWR = + (IDP_CPLD_PCCARD_PWR & + ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0; + else { + printk(KERN_ERR "%s(): unrecognized Vpp %u\n", + __FUNCTION__, state->Vpp); + return -1; + } + } + IDP_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC1_RESET) + : (IDP_CPLD_PCCARD_EN & ~PCC1_RESET); + break; + } + return 0; +} + +struct pcmcia_low_level pxa_idp_pcmcia_ops = { + pxa_idp_pcmcia_init, + pxa_idp_pcmcia_shutdown, + pxa_idp_pcmcia_socket_state, + pxa_idp_pcmcia_get_irq_info, + pxa_idp_pcmcia_configure_socket +}; --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/pxa/trizeps2.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,187 @@ +/* + * linux/drivers/pcmcia/pxa/trizeps2.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved + * + * Platform specific routines for the Keith-n-Koep Trizeps-II, based on IDP + * + * Copyright (c) 2003 Teradyne DS, Ltd. + * Port to Trizeps-2 MT6N board by Luc De Cock + * + */ + +#include +#include + +#include + +#include +#include +#include +#include + +static int trizeps2_pcmcia_init(struct pcmcia_init *init) +{ + int return_val = 0; + unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE; + unsigned short val; + + /* reset the PCMCIA controller */ + val = trizeps2_bcr_shadow | BCR_PCMCIA_RESET; + *bcr = val; + udelay(500); + /* un-reset it again */ + trizeps2_bcr_shadow &= ~BCR_PCMCIA_RESET; + /* enable the PCMCIA buffer */ + trizeps2_bcr_shadow &= ~(1 << 5); + *bcr = trizeps2_bcr_shadow; + + GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID)) &= + ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID)); + set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID), + PCMCIA_S_CD_VALID_EDGE); + GPDR(IRQ_TO_GPIO(PCMCIA_S_RDYINT)) &= + ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S_RDYINT)); + set_GPIO_IRQ_edge(IRQ_TO_GPIO(PCMCIA_S_RDYINT), + PCMCIA_S_RDYINT_EDGE); + + return_val = request_irq(PCMCIA_S_CD_VALID, init->handler, SA_INTERRUPT, + "PXA PCMCIA CD", NULL); + if (return_val < 0) { + return -1; + } + /* only 1 slot */ + return 1; +} + +static int trizeps2_pcmcia_shutdown(void) +{ + free_irq(PCMCIA_S_CD_VALID, NULL); + + unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE; + trizeps2_bcr_shadow |= (1 << 5); /* pcmcia buffer off */ + *bcr = trizeps2_bcr_shadow; + trizeps2_bcr_shadow &= 0xFFF0; /* pcmcia control logic grounded */ + *bcr = trizeps2_bcr_shadow; + + return 0; +} + +static int trizeps2_pcmcia_socket_state(struct pcmcia_state_array *state_array) +{ + unsigned long status; + int return_val = 1; + volatile unsigned short *stat_regs[1] = { + &TRIZEPS2_PCCARD_STATUS + }; + + if (state_array->size < 1) + return -1; + + memset(state_array->state, 0, + (state_array->size) * sizeof (struct pcmcia_state)); + + status = *stat_regs[0]; + + /* this one is a gpio */ + state_array->state[0].detect = (PCC_DETECT) ? 0 : 1; + state_array->state[0].ready = (PCC_READY) ? 1 : 0; + state_array->state[0].bvd1 = (status & PCC_BVD1) ? 1 : 0; + state_array->state[0].bvd2 = (status & PCC_BVD2) ? 1 : 0; + state_array->state[0].wrprot = 0; /* r/w all the time */ + state_array->state[0].vs_3v = (status & PCC_VS1) ? 0 : 1; + state_array->state[0].vs_Xv = (status & PCC_VS2) ? 0 : 1; + + return return_val; +} + +static int trizeps2_pcmcia_get_irq_info(struct pcmcia_irq_info *info) +{ + switch (info->sock) { + case 0: + info->irq = PCMCIA_S_RDYINT; + break; + + default: + return -1; + } + + return 0; +} + +static int trizeps2_pcmcia_configure_socket(unsigned int sock, socket_state_t *state) +{ + unsigned short cntr_logic = trizeps2_bcr_shadow & 0xF; + unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE; + + /* configure Vcc and Vpp */ + switch (sock) { + case 0: + switch (state->Vcc) { + case 0: + cntr_logic &= ~(PCC_3V | PCC_5V); + break; + + case 33: + cntr_logic &= ~(PCC_3V | PCC_5V); + cntr_logic |= PCC_3V; + break; + + case 50: + cntr_logic &= ~(PCC_3V | PCC_5V); + cntr_logic |= PCC_5V; + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + return -1; + } + + switch (state->Vpp) { + case 0: + cntr_logic &= ~(PCC_EN0 | PCC_EN1); + break; + + case 120: + cntr_logic &= ~(PCC_EN0 | PCC_EN1); + cntr_logic |= PCC_EN1; + break; + + default: + if (state->Vpp == state->Vcc) { + cntr_logic &= ~(PCC_EN0 | PCC_EN1); + cntr_logic |= PCC_EN0; + } + else { + printk(KERN_ERR "%s(): unrecognized Vpp %u\n", + __FUNCTION__, state->Vpp); + return -1; + } + } + trizeps2_bcr_shadow &= ~(PCC_EN0 | PCC_EN1 | PCC_3V | PCC_5V | + BCR_PCMCIA_RESET); + trizeps2_bcr_shadow |= cntr_logic; + *bcr = trizeps2_bcr_shadow; + /* reset PCMCIA controller if requested */ + trizeps2_bcr_shadow |= + (state->flags & SS_RESET) ? BCR_PCMCIA_RESET : 0; + *bcr = trizeps2_bcr_shadow; + udelay(500); + break; + } + return 0; +} + +struct pcmcia_low_level trizeps2_pcmcia_ops = { + trizeps2_pcmcia_init, + trizeps2_pcmcia_shutdown, + trizeps2_pcmcia_socket_state, + trizeps2_pcmcia_get_irq_info, + trizeps2_pcmcia_configure_socket +}; + --- linux-2.4.25/drivers/pcmcia/sa1100_cerf.c~2.4.25-vrs2-pxa1.patch 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.c 2004-03-31 17:15:12.000000000 +0200 @@ -7,15 +7,25 @@ */ #include #include +#include #include #include -#include "sa1100_generic.h" -#ifdef CONFIG_SA1100_CERF_CPLD -#define CERF_SOCKET 0 +#include +#include +#include "sa1100_cerf.h" + +/* + * Set this to zero to remove all the debug statements via + * dead code elimination + */ +//#define DEBUGGING 1 + +#if DEBUGGING +static unsigned int pcmcia_debug = DEBUGGING; #else -#define CERF_SOCKET 1 +#define pcmcia_debug 0 /* gcc will remove all the debug code for us */ #endif static struct irqs { @@ -23,122 +33,178 @@ unsigned int gpio; const char *str; } irqs[] = { - { IRQ_GPIO_CF_CD, GPIO_CF_CD, "CF_CD" }, - { IRQ_GPIO_CF_BVD2, GPIO_CF_BVD2, "CF_BVD2" }, - { IRQ_GPIO_CF_BVD1, GPIO_CF_BVD1, "CF_BVD1" } + { PCMCIA_IRQ_CF_CD, PCMCIA_GPIO_CF_CD_EDGE, "CF_CD" }, + { PCMCIA_IRQ_CF_BVD2, PCMCIA_GPIO_CF_BVD2_EDGE, "CF_BVD2" }, + { PCMCIA_IRQ_CF_BVD1, PCMCIA_GPIO_CF_BVD1_EDGE, "CF_BVD1" } }; +static void cerf_pcmcia_reset( void) +{ + int i; + + // Make sure SKTSEL is 0 (single slot) + set_GPIO_mode(54 | GPIO_OUT); + GPCR1 = GPIO_bit(54); + set_GPIO_mode(GPIO54_pSKTSEL_MD); + + PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK; + mdelay(300); + + PCMCIA_GPSR = PCMCIA_GPIO_CF_RESET_MASK; + udelay(20); + + PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK; + mdelay(50); + + for( i=0; i<10; i++) + { + if( cerf_pcmcia_level_ready()) break; + mdelay(100); + } +} + static int cerf_pcmcia_init(struct pcmcia_init *init) { - int i, res; + int i, res; - set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE ); + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_init: enter\n"); - for (i = 0; i < ARRAY_SIZE(irqs); i++) { - set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES); - res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT, - irqs[i].str, NULL); - if (res) - goto irq_err; - } + cerf_pcmcia_set_gpio_direction(); - return 2; + set_GPIO_IRQ_edge( PCMCIA_GPIO_CF_IRQ_EDGE, GPIO_FALLING_EDGE ); - irq_err: - printk(KERN_ERR "%s: Request for IRQ%d failed\n", __FUNCTION__, irqs[i].irq); + for (i = 0; i < ARRAY_SIZE(irqs); i++) { - while (i--) - free_irq(irqs[i].irq, NULL); + set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES); - return -1; + res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT, + irqs[i].str, NULL); + if (res) + goto irq_err; + } + + printk( KERN_INFO "PCMCIA for Cerf: OK\n"); + + return CERF_SOCKET+1; /* last socket used +1 */ + +irq_err: + printk(KERN_ERR "%s: Request for IRQ%d failed\n", + __FUNCTION__, irqs[i].irq); + + while (i--) + free_irq(irqs[i].irq, NULL); + + return -1; } static int cerf_pcmcia_shutdown(void) { - int i; + int i; + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_shutdown: enter\n"); - for (i = 0; i < ARRAY_SIZE(irqs); i++) - free_irq(irqs[i].irq, NULL); + for (i = 0; i < ARRAY_SIZE(irqs); i++) + free_irq(irqs[i].irq, NULL); - return 0; + return 0; } -static int cerf_pcmcia_socket_state(struct pcmcia_state_array - *state_array){ - unsigned long levels; - int i = CERF_SOCKET; +static int cerf_pcmcia_socket_state(struct pcmcia_state_array *state_array) +{ + int i = CERF_SOCKET; - if(state_array->size<2) return -1; + if( pcmcia_debug > 3) + printk( KERN_INFO "cerf_pcmcia_socket_state: i=%d, size=%d\n", + i, state_array->size); - levels=GPLR; + memset(state_array->state, 0, + (state_array->size)*sizeof(struct pcmcia_state)); - state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0; - state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0; - state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0; - state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0; - state_array->state[i].wrprot=0; - state_array->state[i].vs_3v=1; - state_array->state[i].vs_Xv=0; + state_array->state[i].detect = cerf_pcmcia_level_detect(); + state_array->state[i].ready = cerf_pcmcia_level_ready(); + state_array->state[i].bvd1 = cerf_pcmcia_level_bvd1(); + state_array->state[i].bvd2 = cerf_pcmcia_level_bvd2(); + state_array->state[i].wrprot=0; + state_array->state[i].vs_3v=1; + state_array->state[i].vs_Xv=0; - return 1; + if( pcmcia_debug > 3) + printk( KERN_INFO "cerf_pcmcia_socket_state: " + "detect=%d ready=%d bvd1=%d bvd2=%d\n", + state_array->state[i].detect, + state_array->state[i].ready, + state_array->state[i].bvd1, + state_array->state[i].bvd2); + + return 1; } static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){ - if(info->sock>1) return -1; + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_get_irq_info: " + "sock=%d\n", info->sock); - if (info->sock == CERF_SOCKET) - info->irq=IRQ_GPIO_CF_IRQ; + if(info->sock>1) return -1; - return 0; + if (info->sock == CERF_SOCKET) + info->irq=PCMCIA_IRQ_CF_IRQ; + + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_get_irq_info: irq=%d\n",info->irq); + + return 0; } -static int cerf_pcmcia_configure_socket(const struct pcmcia_configure - *configure) +static int cerf_pcmcia_configure_socket( unsigned int sock, socket_state_t *state) { - if(configure->sock>1) - return -1; + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_configure_socket:" + "sock=%d vcc=%d flags=%x\n", + sock, state->Vcc, state->flags); - if (configure->sock != CERF_SOCKET) - return 0; + if(sock>1) + return -1; - switch(configure->vcc){ - case 0: - break; + if (sock != CERF_SOCKET) + return 0; - case 50: - case 33: -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_PWR_SHUTDOWN; + switch(state->Vcc){ + case 0: + break; + + case 50: + case 33: +#if defined(CONFIG_SA1100_CERF_CPLD) + PCMCIA_GPDR |= PCMCIA_PWR_SHUTDOWN; + PCMCIA_GPCR |= PCMCIA_PWR_SHUTDOWN; #endif - break; + /* voltage selected automatically */ + break; - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, - configure->vcc); - return -1; - } + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + return -1; + } - if(configure->reset) - { -#ifdef CONFIG_SA1100_CERF_CPLD - GPSR = GPIO_CF_RESET; -#endif - } - else - { -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_CF_RESET; -#endif - } + if(state->flags&SS_RESET) + { + cerf_pcmcia_reset(); + } - return 0; + return 0; } +#ifdef CONFIG_SA1100_CERF static int cerf_pcmcia_socket_init(int sock) { int i; + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_socket_init: sock=%d\n",sock); + if (sock == CERF_SOCKET) for (i = 0; i < ARRAY_SIZE(irqs); i++) set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES); @@ -150,21 +216,26 @@ { int i; + if( pcmcia_debug) + printk( KERN_INFO "cerf_pcmcia_socket_suspend: sock=%d\n",sock); + if (sock == CERF_SOCKET) for (i = 0; i < ARRAY_SIZE(irqs); i++) set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES); return 0; } +#endif struct pcmcia_low_level cerf_pcmcia_ops = { - init: cerf_pcmcia_init, - shutdown: cerf_pcmcia_shutdown, - socket_state: cerf_pcmcia_socket_state, - get_irq_info: cerf_pcmcia_get_irq_info, - configure_socket: cerf_pcmcia_configure_socket, +init: cerf_pcmcia_init, +shutdown: cerf_pcmcia_shutdown, +socket_state: cerf_pcmcia_socket_state, +get_irq_info: cerf_pcmcia_get_irq_info, +configure_socket: cerf_pcmcia_configure_socket, - socket_init: cerf_pcmcia_socket_init, - socket_suspend: cerf_pcmcia_socket_suspend, +#ifdef CONFIG_SA1100_CERF +socket_init: cerf_pcmcia_socket_init, +socket_suspend: cerf_pcmcia_socket_suspend, +#endif }; - --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.h 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,138 @@ +/* + * drivers/pcmcia/cerf.h + * + * PCMCIA implementation routines for CerfBoard + * Based off the Assabet. + * + */ +#ifndef _LINUX_PCMCIA_CERF_H +#define _LINUX_PCMCIA_CERF_H + +#include +#include +#include +#include + +#ifdef CONFIG_PXA_CERF /* PXA */ + +#define PCMCIA_GPCR GPCR0 +#define PCMCIA_GPSR GPSR0 + +#define PCMCIA_GPIO_CF_CD 14 +#define PCMCIA_GPIO_CF_IRQ 13 +#define PCMCIA_GPIO_CF_RESET 12 +#ifdef CONFIG_PXA_CERF_PDA +# define PCMCIA_GPIO_CF_BVD1 11 +# define PCMCIA_GPIO_CF_BVD2 10 +#elif defined( CONFIG_PXA_CERF_BOARD) +# define PCMCIA_GPIO_CF_BVD1 32 +# define PCMCIA_GPIO_CF_BVD2 10 +#endif + +#define PCMCIA_GPIO_CF_CD_MASK (GPIO_bit(PCMCIA_GPIO_CF_CD)) +#define PCMCIA_GPIO_CF_IRQ_MASK (GPIO_bit(PCMCIA_GPIO_CF_IRQ)) +#define PCMCIA_GPIO_CF_RESET_MASK (GPIO_bit(PCMCIA_GPIO_CF_RESET)) +#define PCMCIA_GPIO_CF_BVD1_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD1)) +#define PCMCIA_GPIO_CF_BVD2_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD2)) + +#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD +#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ +#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET +#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1 +#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2 + +#define PCMCIA_IRQ_CF_CD IRQ_GPIO(PCMCIA_GPIO_CF_CD) +#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO(PCMCIA_GPIO_CF_IRQ) +#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO(PCMCIA_GPIO_CF_BVD1) +#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO(PCMCIA_GPIO_CF_BVD2) + +#define PCMCIA_PWR_SHUTDOWN 0 /* not needed */ +#define CERF_SOCKET 0 + +inline void cerf_pcmcia_set_gpio_direction(void) +{ + GPDR(PCMCIA_GPIO_CF_CD) &= ~(PCMCIA_GPIO_CF_CD_MASK); + GPDR(PCMCIA_GPIO_CF_BVD1) &= ~(PCMCIA_GPIO_CF_BVD1_MASK); + GPDR(PCMCIA_GPIO_CF_BVD2) &= ~(PCMCIA_GPIO_CF_BVD2_MASK); + GPDR(PCMCIA_GPIO_CF_IRQ) &= ~(PCMCIA_GPIO_CF_IRQ_MASK); + GPDR(PCMCIA_GPIO_CF_RESET)|= (PCMCIA_GPIO_CF_RESET_MASK); +} + +inline int cerf_pcmcia_level_detect( void) +{ + return ((GPLR(PCMCIA_GPIO_CF_CD)&PCMCIA_GPIO_CF_CD_MASK)==0)?1:0; +} +inline int cerf_pcmcia_level_ready( void) +{ + return (GPLR(PCMCIA_GPIO_CF_IRQ)&PCMCIA_GPIO_CF_IRQ_MASK)?1:0; +} +inline int cerf_pcmcia_level_bvd1( void) +{ + return (GPLR(PCMCIA_GPIO_CF_BVD1)&PCMCIA_GPIO_CF_BVD1_MASK)?1:0; +} +inline int cerf_pcmcia_level_bvd2( void) +{ + return (GPLR(PCMCIA_GPIO_CF_BVD2)&PCMCIA_GPIO_CF_BVD2_MASK)?1:0; +} + +#elif defined(CONFIG_SA1100_CERF) /* SA1100 */ + +#define PCMCIA_GPDR GPDR +#define PCMCIA_GPCR GPCR +#define PCMCIA_GPSR GPSR +#define PCMCIA_GPLR GPLR + +#define PCMCIA_GPIO_CF_CD_MASK GPIO_CF_CD +#define PCMCIA_GPIO_CF_IRQ_MASK GPIO_CF_IRQ +#define PCMCIA_GPIO_CF_RESET_MASK GPIO_CF_RESET +#define PCMCIA_GPIO_CF_BVD1_MASK GPIO_CF_BVD1 +#define PCMCIA_GPIO_CF_BVD2_MASK GPIO_CF_BVD2 + +#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD_MASK +#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ_MASK +#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET_MASK +#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1_MASK +#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2_MASK + +#define PCMCIA_IRQ_CF_CD IRQ_GPIO_CF_CD +#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO_CF_IRQ +#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO_CF_BVD1 +#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO_CF_BVD2 + +#define PCMCIA_PWR_SHUTDOWN GPIO_PWR_SHUTDOWN + +#ifdef CONFIG_SA1100_CERF_CPLD +#define CERF_SOCKET 0 +#else +#define CERF_SOCKET 1 +#endif + +inline void cerf_pcmcia_set_gpio_direction(void) +{ + PCMCIA_GPDR &= ~(PCMCIA_GPIO_CF_CD_MASK | + PCMCIA_GPIO_CF_BVD1_MASK | + PCMCIA_GPIO_CF_BVD2_MASK | + PCMCIA_GPIO_CF_IRQ_MASK); + PCMCIA_GPDR |= PCMCIA_GPIO_CF_RESET_MASK; +} + +inline int cerf_pcmcia_level_detect( void) +{ + return ((PCMCIA_GPLR & PCMCIA_GPIO_CF_CD_MASK)==0)?1:0; +} +inline int cerf_pcmcia_level_ready( void) +{ + return (PCMCIA_GPLR & PCMCIA_GPIO_CF_IRQ_MASK)?1:0; +} +inline int cerf_pcmcia_level_bvd1( void) +{ + return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD1_MASK)?1:0; +} +inline int cerf_pcmcia_level_bvd2( void) +{ + return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD2_MASK)?1:0; +} + +#endif + +#endif --- linux-2.4.25/drivers/sound/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/sound/Config.in 2004-03-31 17:15:12.000000000 +0200 @@ -239,6 +239,7 @@ dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS fi dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER + dep_tristate ' Intel PXA250/210 AC97 audio' CONFIG_SOUND_PXA_AC97 $CONFIG_ARCH_PXA $CONFIG_SOUND fi dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C --- linux-2.4.25/drivers/sound/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/sound/Makefile 2004-03-31 17:15:12.000000000 +0200 @@ -11,7 +11,7 @@ msnd.o opl3.o sb_common.o sequencer_syms.o \ sound_core.o sound_syms.o uart401.o \ nm256_audio.o ac97.o ac97_codec.o aci.o \ - sa1100-audio.o + sa1100-audio.o pxa-audio.o pxa-ac97.o # Each configuration option enables a list of files. @@ -85,6 +85,7 @@ obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o +obj-$(CONFIG_SOUND_PXA_AC97)+= pxa-ac97.o pxa-audio.o ac97_codec.o obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o --- linux-2.4.25/drivers/sound/ac97_codec.c~2.4.25-vrs2-pxa1.patch 2003-11-28 19:26:20.000000000 +0100 +++ linux-2.4.25/drivers/sound/ac97_codec.c 2004-03-31 17:15:12.000000000 +0200 @@ -155,6 +155,7 @@ {0x45838308, "ESS Allegro ES1988", &null_ops}, {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */ {0x4e534331, "National Semiconductor LM4549", &null_ops}, + {0x50534304, "Philips UCB1400", &default_ops}, {0x53494c22, "Silicon Laboratory Si3036", &null_ops}, {0x53494c23, "Silicon Laboratory Si3038", &null_ops}, {0x545200FF, "TriTech TR?????", &tritech_m_ops}, --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/sound/pxa-ac97.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,370 @@ +/* + * linux/drivers/sound/pxa-ac97.c -- AC97 interface for the Cotula chip + * + * Author: Nicolas Pitre + * Created: Aug 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * AC97 GPIO Changes:- + * In order to read/write codec GPIO bits using AC97 link slot 12, + * all IO to AC97_GPIO_STATUS must be via the Xscale modem codec + * address space. + * Liam Girdwood + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pxa-audio.h" + +static struct completion CAR_completion; +static int waitingForMask; +static DECLARE_MUTEX(CAR_mutex); + +static u16 pxa_ac97_read(struct ac97_codec *codec, u8 reg) +{ + u16 val = -1; + + down(&CAR_mutex); + if (!(CAR & CAR_CAIP)) { + volatile u32 *reg_addr; + + // if we are reading the GPIO status then this is cached + // in hardware so we don't need to read over the link. + if (reg == AC97_GPIO_STATUS) { + reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1); + val = *reg_addr; + return val; + } + + reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1); + + waitingForMask=GSR_SDONE; + + init_completion(&CAR_completion); + (void)*reg_addr; //start read access across the ac97 link + wait_for_completion(&CAR_completion); + + if (GSR & GSR_RDCS) { + GSR |= GSR_RDCS; //write a 1 to clear + printk(KERN_CRIT __FUNCTION__": read codec register timeout.\n"); + } + + init_completion(&CAR_completion); + val = *reg_addr; //valid data now but we've just started another cycle... + wait_for_completion(&CAR_completion); + + } else { + printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n"); + } + up(&CAR_mutex); + //printk("%s(0x%02x) = 0x%04x\n", __FUNCTION__, reg, val); + return val; +} + +static void pxa_ac97_write(struct ac97_codec *codec, u8 reg, u16 val) +{ + down(&CAR_mutex); + if (!(CAR & CAR_CAIP)) { + volatile u32 *reg_addr; + + // if we are writing to the codec GPIO using slot 12 + // then we have to write to the modem register space + if (reg == AC97_GPIO_STATUS) { + reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1); + *reg_addr = val; + return; + } + + reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1); + + waitingForMask=GSR_CDONE; + init_completion(&CAR_completion); + *reg_addr = val; + wait_for_completion(&CAR_completion); + } else { + printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n"); + } + up(&CAR_mutex); + //printk("%s(0x%02x, 0x%04x)\n", __FUNCTION__, reg, val); +} + +static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + int gsr = GSR; + GSR = gsr & (GSR_SDONE|GSR_CDONE); //write a 1 to clear + if (gsr & waitingForMask) + { + complete(&CAR_completion); + } +} + +static struct ac97_codec pxa_ac97_codec = { + codec_read: pxa_ac97_read, + codec_write: pxa_ac97_write, +}; + +static DECLARE_MUTEX(pxa_ac97_mutex); +static int pxa_ac97_refcount; + +int pxa_ac97_get(struct ac97_codec **codec) +{ + int ret; + + *codec = NULL; + down(&pxa_ac97_mutex); + + if (!pxa_ac97_refcount) { + ret = request_irq(IRQ_AC97, pxa_ac97_irq, 0, "AC97", NULL); + if (ret) + return ret; + + CKEN |= CKEN2_AC97; + set_GPIO_mode(GPIO31_SYNC_AC97_MD); + set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD); + set_GPIO_mode(GPIO28_BITCLK_AC97_MD); + set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD); + + GCR = 0; + udelay(10); + GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE; + while (!(GSR & GSR_PCR)) { + schedule(); + } + + ret = ac97_probe_codec(&pxa_ac97_codec); + if (ret != 1) { + free_irq(IRQ_AC97, NULL); + GCR = GCR_ACLINK_OFF; + CKEN &= ~CKEN2_AC97; + return ret; + } + + // need little hack for UCB1400 (should be moved elsewhere) + pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1); + //pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7); + pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050); + pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030); + } + + pxa_ac97_refcount++; + up(&pxa_ac97_mutex); + *codec = &pxa_ac97_codec; + return 0; +} + +void pxa_ac97_put(void) +{ + down(&pxa_ac97_mutex); + pxa_ac97_refcount--; + if (!pxa_ac97_refcount) { + GCR = GCR_ACLINK_OFF; + CKEN &= ~CKEN2_AC97; + free_irq(IRQ_AC97, NULL); + } + up(&pxa_ac97_mutex); +} + +EXPORT_SYMBOL(pxa_ac97_get); +EXPORT_SYMBOL(pxa_ac97_put); + + +/* + * Audio Mixer stuff + */ + +static audio_state_t ac97_audio_state; +static audio_stream_t ac97_audio_in; + +static int mixer_ioctl( struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret, val; + + ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg); + if (ret) + return ret; + + /* We must snoop for some commands to provide our own extra processing */ + switch (cmd) { + case SOUND_MIXER_WRITE_RECSRC: + /* + * According to the PXA250 spec, mic-in should use different + * DRCMR and different AC97 FIFO. + * Unfortunately current UCB1400 versions (up to ver 2A) don't + * produce slot 6 for the audio input frame, therefore the PXA + * AC97 mic-in FIFO is always starved. + */ +#if 0 + ret = get_user(val, (int *)arg); + if (ret) + return ret; + pxa_audio_clear_buf(&ac97_audio_in); + *ac97_audio_in.drcmr = 0; + if (val & (1 << SOUND_MIXER_MIC)) { + ac97_audio_in.dcmd = DCMD_RXMCDR; + ac97_audio_in.drcmr = &DRCMRRXMCDR; + ac97_audio_in.dev_addr = __PREG(MCDR); + } else { + ac97_audio_in.dcmd = DCMD_RXPCDR; + ac97_audio_in.drcmr = &DRCMRRXPCDR; + ac97_audio_in.dev_addr = __PREG(PCDR); + } + if (ac97_audio_state.rd_ref) + *ac97_audio_in.drcmr = + ac97_audio_in.dma_ch | DRCMR_MAPVLD; +#endif + break; + } + return 0; +} + +static struct file_operations mixer_fops = { + ioctl: mixer_ioctl, + llseek: no_llseek, + owner: THIS_MODULE +}; + +/* + * AC97 codec ioctls + */ + +static int codec_adc_rate = 48000; +static int codec_dac_rate = 48000; + +static int ac97_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret; + long val; + + switch(cmd) { + case SNDCTL_DSP_STEREO: + ret = get_user(val, (int *) arg); + if (ret) + return ret; + /* FIXME: do we support mono? */ + ret = (val == 0) ? -EINVAL : 1; + return put_user(ret, (int *) arg); + + case SNDCTL_DSP_CHANNELS: + case SOUND_PCM_READ_CHANNELS: + /* FIXME: do we support mono? */ + return put_user(2, (long *) arg); + + case SNDCTL_DSP_SPEED: + ret = get_user(val, (long *) arg); + if (ret) + return ret; + if (file->f_mode & FMODE_READ) + codec_adc_rate = ac97_set_adc_rate(&pxa_ac97_codec, val); + if (file->f_mode & FMODE_WRITE) + codec_dac_rate = ac97_set_dac_rate(&pxa_ac97_codec, val); + /* fall through */ + + case SOUND_PCM_READ_RATE: + if (file->f_mode & FMODE_READ) + val = codec_adc_rate; + if (file->f_mode & FMODE_WRITE) + val = codec_dac_rate; + return put_user(val, (long *) arg); + + case SNDCTL_DSP_SETFMT: + case SNDCTL_DSP_GETFMTS: + /* FIXME: can we do other fmts? */ + return put_user(AFMT_S16_LE, (long *) arg); + + default: + /* Maybe this is meant for the mixer (As per OSS Docs) */ + return mixer_ioctl(inode, file, cmd, arg); + } + return 0; +} + + +/* + * Audio stuff + */ + +static audio_stream_t ac97_audio_out = { + name: "AC97 audio out", + dcmd: DCMD_TXPCDR, + drcmr: &DRCMRTXPCDR, + dev_addr: __PREG(PCDR), +}; + +static audio_stream_t ac97_audio_in = { + name: "AC97 audio in", + dcmd: DCMD_RXPCDR, + drcmr: &DRCMRRXPCDR, + dev_addr: __PREG(PCDR), +}; + +static audio_state_t ac97_audio_state = { + output_stream: &ac97_audio_out, + input_stream: &ac97_audio_in, + client_ioctl: ac97_ioctl, + sem: __MUTEX_INITIALIZER(ac97_audio_state.sem), +}; + +static int ac97_audio_open(struct inode *inode, struct file *file) +{ + return pxa_audio_attach(inode, file, &ac97_audio_state); +} + +/* + * Missing fields of this structure will be patched with the call + * to pxa_audio_attach(). + */ + +static struct file_operations ac97_audio_fops = { + open: ac97_audio_open, + owner: THIS_MODULE +}; + + +static int __init pxa_ac97_init(void) +{ + int ret; + struct ac97_codec *dummy; + + ret = pxa_ac97_get(&dummy); + if (ret) + return ret; + + ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1); + pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1); + + return 0; +} + +static void __exit pxa_ac97_exit(void) +{ + unregister_sound_dsp(ac97_audio_state.dev_dsp); + unregister_sound_mixer(pxa_ac97_codec.dev_mixer); + pxa_ac97_put(); +} + + +module_init(pxa_ac97_init); +module_exit(pxa_ac97_exit); + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/sound/pxa-audio.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,853 @@ +/* + * linux/drivers/sound/pxa-audio.c -- audio interface for the Cotula chip + * + * Author: Nicolas Pitre + * Created: Aug 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pxa-audio.h" + + +#define AUDIO_NBFRAGS_DEFAULT 8 +#define AUDIO_FRAGSIZE_DEFAULT 8192 + +#define MAX_DMA_SIZE 4096 +#define DMA_DESC_SIZE sizeof(pxa_dma_desc) + + +/* + * This function frees all buffers + */ +#define audio_clear_buf pxa_audio_clear_buf + +void pxa_audio_clear_buf(audio_stream_t * s) +{ + DECLARE_WAITQUEUE(wait, current); + int frag; + + if (!s->buffers) + return; + + /* Ensure DMA isn't running */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&s->stop_wq, &wait); + DCSR(s->dma_ch) = DCSR_STOPIRQEN; + schedule(); + remove_wait_queue(&s->stop_wq, &wait); + + /* free DMA buffers */ + for (frag = 0; frag < s->nbfrags; frag++) { + audio_buf_t *b = &s->buffers[frag]; + if (!b->master) + continue; + consistent_free(b->data, b->master, b->dma_desc->dsadr); + } + + /* free descriptor ring */ + if (s->buffers->dma_desc) + consistent_free(s->buffers->dma_desc, + s->nbfrags * s->descs_per_frag * DMA_DESC_SIZE, + s->dma_desc_phys); + + /* free buffer structure array */ + kfree(s->buffers); + s->buffers = NULL; +} + +/* + * This function allocates the DMA descriptor array and buffer data space + * according to the current number of fragments and fragment size. + */ +static int audio_setup_buf(audio_stream_t * s) +{ + pxa_dma_desc *dma_desc; + dma_addr_t dma_desc_phys; + int nb_desc, frag, i, buf_size = 0; + char *dma_buf = NULL; + dma_addr_t dma_buf_phys = 0; + + if (s->buffers) + return -EBUSY; + + /* Our buffer structure array */ + s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL); + if (!s->buffers) + goto err; + memzero(s->buffers, sizeof(audio_buf_t) * s->nbfrags); + + /* + * Our DMA descriptor array: + * for Each fragment we have one checkpoint descriptor plus one + * descriptor per MAX_DMA_SIZE byte data blocks. + */ + nb_desc = (1 + (s->fragsize + MAX_DMA_SIZE - 1)/MAX_DMA_SIZE) * s->nbfrags; + dma_desc = consistent_alloc(GFP_KERNEL, + nb_desc * DMA_DESC_SIZE, + &dma_desc_phys, + 0); + if (!dma_desc) + goto err; + s->descs_per_frag = nb_desc / s->nbfrags; + s->buffers->dma_desc = dma_desc; + s->dma_desc_phys = dma_desc_phys; + for (i = 0; i < nb_desc - 1; i++) + dma_desc[i].ddadr = dma_desc_phys + (i + 1) * DMA_DESC_SIZE; + dma_desc[i].ddadr = dma_desc_phys; + + /* Our actual DMA buffers */ + for (frag = 0; frag < s->nbfrags; frag++) { + audio_buf_t *b = &s->buffers[frag]; + + /* + * Let's allocate non-cached memory for DMA buffers. + * We try to allocate all memory at once. + * If this fails (a common reason is memory fragmentation), + * then we'll try allocating smaller buffers. + */ + if (!buf_size) { + buf_size = (s->nbfrags - frag) * s->fragsize; + do { + dma_buf = consistent_alloc(GFP_KERNEL, + buf_size, + &dma_buf_phys, + 0); + if (!dma_buf) + buf_size -= s->fragsize; + } while (!dma_buf && buf_size); + if (!dma_buf) + goto err; + b->master = buf_size; + memzero(dma_buf, buf_size); + } + + /* + * Set up our checkpoint descriptor. Since the count + * is always zero, we'll abuse the dsadr and dtadr fields + * just in case this one is picked up by the hardware + * while processing SOUND_DSP_GETPTR. + */ + dma_desc->dsadr = dma_buf_phys; + dma_desc->dtadr = dma_buf_phys; + dma_desc->dcmd = DCMD_ENDIRQEN; + if (s->output && !s->mapped) + dma_desc->ddadr |= DDADR_STOP; + b->dma_desc = dma_desc++; + + /* set up the actual data descriptors */ + for (i = 0; (i * MAX_DMA_SIZE) < s->fragsize; i++) { + dma_desc[i].dsadr = (s->output) ? + (dma_buf_phys + i*MAX_DMA_SIZE) : s->dev_addr; + dma_desc[i].dtadr = (s->output) ? + s->dev_addr : (dma_buf_phys + i*MAX_DMA_SIZE); + dma_desc[i].dcmd = s->dcmd | + ((s->fragsize < MAX_DMA_SIZE) ? + s->fragsize : MAX_DMA_SIZE); + } + dma_desc += i; + + /* handle buffer pointers */ + b->data = dma_buf; + dma_buf += s->fragsize; + dma_buf_phys += s->fragsize; + buf_size -= s->fragsize; + } + + s->usr_frag = s->dma_frag = 0; + s->bytecount = 0; + s->fragcount = 0; + sema_init(&s->sem, (s->output) ? s->nbfrags : 0); + return 0; + +err: + printk("pxa-audio: unable to allocate audio memory\n "); + audio_clear_buf(s); + return -ENOMEM; +} + +/* + * Our DMA interrupt handler + */ +static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs) +{ + audio_stream_t *s = dev_id; + u_int dcsr; + + dcsr = DCSR(ch); + DCSR(ch) = dcsr & ~DCSR_STOPIRQEN; + + if (!s->buffers) { + printk("AC97 DMA: wow... received IRQ for channel %d but no buffer exists\n", ch); + return; + } + + if (dcsr & DCSR_BUSERR) + printk("AC97 DMA: bus error interrupt on channel %d\n", ch); + + if (dcsr & DCSR_ENDINTR) { + u_long cur_dma_desc; + u_int cur_dma_frag; + + /* + * Find out which DMA desc is current. Note that DDADR + * points to the next desc, not the current one. + */ + cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE; + + /* + * Let the compiler nicely optimize constant divisors into + * multiplications for the common cases which is much faster. + * Common cases: x = 1 + (1 << y) for y = [0..3] + */ + switch (s->descs_per_frag) { + case 2: cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break; + case 3: cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break; + case 5: cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break; + case 9: cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break; + default: cur_dma_frag = + cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE); + } + + /* Account for possible wrap back of cur_dma_desc above */ + if (cur_dma_frag >= s->nbfrags) + cur_dma_frag = s->nbfrags - 1; + + while (s->dma_frag != cur_dma_frag) { + if (!s->mapped) { + /* + * This fragment is done - set the checkpoint + * descriptor to STOP until it is gets + * processed by the read or write function. + */ + s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP; + up(&s->sem); + } + if (++s->dma_frag >= s->nbfrags) + s->dma_frag = 0; + + /* Accounting */ + s->bytecount += s->fragsize; + s->fragcount++; + } + + /* ... and for polling processes */ + wake_up(&s->frag_wq); + } + + if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE)) + wake_up(&s->stop_wq); +} + +/* + * Validate and sets up buffer fragments, etc. + */ +static int audio_set_fragments(audio_stream_t *s, int val) +{ + if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN) + return -EBUSY; + if (s->buffers) + audio_clear_buf(s); + s->nbfrags = (val >> 16) & 0x7FFF; + val &= 0xffff; + if (val < 5) + val = 5; + if (val > 15) + val = 15; + s->fragsize = 1 << val; + if (s->nbfrags < 2) + s->nbfrags = 2; + if (s->nbfrags * s->fragsize > 256 * 1024) + s->nbfrags = 256 * 1024 / s->fragsize; + if (audio_setup_buf(s)) + return -ENOMEM; + return val|(s->nbfrags << 16); +} + + +/* + * The fops functions + */ + +static int audio_write(struct file *file, const char *buffer, + size_t count, loff_t * ppos) +{ + const char *buffer0 = buffer; + audio_state_t *state = (audio_state_t *)file->private_data; + audio_stream_t *s = state->output_stream; + int chunksize, ret = 0; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->mapped) + return -ENXIO; + if (!s->buffers && audio_setup_buf(s)) + return -ENOMEM; + + while (count > 0) { + audio_buf_t *b = &s->buffers[s->usr_frag]; + + /* Grab a fragment */ + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + if (down_trylock(&s->sem)) + break; + } else { + ret = -ERESTARTSYS; + if (down_interruptible(&s->sem)) + break; + } + + /* Feed the current buffer */ + chunksize = s->fragsize - b->offset; + if (chunksize > count) + chunksize = count; + if (copy_from_user(b->data + b->offset, buffer, chunksize)) { + up(&s->sem); + return -EFAULT; + } + b->offset += chunksize; + buffer += chunksize; + count -= chunksize; + if (b->offset < s->fragsize) { + up(&s->sem); + break; + } + + /* + * Activate DMA on current buffer. + * We unlock this fragment's checkpoint descriptor and + * kick DMA if it is idle. Using checkpoint descriptors + * allows for control operations without the need for + * stopping the DMA channel if it is already running. + */ + b->offset = 0; + b->dma_desc->ddadr &= ~DDADR_STOP; + if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { + DDADR(s->dma_ch) = b->dma_desc->ddadr; + DCSR(s->dma_ch) = DCSR_RUN; + } + + /* move the index to the next fragment */ + if (++s->usr_frag >= s->nbfrags) + s->usr_frag = 0; + } + + if ((buffer - buffer0)) + ret = buffer - buffer0; + return ret; +} + + +static int audio_read(struct file *file, char *buffer, + size_t count, loff_t * ppos) +{ + char *buffer0 = buffer; + audio_state_t *state = file->private_data; + audio_stream_t *s = state->input_stream; + int chunksize, ret = 0; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->mapped) + return -ENXIO; + if (!s->buffers && audio_setup_buf(s)) + return -ENOMEM; + + while (count > 0) { + audio_buf_t *b = &s->buffers[s->usr_frag]; + + /* prime DMA */ + if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { + DDADR(s->dma_ch) = + s->buffers[s->dma_frag].dma_desc->ddadr; + DCSR(s->dma_ch) = DCSR_RUN; + } + + /* Wait for a buffer to become full */ + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + if (down_trylock(&s->sem)) + break; + } else { + ret = -ERESTARTSYS; + if (down_interruptible(&s->sem)) + break; + } + + /* Grab data from current buffer */ + chunksize = s->fragsize - b->offset; + if (chunksize > count) + chunksize = count; + if (copy_to_user(buffer, b->data + b->offset, chunksize)) { + up(&s->sem); + return -EFAULT; + } + b->offset += chunksize; + buffer += chunksize; + count -= chunksize; + if (b->offset < s->fragsize) { + up(&s->sem); + break; + } + + /* + * Make this buffer available for DMA again. + * We unlock this fragment's checkpoint descriptor and + * kick DMA if it is idle. Using checkpoint descriptors + * allows for control operations without the need for + * stopping the DMA channel if it is already running. + */ + b->offset = 0; + b->dma_desc->ddadr &= ~DDADR_STOP; + + /* move the index to the next fragment */ + if (++s->usr_frag >= s->nbfrags) + s->usr_frag = 0; + } + + if ((buffer - buffer0)) + ret = buffer - buffer0; + return ret; +} + + +static int audio_sync(struct file *file) +{ + audio_state_t *state = file->private_data; + audio_stream_t *s = state->output_stream; + audio_buf_t *b; + pxa_dma_desc *final_desc; + u_long dcmd_save = 0; + DECLARE_WAITQUEUE(wait, current); + + if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) + return 0; + + /* + * Send current buffer if it contains data. Be sure to send + * a full sample count. + */ + final_desc = NULL; + b = &s->buffers[s->usr_frag]; + if (b->offset &= ~3) { + final_desc = &b->dma_desc[1 + b->offset/MAX_DMA_SIZE]; + b->offset &= (MAX_DMA_SIZE-1); + dcmd_save = final_desc->dcmd; + final_desc->dcmd = b->offset | s->dcmd | DCMD_ENDIRQEN; + final_desc->ddadr |= DDADR_STOP; + b->offset = 0; + b->dma_desc->ddadr &= ~DDADR_STOP; + if (DCSR(s->dma_ch) & DCSR_STOPSTATE) { + DDADR(s->dma_ch) = b->dma_desc->ddadr; + DCSR(s->dma_ch) = DCSR_RUN; + } + } + + /* Wait for DMA to complete. */ + set_current_state(TASK_INTERRUPTIBLE); +#if 0 + /* + * The STOPSTATE IRQ never seem to occur if DCSR_STOPIRQEN is set + * along wotj DCSR_RUN. Silicon bug? + */ + add_wait_queue(&s->stop_wq, &wait); + DCSR(s->dma_ch) |= DCSR_STOPIRQEN; + schedule(); +#else + add_wait_queue(&s->frag_wq, &wait); + while ((DCSR(s->dma_ch) & DCSR_RUN) && !signal_pending(current)) { + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } +#endif + set_current_state(TASK_RUNNING); + remove_wait_queue(&s->frag_wq, &wait); + + /* Restore the descriptor chain. */ + if (final_desc) { + final_desc->dcmd = dcmd_save; + final_desc->ddadr &= ~DDADR_STOP; + b->dma_desc->ddadr |= DDADR_STOP; + } + return 0; +} + + +static unsigned int audio_poll(struct file *file, + struct poll_table_struct *wait) +{ + audio_state_t *state = file->private_data; + audio_stream_t *is = state->input_stream; + audio_stream_t *os = state->output_stream; + unsigned int mask = 0; + + if (file->f_mode & FMODE_READ) { + /* Start audio input if not already active */ + if (!is->buffers && audio_setup_buf(is)) + return -ENOMEM; + if (DCSR(is->dma_ch) & DCSR_STOPSTATE) { + DDADR(is->dma_ch) = + is->buffers[is->dma_frag].dma_desc->ddadr; + DCSR(is->dma_ch) = DCSR_RUN; + } + poll_wait(file, &is->frag_wq, wait); + } + + if (file->f_mode & FMODE_WRITE) { + if (!os->buffers && audio_setup_buf(os)) + return -ENOMEM; + poll_wait(file, &os->frag_wq, wait); + } + + if (file->f_mode & FMODE_READ) + if (( is->mapped && is->bytecount > 0) || + (!is->mapped && atomic_read(&is->sem.count) > 0)) + mask |= POLLIN | POLLRDNORM; + + if (file->f_mode & FMODE_WRITE) + if (( os->mapped && os->bytecount > 0) || + (!os->mapped && atomic_read(&os->sem.count) > 0)) + mask |= POLLOUT | POLLWRNORM; + + return mask; +} + + +static int audio_ioctl( struct inode *inode, struct file *file, + uint cmd, ulong arg) +{ + audio_state_t *state = file->private_data; + audio_stream_t *os = state->output_stream; + audio_stream_t *is = state->input_stream; + long val; + + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, (int *)arg); + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) + return put_user(os->fragsize, (int *)arg); + else + return put_user(is->fragsize, (int *)arg); + + case SNDCTL_DSP_GETCAPS: + val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; + if (is && os) + val |= DSP_CAP_DUPLEX; + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETFRAGMENT: + if (get_user(val, (long *) arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + int ret = audio_set_fragments(is, val); + if (ret < 0) + return ret; + ret = put_user(ret, (int *)arg); + if (ret) + return ret; + } + if (file->f_mode & FMODE_WRITE) { + int ret = audio_set_fragments(os, val); + if (ret < 0) + return ret; + ret = put_user(ret, (int *)arg); + if (ret) + return ret; + } + return 0; + + case SNDCTL_DSP_SYNC: + return audio_sync(file); + + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_POST: + return 0; + + case SNDCTL_DSP_GETTRIGGER: + val = 0; + if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN) + val |= PCM_ENABLE_INPUT; + if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN) + val |= PCM_ENABLE_OUTPUT; + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETTRIGGER: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + if (val & PCM_ENABLE_INPUT) { + if (!is->buffers && audio_setup_buf(is)) + return -ENOMEM; + if (!(DCSR(is->dma_ch) & DCSR_RUN)) { + audio_buf_t *b = &is->buffers[is->dma_frag]; + DDADR(is->dma_ch) = b->dma_desc->ddadr; + DCSR(is->dma_ch) = DCSR_RUN; + } + } else { + DCSR(is->dma_ch) = 0; + } + } + if (file->f_mode & FMODE_WRITE) { + if (val & PCM_ENABLE_OUTPUT) { + if (!os->buffers && audio_setup_buf(os)) + return -ENOMEM; + if (!(DCSR(os->dma_ch) & DCSR_RUN)) { + audio_buf_t *b = &os->buffers[os->dma_frag]; + DDADR(os->dma_ch) = b->dma_desc->ddadr; + DCSR(os->dma_ch) = DCSR_RUN; + } + } else { + DCSR(os->dma_ch) = 0; + } + } + return 0; + + case SNDCTL_DSP_GETOSPACE: + case SNDCTL_DSP_GETISPACE: + { + audio_buf_info inf = { 0, }; + audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is; + + if ((s == is && !(file->f_mode & FMODE_READ)) || + (s == os && !(file->f_mode & FMODE_WRITE))) + return -EINVAL; + if (!s->buffers && audio_setup_buf(s)) + return -ENOMEM; + inf.bytes = atomic_read(&s->sem.count) * s->fragsize; + inf.bytes -= s->buffers[s->usr_frag].offset; + inf.fragments = inf.bytes / s->fragsize; + inf.fragsize = s->fragsize; + inf.fragstotal = s->nbfrags; + return copy_to_user((void *)arg, &inf, sizeof(inf)); + } + + case SNDCTL_DSP_GETOPTR: + case SNDCTL_DSP_GETIPTR: + { + count_info inf = { 0, }; + audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; + dma_addr_t ptr; + int bytecount, offset, flags; + + if ((s == is && !(file->f_mode & FMODE_READ)) || + (s == os && !(file->f_mode & FMODE_WRITE))) + return -EINVAL; + if (DCSR(s->dma_ch) & DCSR_RUN) { + audio_buf_t *b; + save_flags_cli(flags); + ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch); + b = &s->buffers[s->dma_frag]; + offset = ptr - b->dma_desc->dsadr; + if (offset >= s->fragsize) + offset = s->fragsize - 4; + } else { + save_flags(flags); + offset = 0; + } + inf.ptr = s->dma_frag * s->fragsize + offset; + bytecount = s->bytecount + offset; + s->bytecount = -offset; + inf.blocks = s->fragcount; + s->fragcount = 0; + restore_flags(flags); + if (bytecount < 0) + bytecount = 0; + inf.bytes = bytecount; + return copy_to_user((void *)arg, &inf, sizeof(inf)); + } + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) + audio_clear_buf(os); + if (file->f_mode & FMODE_READ) + audio_clear_buf(is); + return 0; + + default: + return state->client_ioctl(inode, file, cmd, arg); + } + + return 0; +} + + +static int audio_mmap(struct file *file, struct vm_area_struct *vma) +{ + audio_state_t *state = file->private_data; + audio_stream_t *s; + unsigned long size, vma_addr; + int i, ret; + + if (vma->vm_pgoff != 0) + return -EINVAL; + + if (vma->vm_flags & VM_WRITE) { + if (!state->wr_ref) + return -EINVAL;; + s = state->output_stream; + } else if (vma->vm_flags & VM_READ) { + if (!state->rd_ref) + return -EINVAL; + s = state->input_stream; + } else return -EINVAL; + + if (s->mapped) + return -EINVAL; + size = vma->vm_end - vma->vm_start; + if (size != s->fragsize * s->nbfrags) + return -EINVAL; + if (!s->buffers && audio_setup_buf(s)) + return -ENOMEM; + vma_addr = vma->vm_start; + for (i = 0; i < s->nbfrags; i++) { + audio_buf_t *buf = &s->buffers[i]; + if (!buf->master) + continue; + ret = remap_page_range(vma_addr, buf->dma_desc->dsadr, + buf->master, vma->vm_page_prot); + if (ret) + return ret; + vma_addr += buf->master; + } + for (i = 0; i < s->nbfrags; i++) + s->buffers[i].dma_desc->ddadr &= ~DDADR_STOP; + s->mapped = 1; + return 0; +} + + +static int audio_release(struct inode *inode, struct file *file) +{ + audio_state_t *state = file->private_data; + + down(&state->sem); + + if (file->f_mode & FMODE_READ) { + audio_clear_buf(state->input_stream); + *state->input_stream->drcmr = 0; + pxa_free_dma(state->input_stream->dma_ch); + state->rd_ref = 0; + } + + if (file->f_mode & FMODE_WRITE) { + audio_sync(file); + audio_clear_buf(state->output_stream); + *state->output_stream->drcmr = 0; + pxa_free_dma(state->output_stream->dma_ch); + state->wr_ref = 0; + } + + up(&state->sem); + return 0; +} + + +int pxa_audio_attach(struct inode *inode, struct file *file, + audio_state_t *state) +{ + audio_stream_t *is = state->input_stream; + audio_stream_t *os = state->output_stream; + int err; + + down(&state->sem); + + /* access control */ + err = -ENODEV; + if ((file->f_mode & FMODE_WRITE) && !os) + goto out; + if ((file->f_mode & FMODE_READ) && !is) + goto out; + err = -EBUSY; + if ((file->f_mode & FMODE_WRITE) && state->wr_ref) + goto out; + if ((file->f_mode & FMODE_READ) && state->rd_ref) + goto out; + + /* request DMA channels */ + if (file->f_mode & FMODE_WRITE) { + err = pxa_request_dma(os->name, DMA_PRIO_LOW, + audio_dma_irq, os); + if (err < 0) + goto out; + os->dma_ch = err; + } + if (file->f_mode & FMODE_READ) { + err = pxa_request_dma(is->name, DMA_PRIO_LOW, + audio_dma_irq, is); + if (err < 0) { + if (file->f_mode & FMODE_WRITE) { + *os->drcmr = 0; + pxa_free_dma(os->dma_ch); + } + goto out; + } + is->dma_ch = err; + } + + file->private_data = state; + file->f_op->release = audio_release; + file->f_op->write = audio_write; + file->f_op->read = audio_read; + file->f_op->mmap = audio_mmap; + file->f_op->poll = audio_poll; + file->f_op->ioctl = audio_ioctl; + file->f_op->llseek = no_llseek; + + if ((file->f_mode & FMODE_WRITE)) { + state->wr_ref = 1; + os->fragsize = AUDIO_FRAGSIZE_DEFAULT; + os->nbfrags = AUDIO_NBFRAGS_DEFAULT; + os->output = 1; + os->mapped = 0; + init_waitqueue_head(&os->frag_wq); + init_waitqueue_head(&os->stop_wq); + *os->drcmr = os->dma_ch | DRCMR_MAPVLD; + } + if (file->f_mode & FMODE_READ) { + state->rd_ref = 1; + is->fragsize = AUDIO_FRAGSIZE_DEFAULT; + is->nbfrags = AUDIO_NBFRAGS_DEFAULT; + is->output = 0; + is->mapped = 0; + init_waitqueue_head(&is->frag_wq); + init_waitqueue_head(&is->stop_wq); + *is->drcmr = is->dma_ch | DRCMR_MAPVLD; + } + + err = 0; + +out: + up(&state->sem); + return err; +} + +EXPORT_SYMBOL(pxa_audio_attach); +EXPORT_SYMBOL(pxa_audio_clear_buf); + --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/sound/pxa-audio.h 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,55 @@ +/* + * linux/drivers/sound/pxa-audio.h -- audio interface for the Cotula chip + * + * Author: Nicolas Pitre + * Created: Aug 15, 2001 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +typedef struct { + int offset; /* current buffer position */ + char *data; /* actual buffer */ + pxa_dma_desc *dma_desc; /* pointer to the starting desc */ + int master; /* owner for buffer allocation, contain size whn true */ +} audio_buf_t; + +typedef struct { + char *name; /* stream identifier */ + audio_buf_t *buffers; /* pointer to audio buffer array */ + u_int usr_frag; /* user fragment index */ + u_int dma_frag; /* DMA fragment index */ + u_int fragsize; /* fragment size */ + u_int nbfrags; /* number of fragments */ + u_int dma_ch; /* DMA channel number */ + dma_addr_t dma_desc_phys; /* phys addr of descriptor ring */ + u_int descs_per_frag; /* nbr descriptors per fragment */ + int bytecount; /* nbr of processed bytes */ + int fragcount; /* nbr of fragment transitions */ + struct semaphore sem; /* account for fragment usage */ + wait_queue_head_t frag_wq; /* for poll(), etc. */ + wait_queue_head_t stop_wq; /* for users of DCSR_STOPIRQEN */ + u_long dcmd; /* DMA descriptor dcmd field */ + volatile u32 *drcmr; /* the DMA request channel to use */ + u_long dev_addr; /* device physical address for DMA */ + int mapped:1; /* mmap()'ed buffers */ + int output:1; /* 0 for input, 1 for output */ +} audio_stream_t; + +typedef struct { + audio_stream_t *output_stream; + audio_stream_t *input_stream; + int dev_dsp; /* audio device handle */ + int rd_ref:1; /* open reference for recording */ + int wr_ref:1; /* open reference for playback */ + int (*client_ioctl)(struct inode *, struct file *, uint, ulong); + struct semaphore sem; /* prevent races in attach/release */ +} audio_state_t; + +extern int pxa_audio_attach(struct inode *inode, struct file *file, + audio_state_t *state); +extern void pxa_audio_clear_buf(audio_stream_t *s); + --- linux-2.4.25/drivers/sound/sa1100-audio.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/sound/sa1100-audio.c 2004-03-31 17:15:12.000000000 +0200 @@ -148,7 +148,8 @@ do { dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA, dmasize, - &dmaphys); + &dmaphys, + 0); if (!dmabuf) dmasize -= s->fragsize; } while (!dmabuf && dmasize); --- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/video/Config.in 2004-03-31 17:15:12.000000000 +0200 @@ -50,6 +50,15 @@ if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT fi + tristate ' PXA LCD support' CONFIG_FB_PXA $CONFIG_ARCH_PXA + if [ "$CONFIG_FB_PXA" != "n" ]; then + choice 'LCD Bit Depth' \ + "8-Bpp CONFIG_FB_PXA_8BPP \ + 16-Bpp CONFIG_FB_PXA_16BPP" Bit-Depth + fi + if [ "$CONFIG_FB_PXA" != "n" -a "$CONFIG_ARCH_LUBBOCK" = "y" ]; then + bool ' Lubbock QVGA LCD support instead of DSTN' CONFIG_FB_PXA_QVGA + fi fi dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI if [ "$CONFIG_APOLLO" = "y" ]; then @@ -295,7 +304,7 @@ if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ - "$CONFIG_FB_DBMX1" = "y" ]; then + "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then define_tristate CONFIG_FBCON_CFB2 y define_tristate CONFIG_FBCON_CFB4 y else @@ -329,7 +338,7 @@ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \ "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \ "$CONFIG_FB_INTEL" = "y" -o \ - "$CONFIG_FB_DBMX1" = "y" ]; then + "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ @@ -372,7 +381,7 @@ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \ "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \ - "$CONFIG_FB_ANAKIN" = "y" -o \ + "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_PXA" = "y" -o \ "$CONFIG_FB_DBMX1" = "y" ]; then define_tristate CONFIG_FBCON_CFB16 y else --- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/video/Makefile 2004-03-31 17:15:12.000000000 +0200 @@ -14,7 +14,7 @@ fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \ fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \ fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \ - fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \ + fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o pxafb.o \ cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o # Each configuration option enables a list of files. @@ -129,6 +129,10 @@ obj-$(CONFIG_FB_BWTWO) += bwtwofb.o obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o +obj-$(CONFIG_FB_PXA) += pxafb.o +ifeq ($(CONFIG_PXA_CERF_PDA),y) + obj-$(CONFIG_FB_PXA) += lcdctrl.o lcdctrl_cerf.o +endif obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o --- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200 +++ linux-2.4.25/drivers/video/fbmem.c 2004-03-31 17:15:12.000000000 +0200 @@ -109,6 +109,7 @@ extern int chips_init(void); extern int g364fb_init(void); extern int sa1100fb_init(void); +extern int pxafb_init(void); extern int fm2fb_init(void); extern int fm2fb_setup(char*); extern int q40fb_init(void); @@ -305,6 +306,9 @@ #ifdef CONFIG_FB_SA1100 { "sa1100", sa1100fb_init, NULL }, #endif +#ifdef CONFIG_FB_PXA + { "pxa", pxafb_init, NULL }, +#endif #ifdef CONFIG_FB_SUN3 { "sun3", sun3fb_init, sun3fb_setup }, #endif @@ -675,13 +679,13 @@ #elif defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; -#elif defined(__arm__) || defined(__mips__) +#elif defined(__mips__) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #elif defined(__sh__) pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE; #elif defined(__hppa__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; -#elif defined(__ia64__) +#elif defined(__ia64__) || defined(__arm__) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); #elif defined(__hppa__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; --- /dev/null 2003-09-23 19:59:22.000000000 +0200 +++ linux-2.4.25/drivers/video/lcdctrl.c 2004-03-31 17:15:12.000000000 +0200 @@ -0,0 +1,223 @@ +/* + * lcdctrl.c + * + * Generic LCD control for brightness, contrast, etc. + * Device specific drivers implement a lcdctrl_device and + * provides access to it via lcdctrl_device_get_ops(). + * + * Copyright (C) 2002 Intrinsyc Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * History: + * Mar 2002: Initial version [FB] + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include