diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/Documentation/Configure.help linux-2.4.21-rmk1-lh7a400/Documentation/Configure.help --- linux-2.4.21-rmk1/Documentation/Configure.help Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/Documentation/Configure.help Sun Feb 8 20:06:00 2004 @@ -26801,6 +26801,33 @@ CONFIG_IPMI_WATCHDOG This enables the IPMI watchdog timer. +Sharp LH7A400 based bords +CONFIG_ARCH_LH7A400 + Say Y here to support the Sharp LH7A400 System on Chip. + +Sharp LH7A400 Evaluation Board (Aruba) +CONFIG_MACH_KEV7A400 + Say Y here to support the Sharp LH7A400 SoC Evaluation Board. + +Sharp LH7A400 UART +CONFIG_SERIAL_LH7A400 + Say Y here to include support for the UART on the Sharp + LH7A400 SoC. + + If unsure, say N. + +Console on a Sharp LH7A400 Serial port +CONFIG_SERIAL_LH7A400_CONSOLE + Say Y here to support a serial console on the + Sharp LH7A400 SoC Serial port. + + If unsure, say N. + +PCMCIA support for Sharp LH7A400 +CONFIG_PCMCIA_LH7A400 + Say Y here to support PCMCIA no the Sharp LH7A400 + + if unsure, say N. # # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/Makefile linux-2.4.21-rmk1-lh7a400/Makefile --- linux-2.4.21-rmk1/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/Makefile Thu Oct 16 13:43:25 2003 @@ -1,11 +1,12 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION =-rmk1 +EXTRAVERSION =-rmk1-lh7a400 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 +20,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE = /opt/hardhat/devkit/arm/920t_le/bin/arm_920t_le- # # Include the make variables (CC, etc...) @@ -195,6 +196,7 @@ DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o +DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmc.o DRIVERS := $(DRIVERS-y) diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/Makefile linux-2.4.21-rmk1-lh7a400/arch/arm/Makefile --- linux-2.4.21-rmk1/arch/arm/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/Makefile Thu Oct 16 13:44:16 2003 @@ -164,6 +164,10 @@ MACHINE = omaha endif +ifeq ($(CONFIG_ARCH_LH7A400),y) +MACHINE = lh7a400 +endif + export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS # Only set INCDIR if its not already defined above diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/boot/Makefile linux-2.4.21-rmk1-lh7a400/arch/arm/boot/Makefile --- linux-2.4.21-rmk1/arch/arm/boot/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/boot/Makefile Thu Oct 16 13:45:25 2003 @@ -101,6 +101,15 @@ INITRD_VIRT = 0x0C800000 endif +ifeq ($(CONFIG_ARCH_LH7A400),y) +ZTEXTADDR = 0xC0008000 +ZBSSADDR = 0xC0200000 +ZRELADDR = 0xC0008000 +INITRD_PHYS = 0xC4000000 +INITRD_VIRT = 0xC4000000 +PARAMS_PHYS = 0xC0000100 +endif + ifeq ($(CONFIG_ARCH_SA1100),y) ZRELADDR = 0xc0008000 # No defconfig file to move this into... diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/boot/compressed/head.S linux-2.4.21-rmk1-lh7a400/arch/arm/boot/compressed/head.S --- linux-2.4.21-rmk1/arch/arm/boot/compressed/head.S Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/boot/compressed/head.S Thu Oct 16 13:46:44 2003 @@ -73,6 +73,13 @@ */ str \rb, [r3, #0x14] @ UTDR .endm +#elif defined(CONFIG_ARCH_LH7A400) + .macro loadsp, rb + ldr \rb, =0x80000700 @ UART1 base + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm #else #error no serial architecture defined #endif diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/config.in linux-2.4.21-rmk1-lh7a400/arch/arm/config.in --- linux-2.4.21-rmk1/arch/arm/config.in Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/config.in Sat Oct 18 07:56:34 2003 @@ -43,6 +43,7 @@ FootBridge CONFIG_ARCH_FOOTBRIDGE \ Integrator CONFIG_ARCH_INTEGRATOR \ Omaha CONFIG_ARCH_OMAHA \ + LH7A400-based CONFIG_ARCH_LH7A400 \ LinkUp-L7200 CONFIG_ARCH_L7200 \ Motorola-MX1ADS CONFIG_ARCH_MX1ADS \ RiscPC CONFIG_ARCH_RPC \ @@ -181,7 +182,14 @@ endmenu +mainmenu_option next_comment +comment 'Sharp LH7A400 Implementations' +dep_bool ' KEV7A400 EVB' CONFIG_MACH_KEV7A400 $CONFIG_ARCH_LH7A400 +dep_bool ' Heeltoe eframe board' CONFIG_MACH_EFRAME $CONFIG_ARCH_LH7A400 +endmenu + # Definitions to make life easier +comment 'Acorn' if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \ "$CONFIG_ARCH_RPC" = "y" ]; then define_bool CONFIG_ARCH_ACORN y @@ -190,6 +198,7 @@ fi ##################################################################### +comment 'Footbridge support' # Footbridge support if [ "$CONFIG_ARCH_CO285" = "y" -o \ "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then @@ -313,11 +322,15 @@ # ARM922T -if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then +if [ "$CONFIG_ARCH_CAMELOT" = "y" -o "$CONFIG_ARCH_LH7A400" = "y" ]; then define_bool CONFIG_CPU_ARM922T y - define_bool CONFIG_PLD y else define_bool CONFIG_CPU_ARM922T n +fi + +if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then + define_bool CONFIG_PLD y +else define_bool CONFIG_PLD n fi @@ -378,7 +391,8 @@ "$CONFIG_ARCH_INTEGRATOR" = "y" -o "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_L7200" = "y" -o "$CONFIG_ARCH_ANAKIN" = "y" -o \ "$CONFIG_ARCH_CAMELOT" = "y" -o "$CONFIG_ARCH_MX1ADS" = "y" -o \ - "$CONFIG_ARCH_OMAHA" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then + "$CONFIG_ARCH_OMAHA" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" -o \ + "$CONFIG_ARCH_LH7A400" = "y" ]; then define_bool CONFIG_CPU_32v4 y else define_bool CONFIG_CPU_32v4 n @@ -414,7 +428,8 @@ # Select various configuration options depending on the machine type if [ "$CONFIG_ARCH_EDB7211" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ - "$CONFIG_ARCH_RISCSTATION" = "y" ]; then + "$CONFIG_ARCH_RISCSTATION" = "y" -o \ + "$CONFIG_ARCH_LH7A400" = "y" ]; then define_bool CONFIG_DISCONTIGMEM y else define_bool CONFIG_DISCONTIGMEM n @@ -446,7 +461,8 @@ "$CONFIG_ARCH_EBSA110" = "y" -o \ "$CONFIG_ARCH_CDB89712" = "y" -o \ "$CONFIG_ARCH_EDB7211" = "y" -o \ - "$CONFIG_ARCH_SA1100" = "y" ]; then + "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_LH7A400" = "y" ]; then define_bool CONFIG_ISA y else define_bool CONFIG_ISA n @@ -466,7 +482,8 @@ hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0 if [ "$CONFIG_ARCH_SA1100" = "y" -o \ - "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then + "$CONFIG_ARCH_INTEGRATOR" = "y" -o \ + "$CONFIG_ARCH_LH7A400" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL fi @@ -663,7 +680,8 @@ "$CONFIG_ARCH_CLPS7500" = "y" -o \ "$CONFIG_ARCH_P720T" = "y" -o \ "$CONFIG_ARCH_ANAKIN" = "y" -o \ - "$CONFIG_ARCH_MX1ADS" = "y" ]; then + "$CONFIG_ARCH_MX1ADS" = "y" -o \ + "$CONFIG_MACH_KEV7A400" = "y" ]; then define_bool CONFIG_PC_KEYMAP y fi if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_ARCH_RISCSTATION" != "y" ]; then @@ -679,6 +697,7 @@ "$CONFIG_ARCH_TBOX" = "y" -o \ "$CONFIG_ARCH_SHARK" = "y" -o \ "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_LH7A400" = "y" -o \ "$CONFIG_PCI" = "y" ]; then mainmenu_option next_comment comment 'Sound' @@ -694,6 +713,8 @@ source drivers/usb/Config.in +source drivers/mmc/Config.in + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then source net/bluetooth/Config.in fi diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/def-configs/kev7a400 linux-2.4.21-rmk1-lh7a400/arch/arm/def-configs/kev7a400 --- linux-2.4.21-rmk1/arch/arm/def-configs/kev7a400 Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/def-configs/kev7a400 Sat Oct 18 15:52:32 2003 @@ -0,0 +1,1008 @@ +# +# 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=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_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_LH7A400=y +# 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 + +# +# 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 + +# +# Sharp LH7A400 Implementations +# +CONFIG_MACH_KEV7A400=y +# CONFIG_MACH_EFRAME is not set + +# +# Acorn +# +# CONFIG_ARCH_ACORN is not set + +# +# Footbridge support +# +# 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=y +# 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_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# 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=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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_LH7A400=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# 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 is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" +CONFIG_ALIGNMENT_TRAP=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=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# 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=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# 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=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES 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=y +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 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=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_AIRO is not set +CONFIG_HERMES=y + +# +# Wireless Pcmcia cards support +# +CONFIG_PCMCIA_HERMES=y +# CONFIG_AIRO_CS is not set +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=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=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +CONFIG_IRPORT_SIR=y + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD 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/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=y +# 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 is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_LH7X_KEYBOARD_DRIVER is not set +CONFIG_LH7X_BUTTON_DRIVER=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_LH7A400=y +CONFIG_SERIAL_LH7A400_CONSOLE=y +# 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_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# 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 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 + +# +# 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_LH7A400_DC2DC=y +# CONFIG_RTC is not set +# CONFIG_LH7A400_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_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=y +# 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_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 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_NFSD_TCP 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# 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 is not set +# 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_PL110=y +CONFIG_PL110_LQ39=y +# CONFIG_PL110_LM57 is not set +# CONFIG_PL110_LQ57 is not set +# CONFIG_PL110_LQ121 is not set +# CONFIG_PL110_LQ104 is not set +# 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=y +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=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# 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_LH7A400=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +# 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 + +# +# Misc devices +# +CONFIG_TOUCHSCREEN_LH7X=y +# CONFIG_EEPROM_LH7X is not set +# CONFIG_7SEGMENT_LH7X is not set +# CONFIG_LH7A400_SCI is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG 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 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=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/kernel/Makefile linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/Makefile --- linux-2.4.21-rmk1/arch/arm/kernel/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/Makefile Fri Nov 28 09:44:33 2003 @@ -45,7 +45,8 @@ $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \ $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \ $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \ - $(CONFIG_ARCH_AT91RM9200) + $(CONFIG_ARCH_AT91RM9200) $(CONFIG_MACH_KEV7A400) \ + $(CONFIG_MACH_EFRAME) ifneq ($(findstring y,$(no-irq-arch)),y) obj-y += irq-arch.o @@ -54,6 +55,7 @@ obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_ARCH_RISCSTATION) += time-acorn.o +obj-$(CONFIG_ARCH_LH7A400) += fiq.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o obj-$(CONFIG_ARTHUR) += arthur.o diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/kernel/debug-armv.S linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/debug-armv.S --- linux-2.4.21-rmk1/arch/arm/kernel/debug-armv.S Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/debug-armv.S Thu Oct 16 14:05:47 2003 @@ -468,7 +468,30 @@ beq 1002b @ wait until transmit done .endm +#elif defined(CONFIG_ARCH_LH7A400) + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldr \rx, =UART2_PHYS @ physical base address + orrne \rx, \rx, #0xf8000000 @ virtual base + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] @ UART3_DR + .endm + + .macro busyuart,rd,rx @ spin while busy +1001: ldr \rd, [\rx, #0x10] @ UART3_FR + tst \rd, #1 << 3 @ BUSY ? + bne 1001b @ yes, spin + .endm + + .macro waituart,rd,rx @ wait for Tx FIFO room +1001: ldrb \rd, [\rx, #0x10] @ UART3_FR + tst \rd, #1 << 5 @ TXFF full? + bne 1001b @ yes, spin + .endm #else #error Unknown architecture diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/kernel/entry-armv.S linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/entry-armv.S --- linux-2.4.21-rmk1/arch/arm/kernel/entry-armv.S Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/entry-armv.S Thu Oct 16 14:08:07 2003 @@ -615,6 +615,28 @@ .text .endm +#elif defined(CONFIG_ARCH_LH7A400) +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =IO_ADDRESS(INTC_PHYS) @ Virt addr IRQ regs + ldr \irqstat, [\irqstat, #0] @ get masked int status + mov \irqnr, #0 @ start count at 0 +1001: tst \irqstat, #1 @ this the interrupt? + bne 1002f @ yup, outta here + add \irqnr, \irqnr, #1 @ no, increment count + mov \irqstat, \irqstat, lsr #1 @ look at next bit + cmp \irqnr, #28 @ at end? + bcc 1001b @ not yet, keep looking +1002: /* EQ will be set if we reach 28 */ + .endm + + .macro irq_prio_table + .endm + #else #error Unknown architecture #endif diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/kernel/head-armv.S linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/head-armv.S --- linux-2.4.21-rmk1/arch/arm/kernel/head-armv.S Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/kernel/head-armv.S Fri Oct 17 11:24:10 2003 @@ -130,6 +130,10 @@ */ mov r1, #MACH_TYPE_L7200 #endif +#if defined(CONFIG_MACH_KEV7A400) + mov r1, #(MACH_TYPE_KEV7A400&0xff) + orr r1, r1, #(MACH_TYPE_KEV7A400&0xff00) +#endif mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode msr cpsr_c, r0 @ and all irqs disabled diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/Makefile linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/Makefile --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/Makefile Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/Makefile Wed Nov 19 21:42:56 2003 @@ -0,0 +1,31 @@ +# +# 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 := lh7a400.o + +export-objs := generic.o dma.o hclkfreq.o + +# Object file lists. +obj-y := arch.o generic.o dma.o apm.o fiqhandler.o +obj-m := +obj-n := +obj- := + +mmc-$(CONFIG_MMC) := mmc.o +obj-y += $(mmc-y) +obj-m += $(mmc-m) + +obj-$(CONFIG_CPU_FREQ) += hclkfreq.o cpu_lh7a400.o + +# Specific board support +obj-$(CONFIG_MACH_KEV7A400) += kev7a400.o apm_kev7a400.o lcd_kev7a400.o \ + irq_kev7a400.o +obj-$(CONFIG_MACH_EFRAME) += eframe.o lcd_eframe.o irq_eframe.o + +include $(TOPDIR)/Rules.make diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/apm.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/apm.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/apm.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/apm.c Fri Oct 17 11:26:25 2003 @@ -0,0 +1,535 @@ +/* + * linux/arch/arm/mach-lh7a400/apm.c + * Jim Gleason + * Adapted from: (See below) + * + * bios-less APM driver for ARM Linux + * Jamey Hicks + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include + +// JMG extern int pm_suggest_suspend(void); + +#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) +extern int (*console_blank_hook)(int); +#endif + +struct apm_bios_info apm_bios_info = { + /* this driver simulates APM version 1.2 */ + version: 0x102, + flags: APM_32_BIT_SUPPORT +}; + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + * [no-]debug log some debugging messages + * [no-]power[-_]off power off on shutdown + */ + +/* + * Need to poll the APM BIOS every second + */ +#define APM_CHECK_TIMEOUT (HZ) + +/* + * Ignore suspend events for this amount of time after a resume + */ +#define DEFAULT_BOUNCE_INTERVAL (3 * HZ) + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 20 + +/* + * The per-file APM data + */ +struct apm_user { + int magic; + struct apm_user * next; + int suser: 1; + int suspend_wait: 1; + int suspend_result; + int suspends_pending; + int standbys_pending; + int suspends_read; + int standbys_read; + int event_head; + int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * The magic number in apm_user + */ +#define APM_BIOS_MAGIC 0x4101 + +/* + * Local variables + */ +//static int suspends_pending; +//static int standbys_pending; +//static int ignore_normal_resume; + +#ifdef CONFIG_APM_RTC_IS_GMT +# define clock_cmos_diff 0 +# define got_clock_diff 1 +#else +//static long clock_cmos_diff; +//static int got_clock_diff; +#endif +static int debug; +static int apm_disabled; +#ifdef CONFIG_SMP +static int power_off; +#else +static int power_off = 1; +#endif +static int exit_kapmd; +static int kapmd_running; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); +static struct apm_user * user_list = NULL; + +static char driver_version[] = "1.13"; /* no spaces */ + +typedef struct lookup_t { + int key; + char * msg; +} lookup_t; + +static const lookup_t error_table[] = { +/* N/A { APM_SUCCESS, "Operation succeeded" }, */ + { APM_DISABLED, "Power management disabled" }, + { APM_CONNECTED, "Real mode interface already connected" }, + { APM_NOT_CONNECTED, "Interface not connected" }, + { APM_16_CONNECTED, "16 bit interface already connected" }, +/* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */ + { APM_32_CONNECTED, "32 bit interface already connected" }, + { APM_32_UNSUPPORTED, "32 bit interface not supported" }, + { APM_BAD_DEVICE, "Unrecognized device ID" }, + { APM_BAD_PARAM, "Parameter out of range" }, + { APM_NOT_ENGAGED, "Interface not engaged" }, + { APM_BAD_FUNCTION, "Function not supported" }, + { APM_RESUME_DISABLED, "Resume timer disabled" }, + { APM_BAD_STATE, "Unable to enter requested state" }, +/* N/A { APM_NO_EVENTS, "No events pending" }, */ + { APM_NO_ERROR, "BIOS did not set a return code" }, + { APM_NOT_PRESENT, "No APM present" } +}; +#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) + +#ifdef CONFIG_MACH_KEV7A400 +extern void kev7a400_apm_get_power_status(u_char *ac_line_status, + u_char *battery_status, + u_char *battery_flag, + u_char *battery_percentage, + u_short *battery_life); +void kev7a400_apm_init(void); +void kev7a400_apm_exit(void); +#endif + +static int apm_get_power_status(u_char *ac_line_status, + u_char *battery_status, + u_char *battery_flag, + u_char *battery_percentage, + u_short *battery_life) +{ +#ifdef CONFIG_MACH_KEV7A400 + kev7a400_apm_get_power_status(ac_line_status, + battery_status, + battery_flag, + battery_percentage, + battery_life); +#endif + return APM_SUCCESS; +} + +static int queue_empty(struct apm_user *as) +{ + return as->event_head == as->event_tail; +} + +static apm_event_t get_queued_event(struct apm_user *as) +{ + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + return as->events[as->event_tail]; +} + +static int check_apm_user(struct apm_user *as, const char *func) +{ + if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { + printk(KERN_ERR "apm: %s passed bad filp\n", func); + return 1; + } + return 0; +} + +static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos) +{ + struct apm_user * as; + int i; + apm_event_t event; + DECLARE_WAITQUEUE(wait, current); + + as = fp->private_data; + if (check_apm_user(as, "read")) + return -EIO; + if (count < sizeof(apm_event_t)) + return -EINVAL; + if (queue_empty(as)) { + if (fp->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&apm_waitqueue, &wait); + printk("do_read: waiting\n"); +repeat: + set_current_state(TASK_INTERRUPTIBLE); + if (queue_empty(as) && !signal_pending(current)) { + schedule(); + goto repeat; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&apm_waitqueue, &wait); + } + i = count; + while ((i >= sizeof(event)) && !queue_empty(as)) { + event = get_queued_event(as); + printk(" do_read: event=%d\n", event); + if (copy_to_user(buf, &event, sizeof(event))) { + if (i < count) + break; + return -EFAULT; + } + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + as->suspends_read++; + break; + + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + as->standbys_read++; + break; + } + buf += sizeof(event); + i -= sizeof(event); + } + if (i < count) + return count - i; + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +static unsigned int do_poll(struct file *fp, poll_table * wait) +{ + struct apm_user * as; + + as = fp->private_data; + if (check_apm_user(as, "poll")) + return 0; + poll_wait(fp, &apm_waitqueue, wait); + if (!queue_empty(as)) + return POLLIN | POLLRDNORM; + return 0; +} + +static int do_ioctl(struct inode * inode, struct file *filp, + u_int cmd, u_long arg) +{ + struct apm_user * as; + + as = filp->private_data; + if (check_apm_user(as, "ioctl")) + return -EIO; + if (!as->suser) + return -EPERM; + switch (cmd) { + case APM_IOC_SUSPEND: + // JMG if (pm_suggest_suspend()) { + // JMG return -EBUSY; + // JMG } + break; + default: + return -EINVAL; + } + return 0; +} + +static int do_release(struct inode * inode, struct file * filp) +{ + struct apm_user * as; + + as = filp->private_data; + if (check_apm_user(as, "release")) + return 0; + filp->private_data = NULL; + lock_kernel(); + unlock_kernel(); + kfree(as); + return 0; +} + +static int do_open(struct inode * inode, struct file * filp) +{ + struct apm_user * as; + + as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); + if (as == NULL) { + printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", + sizeof(*as)); + return -ENOMEM; + } + as->magic = APM_BIOS_MAGIC; + as->event_tail = as->event_head = 0; + as->suspends_pending = as->standbys_pending = 0; + as->suspends_read = as->standbys_read = 0; + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->next = user_list; + user_list = as; + filp->private_data = as; + return 0; +} + +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + char * p; + unsigned short dx; + unsigned short error; + unsigned char ac_line_status = 0xff; + unsigned char battery_status = 0xff; + unsigned char battery_flag = 0xff; + unsigned char percentage = 0xff; + int time_units = -1; + char *units = "?"; + + p = buf; + + if ((smp_num_cpus == 1) && + !(error = apm_get_power_status(&ac_line_status, + &battery_status, &battery_flag, &percentage, &dx))) { + if (apm_bios_info.version > 0x100) { + if (dx != 0xffff) { + units = (dx & 0x8000) ? "min" : "sec"; + time_units = dx & 0x7fff; + } + } + } + /* Arguments, with symbols from linux/apm_bios.h. Information is + from the Get Power Status (0x0a) call unless otherwise noted. + + 0) Linux driver version (this will change if format changes) + 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + 2) APM flags from APM Installation Check (0x00): + bit 0: APM_16_BIT_SUPPORT + bit 1: APM_32_BIT_SUPPORT + bit 2: APM_IDLE_SLOWS_CLOCK + bit 3: APM_BIOS_DISABLED + bit 4: APM_BIOS_DISENGAGED + 3) AC line status + 0x00: Off-line + 0x01: On-line + 0x02: On backup power (BIOS >= 1.1 only) + 0xff: Unknown + 4) Battery status + 0x00: High + 0x01: Low + 0x02: Critical + 0x03: Charging + 0x04: Selected battery not present (BIOS >= 1.2 only) + 0xff: Unknown + 5) Battery flag + bit 0: High + bit 1: Low + bit 2: Critical + bit 3: Charging + bit 7: No system battery + 0xff: Unknown + 6) Remaining battery life (percentage of charge): + 0-100: valid + -1: Unknown + 7) Remaining battery life (time units): + Number of remaining minutes or seconds + -1: Unknown + 8) min = minutes; sec = seconds */ + + p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, + (apm_bios_info.version >> 8) & 0xff, + apm_bios_info.version & 0xff, + apm_bios_info.flags, + ac_line_status, + battery_status, + battery_flag, + (signed char)percentage, + time_units, + units); + + return p - buf; +} + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + int invert; + + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + invert = (strncmp(str, "no-", 3) == 0); + if (invert) + str += 3; + if (strncmp(str, "debug", 5) == 0) + debug = !invert; + if ((strncmp(str, "power-off", 9) == 0) || + (strncmp(str, "power_off", 9) == 0)) + power_off = !invert; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif + +static struct file_operations apm_bios_fops = { + owner: THIS_MODULE, + read: do_read, + poll: do_poll, + ioctl: do_ioctl, + open: do_open, + release: do_release, +}; + +static struct miscdevice apm_device = { + APM_MINOR_DEV, + "apm_bios", + &apm_bios_fops +}; + +#define APM_INIT_ERROR_RETURN return -1 + +/* + * Just start the APM thread. We do NOT want to do APM BIOS + * calls from anything but the APM thread, if for no other reason + * than the fact that we don't trust the APM BIOS. This way, + * most common APM BIOS problems that lead to protection errors + * etc will have at least some level of being contained... + * + * In short, if something bad happens, at least we have a choice + * of just killing the apm thread.. + */ +static int __init apm_init(void) +{ + if (apm_bios_info.version == 0) { + printk(KERN_INFO "apm: BIOS not found.\n"); + APM_INIT_ERROR_RETURN; + } + printk(KERN_INFO + "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n", + ((apm_bios_info.version >> 8) & 0xff), + (apm_bios_info.version & 0xff), + apm_bios_info.flags, + driver_version); + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + APM_INIT_ERROR_RETURN; + } + + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + APM_INIT_ERROR_RETURN; + } + // JMG pm_active = 1; + +#ifdef CONFIG_MACH_KEV7A400 + kev7a400_apm_init(); +#endif + + create_proc_info_entry("apm", 0, NULL, apm_get_info); + + misc_register(&apm_device); + + return 0; +} + +static void __exit apm_exit(void) +{ +#ifdef CONFIG_MACH_KEV7A400 + kev7a400_apm_exit(); +#endif + + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + if (power_off) + pm_power_off = NULL; + exit_kapmd = 1; + while (kapmd_running) + schedule(); + // JMG pm_active = 0; +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell"); +MODULE_DESCRIPTION("A minimal emulation of APM"); +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Enable debug mode"); +MODULE_PARM(power_off, "i"); +MODULE_PARM_DESC(power_off, "Enable power off"); + +EXPORT_NO_SYMBOLS; diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/apm_kev7a400.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/apm_kev7a400.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/apm_kev7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/apm_kev7a400.c Mon Oct 20 16:07:04 2003 @@ -0,0 +1,1068 @@ +/* + * linux/arch/arm/mach-lh7a400/apm-kev7a400.c + * + * Author: Jim Gleason + * + * Copyright (c) 2002, Embedix, Inc. + * + * This file contains the LH7A400 Battery Monitor Interface driver + * ((( Single Wire interface ))) + * + * 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. + * + * Based on Sharp MicroElectronics LH7A400 Battery Monitor interface. + * Author: MaysR + * Date: 16 Apr 2002 + * + * COPYRIGHT (C) 2001, SHARP MICROELECTRONICS OF THE AMERICAS, INC. + * CAMAS, WA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* The number of times a transmit/receive command are retried on failure */ +#define NTXRXATTEMPTS 3 + +/* +* I found it easier to control without the TX and RX interrupts +* ALSO - If using the interrupts, a watchdog interrupt will be needed!!! +*/ +#undef USE_TX_INTERRUPT +#undef USE_RX_INTERRUPT + +/* A loop count controlling logic overriding stuck processes */ +#define TX_WATCHDOGCOUNT 1000 +#define RX_WATCHDOGCOUNT 3000 + +/* +* Delays associated with the respective action +* (See BQ2050H datasheet timing info +* (I found it hangs periodically with less delay - JimG) +*/ +#undef USE_BREAK_UDELAY +#define USE_TX_UDELAY +#define USE_RX_UDELAY + +#define BREAK_UDELAY_COUNT 1000 +#define TX_UDELAY_COUNT 1000 +#define RX_UDELAY_COUNT 1000 + +/* Use a group of flags to "try" and determine if it is ok to proceed */ +#define USE_TX_WAITUNTILREADY +#define USE_RX_WAITUNTILREADY + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "LH7A400 BMI" + +static gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); +static clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + +/* BMI Single Wire Interface (SWI) Register Structure */ +typedef struct { + volatile uint32_t dr; /* Data Register */ + volatile uint32_t cr; /* Control Register */ + volatile uint32_t sr; /* Status Register */ + volatile union { + volatile uint32_t risr; /* Raw Interrupt Status Register */ + volatile uint32_t eoi; /* RISR End-Of-Interrupt Register */ + } u; + volatile uint32_t isr; /* Interrupt Status Register */ + volatile uint32_t ie; /* Interrupt Enable Register */ + volatile uint32_t tr; /* Timing Register */ + volatile uint32_t br; /* Break Register */ +} bmiSwiRegs_t; + +/* SWI CR (Control Register) defines */ +#define SWICR_SWIEN _BIT(0) +#define SWICR_GBS _BIT(1) +#define SWICR_SWIDINV _BIT(2) +#define SWICR_WDCS(n) ((n & 0x3F) << 3) +#define SWICR_RDSS(n) ((n & 0x3F) << 9) +#define SWICR_T_RST _BIT(15) +#define SWICR_SP_INVERT _BIT(16) + +/* SWI SR (Status Register) defines */ +#define SWISR_TXB _BIT(0) +#define SWISR_SBS _BIT(1) +#define SWISR_DBS _BIT(2) +#define SWISR_PBS _BIT(3) +#define SWISR_WTF _BIT(4) +#define SWISR_WRF _BIT(5) +#define SWISR_BKS _BIT(6) +#define SWISR_BRS _BIT(7) +#define SWISR_BRF _BIT(8) +#define SWISR_RXB _BIT(9) +#define SWISR_TEF _BIT(10) +#define SWISR_COL _BIT(11) + +/* SWI RISR (Raw Interrupt Status Register) defines */ +#define SWIRISR_RWTIS _BIT(0) +#define SWIRISR_RWRIS _BIT(1) +#define SWIRISR_RBRIS _BIT(2) + +/* SWI EOI (RISR End-Of-Interrupt Register) defines */ +#define SWIEOI_RWTIS SWIRISR_RWTIS +#define SWIEOI_RWRIS SWIRISR_RWRIS +#define SWIEOI_RBRIS SWIRISR_RBRIS + +/* SWI ISR (Interrupt Status Register) defines */ +#define SWIISR_WTIS _BIT(0) +#define SWIISR_WRIS _BIT(1) +#define SWIISR_BRIS _BIT(2) + +/* SWI IE (Interrupt Enable Register) defines */ +#define SWIIE_WTIE _BIT(0) +#define SWIIE_WRIE _BIT(1) +#define SWIIE_BRIE _BIT(2) + +/* SWI TR (Timing Register) defines */ +#define SWITR_BTG(n) ((n & 0xFFFF) << 0) + +/* SWI BR (Break Register) defines */ +#define SWIBR_BR(n) (n & 0x0FFF) +#define SWIBR_B(n) ((n & 0x0FFF) << 12) + +/* BMI Smart Battery Interface (SBI) Register Structure */ +typedef struct { + volatile uint32_t dr; /* Data Register */ + volatile uint32_t cr; /* Control Register */ + volatile uint32_t count; /* Count Register */ + volatile uint32_t sr; /* Status Register */ + volatile union { + volatile uint32_t risr; /* Raw Interrupt Status Register */ + volatile uint32_t eoi; /* RISR End-Of-Interrupt Register */ + } u; + volatile uint32_t isr; /* Interrupt Status Register */ + volatile uint32_t ie; /* Interrupt Enable Register */ +} bmiSbiRegs_t; + +/* SBI CR (Control Register) defines */ +#define SBICR_SBI_EN _BIT(0) +#define SBICR_FFLUSH _BIT(1) +#define SBICR_DIVFACT(n) ((n & 0xFF) << 2) +#define SBICR_TX_FDIS _BIT(10) +#define SBICR_RX_FDIS _BIT(11) +#define SBICR_TOC(n) ((n & ˆw0FFF) << 12) +#define SBICR_BRF _BIT(24) +#define SBICR_PEF _BIT(25) + +/* SBI COUNT (Count Register) defines */ +#define SBICOUNT_PRE(n) ((n & 0x1F) << 0) +#define SBICOUNT_REP(n) ((n & 0x1F) << 5) +#define SBICOUNT_READ(n) ((n & 0x1F) << 10) + +/* SBI SR (Status Register) defines */ +#define SBISR_RXFE _BIT(0) +#define SBISR_TXFE _BIT(1) +#define SBISR_RXFF _BIT(2) +#define SBISR_TXFF _BIT(3) +#define SBISR_TXBUSY _BIT(4) +#define SBISR_MASTER _BIT(5) +#define SBISR_SLAVE _BIT(6) +#define SBISR_READnWRITE _BIT(7) +#define SBISR_ACKFAIL _BIT(8) +#define SBISR_RXOE _BIT(9) +#define SBISR_TXUE _BIT(10) +#define SBISR_CLT _BIT(11) +#define SBISR_SBH _BIT(12) + +/* SBI RISR (Raw Interrupt Status Register) defines */ +#define SBIRISR_RMTCIS _BIT(0) +#define SBIRISR_RRTIS _BIT(1) +#define SBIRISR_RTIS _BIT(2) +#define SBIRISR_RRIS _BIT(3) +#define SBIRISR_RAFIS _BIT(4) +#define SBIRISR_RALIS _BIT(5) +#define SBIRISR_RSTCIS _BIT(6) +#define SBIRISR_RCLTIS _BIT(7) + +/* SBI EOI (RISR End-Of-Interrupt Register) defines */ +#define SBIEOI_RMTCIS SBIRISR_RMTCIS +#define SBIEOI_RRTIS SBIRISR_RRTIS +#define SBIEOI_RTIS SBIRISR_RTIS +#define SBIEOI_RRIS SBIRISR_RRIS +#define SBIEOI_RAFIS SBIRISR_RAFIS +#define SBIEOI_RALIS SBIRISR_RALIS +#define SBIEOI_RSTCIS SBIRISR_RSTCIS +#define SBIEOI_RCLTIS SBIRISR_RCLTIS + +/* SBI ISR (Interrupt Status Register) defines */ +#define SBIISR_MTCIS _BIT(0) +#define SBIISR_RTIS _BIT(1) +#define SBIISR_TIS _BIT(2) +#define SBIISR_RIS _BIT(3) +#define SBIISR_AFIS _BIT(4) +#define SBIISR_ALIS _BIT(5) +#define SBIISR_STCIS _BIT(6) +#define SBIISR_CLTIS _BIT(7) + +/* SBI IE (Interrupt Enable Register) defines */ +#define SBIIE_TCIE _BIT(0) +#define SBIIE_RTIE _BIT(1) +#define SBIIE_TIE _BIT(2) +#define SBIIE_RIE _BIT(3) +#define SBIIE_AFE _BIT(4) +#define SBIIE_ALE _BIT(5) +#define SBIIE_STCIE _BIT(6) +#define SBIIE_CLTIE _BIT(7) + +/* Battery monitor Interface (BMI) Register Structure */ +typedef struct { + bmiSwiRegs_t swi; + uint32_t res[36]; + bmiSbiRegs_t sbi; +} bmiRegs_t; + +static bmiRegs_t *bmi = (bmiRegs_t *)IO_ADDRESS(BMI_PHYS); +static bmiSwiRegs_t *bmiswi = NULL; /* Set in kev7a400_apm_init() */ +static bmiSbiRegs_t *bmisbi = NULL; /* Set in kev7a400_apm_init() */ + +typedef enum { + BQ2050H, + BQ2014H, + MAX_BMI_SWI +} swi_types_t; + +typedef struct { + uint32_t break_time; + uint32_t break_recovery; + uint16_t bit_time_gen; + uint16_t read_size; + uint16_t write_size; + uint8_t ss_invert; + uint8_t data_invert; +} swi_settings_t; + +#if !defined (YES) +#define YES (1) +#endif + +#if !defined (NO) +#define NO (0) +#endif + +static int bmi_irq_enabled = 0; +static swi_types_t bmi_device = BQ2050H; + +#define vdprintk if (0) printk +#define dprintk if (0) printk + +/********************************************************************* + * Interface communication parameters for each battery monitor device. + * Add additional device parameters here. + *********************************************************************/ +#define BQ2050H_BREAK_TIME (1481) +#define BQ2050H_BREAK_RECOVERY_TIME (370) +//#define BQ2050H_BIT_TIME_GENERATION (37) +#define BQ2050H_BIT_TIME_GENERATION (494) +#define BQ2050H_READ_DATA_SIZE (8) +#define BQ2050H_WRITE_DATA_SIZE (8) +#define BQ2050H_START_STOP_INVERT NO +#define BQ2050H_DATA_INVERT NO + +#define BQ2014H_BREAK_TIME (1481) +#define BQ2014H_BREAK_RECOVERY_TIME (370) +//#define BQ2014H_BIT_TIME_GENERATION (37) +#define BQ2014H_BIT_TIME_GENERATION (494) +#define BQ2014H_READ_DATA_SIZE (8) +#define BQ2014H_WRITE_DATA_SIZE (8) +#define BQ2014H_START_STOP_INVERT NO +#define BQ2014H_DATA_INVERT NO + +/********************************************************************* + * Structure to provide interface communications parameters to driver. + * Add new device entries here in the same order as the typedef list + * above. + *********************************************************************/ +static swi_settings_t swi_settings[] = +{ + { + BQ2050H_BREAK_TIME, + BQ2050H_BREAK_RECOVERY_TIME, + BQ2050H_BIT_TIME_GENERATION, + BQ2050H_READ_DATA_SIZE, + BQ2050H_WRITE_DATA_SIZE, + BQ2050H_START_STOP_INVERT, + BQ2050H_DATA_INVERT + }, + { + BQ2014H_BREAK_TIME, + BQ2014H_BREAK_RECOVERY_TIME, + BQ2014H_BIT_TIME_GENERATION, + BQ2014H_READ_DATA_SIZE, + BQ2014H_WRITE_DATA_SIZE, + BQ2014H_START_STOP_INVERT, + BQ2014H_DATA_INVERT + } +}; + +typedef struct { + uint8_t flgs1; /* Primary Status Flags */ + uint8_t tmp; /* Temperature */ + uint8_t nach; /* Nominal Available Capacity High Byte */ + uint8_t batid; /* Battery ID */ + uint8_t lmd; /* Last Measured Discharge */ + uint8_t flgs2; /* Secondary Status Flags */ + uint8_t ppd; /* Program Pin Pull-Down */ + uint8_t ppu; /* Program Pin Pull-Up */ + uint8_t cpi; /* Capacity Inaccurate Count */ + uint8_t reserved_0x0A; + uint8_t vsb; /* Battery Voltage */ + uint8_t vts; /* End-of-Discharge Threshld Select */ + uint8_t cact; /* Temp & Discharge Rate Compensated Avail Capacity */ + uint8_t cacd; /* Discharge Rate Compensated Avail Capacity */ + uint8_t saeh; /* Scaled Available Energy High Byte */ + uint8_t sael; /* Scaled Available Energy Low Byte */ + uint8_t rcac; /* Relative CAC */ + uint8_t vsrh; /* Current Scale High */ + uint8_t vsrl; /* Current Scale Low */ + uint8_t reserved_0x14; + uint8_t nmcv; /* Maximum Cell Voltage */ + uint8_t reserved_0x16; + uint8_t nacl; /* Nominal Available Capacity Low Byte */ + uint8_t dcr; /* Discharge */ + uint8_t reserved_0x19_to_0x1d[5]; + uint8_t ppfc; /* Program Pin Data */ + uint8_t reserved_0x1F_to_0x37[25]; + uint8_t intss; /* Vos interrupt */ + uint8_t rst; /* Reset */ + uint8_t reserved_0x3A_to_0x3E[5]; + uint8_t hexff; /* Check */ +} BQ2050HREGS_t; +static BQ2050HREGS_t BQ2050HREGS; + +wait_queue_head_t bmi_wait_q; + +#ifdef DEBUG +static void +dump_bmi_swi_regs(void) +{ + uint32_t dr, cr, sr, risr, isr, ie, tr, br; + + dr = bmiswi->dr; + cr = bmiswi->cr; + sr = bmiswi->sr; + risr = bmiswi->u.risr; + isr = bmiswi->isr; + ie = bmiswi->ie; + tr = bmiswi->tr; + br = bmiswi->br; + + dprintk("* bmiswi->dr : 0x%08X\n", dr); + + dprintk("* bmiswi->cr : 0x%08X\n", cr); + if (cr & SWICR_SWIEN) { + vdprintk(" SWI enabled\n"); + } else { + vdprintk(" SWI disabled\n"); + } + if (cr & SWICR_GBS) + vdprintk(" Generate a break\n"); + if (cr & SWICR_SWIDINV) + vdprintk(" Data inverted\n"); + vdprintk(" %d bits to be written\n", (cr & SWICR_WDCS(-1)) >> 3); + vdprintk(" %d bits to be read\n", (cr & SWICR_RDSS(-1)) >> 9); + if (cr & SWICR_T_RST) + vdprintk(" Reset data transfer\n"); + if (cr & SWICR_SP_INVERT) + vdprintk(" Protocol bits inverted\n"); + + dprintk("* bmiswi->sr : 0x%08X\n", sr); + if (sr & SWISR_TXB) + vdprintk(" Transmit process busy\n"); + if (sr & SWISR_SBS) + vdprintk(" Reading/writing a start bit\n"); + if (sr & SWISR_DBS) + vdprintk(" Reading/writing a data bit\n"); + if (sr & SWISR_PBS) + vdprintk(" Read/writing a stop bit\n"); + if (sr & SWISR_WTF) + vdprintk(" Write finished\n"); + if (sr & SWISR_WRF) + vdprintk(" Read finished\n"); + if (sr & SWISR_BKS) + vdprintk(" In break process\n"); + if (sr & SWISR_BRS) + vdprintk(" Generating a break recovery\n"); + if (sr & SWISR_BRF) + vdprintk(" Break recovery finished\n"); + if (sr & SWISR_RXB) + vdprintk(" Receive process is busy\n"); + if (sr & SWISR_TEF) + vdprintk(" Cannot transmit - Process busy\n"); + if (sr & SWISR_COL) + vdprintk(" Cannot receive - Process busy\n"); + + dprintk("* bmiswi->u.risr: 0x%08X\n", risr); + if (risr & SWIRISR_RWTIS) + vdprintk(" Transfer complete\n"); + if (risr & SWIRISR_RWRIS) + vdprintk(" Receive complete\n"); + if (risr & SWIRISR_RBRIS) + vdprintk(" Break complete\n"); + + dprintk("* bmiswi->isr : 0x%08X\n", isr); + if (isr & SWIISR_WTIS) + vdprintk(" Transfer complete\n"); + if (isr & SWIISR_WRIS) + vdprintk(" Receive complete\n"); + if (isr & SWIISR_BRIS) + vdprintk(" Break complete\n"); + + dprintk("* bmiswi->ie : 0x%08X\n", ie); + if (ie & SWIIE_WTIE) + vdprintk(" Transfer interrupt enabled\n"); + if (ie & SWIIE_WRIE) + vdprintk(" Receive interrupt enabled\n"); + if (ie & SWIIE_BRIE) + vdprintk(" Break interrupt enabled\n"); + + dprintk("* bmiswi->tr : 0x%08X\n", tr); + vdprintk(" BTG is %d\n", (tr & SWITR_BTG(-1)) >> 0); + + dprintk("* bmiswi->br : 0x%08X\n", br); + vdprintk(" SWIBR is %d\n", (tr & SWIBR_BR(-1)) >> 0); + vdprintk(" SWIB is %d\n", (tr & SWIBR_B(-1)) >> 12); +} +#else +#define dump_bmi_swi_regs() +#endif /* DEBUG */ + +/* Enable the Single Wire Interface (SWI) */ +static void +bmi_swi_enable(void) +{ + vdprintk("ENTER: bmi_swi_enable()\n"); + bmiswi->cr |= SWICR_SWIEN; + vdprintk("LEAVE: bmi_swi_enable()\n"); +} + +#ifdef NOT_CURRENTLY_USED +/* Disable the Single Wire Interface (SWI) */ +static void +bmi_swi_disable(void) +{ + vdprintk("ENTER: bmi_swi_disable()\n"); + bmiswi->cr &= ~(SWICR_SWIEN); + vdprintk("LEAVE: bmi_swi_disable()\n"); +} +#endif /* NOT_CURRENTLY_USED */ + +void bmi_swi_break(u_char device) +{ + DECLARE_WAITQUEUE(bmi_swi_break_wait, current); + + vdprintk("ENTER: bmi_swi_break()\n"); + add_wait_queue(&bmi_wait_q, &bmi_swi_break_wait); + /* + * SWIBR_B: + * Specifies the number of 7.3278 MHZ clock cycles in which SWI + * must be driven LOW to generate a break. i.e. + * 0xFFF generates a 555 micro-second break. + * 0x000 generates a 135 nano-second break. + * SWIBR_BR + * Specifies the number of 7.3278 MHZ clocks in which HDQ must be + * returned HIGH to generate a break recovery. i.e. + * 0xFFF generates a 555 micro-second recovery period. + * 0x000 generates a 135 nano-second recovery period. + */ + bmiswi->br = (SWIBR_B(swi_settings[device].break_time) | + SWIBR_BR(swi_settings[device].break_recovery)); + /* + * Specifies the 7.3278 MHZ clock cycles required to generate + * a bit time * for the start, stop, and data bits required in + * a data packet. The clock * period generated is 3 x (the + * data rate). + */ + bmiswi->tr = 0; + /* Generate a break followed by a recovery period */ + set_current_state(TASK_INTERRUPTIBLE); + bmiswi->cr |= SWICR_GBS; + /* Wait for the break and recovery period to finish */ + while (bmiswi->sr & SWISR_BKS) { + schedule(); /* Give the system time to do other work */ + } + remove_wait_queue(&bmi_wait_q, &bmi_swi_break_wait); + current->state = TASK_RUNNING; + /* Clean up from the break and recovery period */ + bmiswi->br = 0; + bmiswi->tr = SWITR_BTG(swi_settings[device].bit_time_gen); + bmiswi->cr &= ~(SWICR_GBS); +#ifdef USE_BREAK_UDELAY + schedule(); /* Give the system time to do other work */ + udelay(BREAK_UDELAY_COUNT); + schedule(); /* Give the system time to do other work */ +#endif /* USE_BREAK_UDELAY */ + + vdprintk("LEAVE: bmi_swi_break()\n"); +} + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_data_invert(void) +{ + vdprintk("ENTER: bmi_swi_data_invert()\n"); + bmiswi->cr |= SWICR_SWIDINV; + vdprintk("LEAVE: bmi_swi_data_invert()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_data_normal(void) +{ + vdprintk("ENTER: bmi_swi_data_normal()\n"); + bmiswi->cr &= ~(SWICR_SWIDINV); + vdprintk("LEAVE: bmi_swi_data_normal()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_read_size(uint32_t size) +{ + vdprintk("ENTER: bmi_swi_read_size()\n"); + bmiswi->cr |= SWICR_RDSS(size); + vdprintk("LEAVE: bmi_swi_read_size()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_write_size(uint32_t size) +{ + vdprintk("ENTER: bmi_swi_write_size()\n"); + bmiswi->cr |= SWICR_WDCS(size); + vdprintk("LEAVE: bmi_swi_write_size()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_transfer_reset(void) +{ + vdprintk("ENTER: bmi_swi_transfer_reset()\n"); + bmiswi->cr |= SWICR_T_RST; + vdprintk("LEAVE: bmi_swi_transfer_reset()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_stop_start_invert(void) +{ + vdprintk("ENTER: bmi_swi_stop_start_invert()\n"); + bmiswi->cr |= SWICR_SP_INVERT; + vdprintk("LEAVE: bmi_swi_stop_start_invert()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +#ifdef NOT_CURRENTLY_USED +static void +bmi_swi_stop_start_normal(void) +{ + vdprintk("ENTER: bmi_swi_stop_start_normal()\n"); + bmiswi->cr &= ~(SWICR_SP_INVERT); + vdprintk("LEAVE: bmi_swi_stop_start_normal()\n"); + + return; +} +#endif /* NOT_CURRENTLY_USED */ + +static uint32_t +bmi_swi_send_data(uint32_t data) +{ + uint32_t retval = 0; +#ifdef USE_TX_INTERRUPT + DECLARE_WAITQUEUE(bmi_swi_send_data_wait, current); +#endif /* USE_TX_INTERRUPT */ + int watchdogCount; + + vdprintk("ENTER: bmi_swi_send_data()\n"); +#ifdef USE_TX_INTERRUPT + add_wait_queue(&bmi_wait_q, &bmi_swi_send_data_wait); + set_current_state(TASK_INTERRUPTIBLE); +#endif /* USE_TX_INTERRUPT */ + +#ifdef USE_TX_WAITUNTILREADY + /* Wait until it is ok to transmit/receive */ + watchdogCount = 0; + while ((bmiswi->sr & (SWISR_RXB | SWISR_TXB | SWISR_BRS | + SWISR_BKS | SWISR_PBS | SWISR_DBS | SWISR_SBS)) + && watchdogCount < TX_WATCHDOGCOUNT) + { + /* Give the system time to do other work */ + schedule(); + watchdogCount++; + } + /***** WHAT IF WATCHDOG FAILS - JMG *****/ +#ifdef DEBUG + if (watchdogCount >= TX_WATCHDOGCOUNT) { + dprintk("SEND WATCHDOG FAILURE(1)\n"); + } +#endif /* DEBUG */ +#endif /* USE_TX_WAITUNTILREADY */ + + /* Send the data */ + bmiswi->dr = data; + + /* Wait for the data to be sent */ +#ifdef USE_TX_UDELAY + /* Give the system time to do other work */ + schedule(); + udelay(TX_UDELAY_COUNT); + + /* Give the system time to do other work */ + schedule(); +#endif /* USE_TX_UDELAY */ + watchdogCount = 0; + while ((bmiswi->sr & SWISR_TXB) && watchdogCount < TX_WATCHDOGCOUNT) + { + /* Give the system time to do other work */ + schedule(); + watchdogCount++; + } + +#ifdef USE_TX_INTERRUPT + remove_wait_queue(&bmi_wait_q, &bmi_swi_send_data_wait); + current->state = TASK_RUNNING; +#endif /* USE_TX_INTERRUPT */ + + if (watchdogCount >= TX_WATCHDOGCOUNT) { + dprintk("SEND WATCHDOG FAILURE(2)\n"); +// retval = -1; + } + vdprintk("LEAVE: bmi_swi_send_data()\n"); + + return(retval); +} + +#if 0 +static uint32_t +bmi_swi_status(void) +{ + uint32_t retval; + vdprintk("ENTER: bmi_swi_status()\n"); + retval = bmiswi->sr; + vdprintk("LEAVE: bmi_swi_status()\n"); + + return(retval); +} +#endif + +static uint32_t +bmi_swi_recv_data(void) +{ +#ifdef USE_RX_INTERRUPT + DECLARE_WAITQUEUE(bmi_swi_recv_data_wait, current); +#endif /* USE_RX_INTERRUPT */ + int watchdogCount; + uint32_t retval; + + vdprintk("ENTER: bmi_swi_recv_data()\n"); + +#ifdef USE_RX_INTERRUPT + add_wait_queue(&bmi_wait_q, &bmi_swi_recv_data_wait); + set_current_state(TASK_INTERRUPTIBLE); +#endif /* USE_RX_INTERRUPT */ + +#ifdef USE_RX_WAITUNTILREADY + /* Wait until it is ok to transmit/receive */ + watchdogCount = 0; + while ((bmiswi->sr & (SWISR_RXB | SWISR_TXB | SWISR_BRS | + SWISR_BKS | SWISR_PBS | SWISR_DBS | SWISR_SBS)) + && watchdogCount < RX_WATCHDOGCOUNT) + { + /* Give the system time to do other work */ + schedule(); + watchdogCount++; + } + /***** WHAT IF WATCHDOG FAILS - JMG *****/ +#ifdef DEBUG + if (watchdogCount >= RX_WATCHDOGCOUNT) { + dprintk("RECV WATCHDOG FAILURE(1)\n"); + } +#endif /* DEBUG */ +#endif /* USE_RX_WAITUNTILREADY */ + + /* Wait for the data to be received */ + watchdogCount = 0; + while (((bmiswi->sr & SWISR_WRF) == 0) && + watchdogCount < RX_WATCHDOGCOUNT) + { + /* Give the system time to do other work */ + schedule(); + watchdogCount++; + } + if (watchdogCount < RX_WATCHDOGCOUNT) { + retval = bmiswi->dr; /* read data & clear interupt */ + } else { + dprintk("RECV WATCHDOG FAILURE(2)\n"); + retval = -1; + } + +#ifdef USE_RX_INTERRUPT + remove_wait_queue(&bmi_wait_q, &bmi_swi_recv_data_wait); + current->state = TASK_RUNNING; +#endif /* USE_RX_INTERRUPT */ + +#ifdef USE_RX_UDELAY + schedule(); /* Give the system time to do other work */ + udelay(RX_UDELAY_COUNT); + schedule(); /* Give the system time to do other work */ +#endif /* USE_RX_UDELAY */ + vdprintk("LEAVE: bmi_swi_recv_data(0x%X)\n", retval); + + return(retval); +} + +#ifdef DEBUG +static void +bmi_swi_dumpstruct(void) +{ + vdprintk("ENTER: bmi_swi_dumpstruct()\n"); + printk("\n" + "0x%02X = flgs1 = Primary Status Flags\n" + "0x%02X = tmp = Temperature\n" + "0x%02X = nach = Nominal Available Capacity High Byte\n" + "0x%02X = batid = Battery ID\n" + "0x%02X = lmd = Last Measured Discharge\n" + "0x%02X = flgs2 = Secondary Status Flags\n" + "0x%02X = ppd = Program Pin Pull-Down\n" + "0x%02X = ppu = Program Pin Pull-Up\n" + "0x%02X = cpi = Capacity Inaccurate Count\n" + "0x%02X = vsb = Battery Voltage\n" + "0x%02X = vts = End-of-Discharge Threshld Select\n" + "0x%02X = cact = Temp & Discharge Rate Compensated Avail Capacity\n" + "0x%02X = cacd = Discharge Rate Compensated Avail Capacity\n" + "0x%02X = saeh = Scaled Available Energy High Byte\n" + "0x%02X = sael = Scaled Available Energy Low Byte\n" + "0x%02X = rcac = Relative CAC\n" + "0x%02X = vsrh = Current Scale High\n" + "0x%02X = vsrl = Current Scale Low\n" + "0x%02X = nmcv = Maximum Cell Voltage\n" + "0x%02X = nacl = Nominal Available Capacity Low Byte\n" + "0x%02X = dcr = Discharge\n" + "0x%02X = ppfc = Program Pin Data\n" + "0x%02X = intss = Vos interrupt\n" + "0x%02X = rst = Reset\n" + "0x%02X = hexff = Check\n" + "\n" + , + BQ2050HREGS.flgs1, + BQ2050HREGS.tmp, + BQ2050HREGS.nach, + BQ2050HREGS.batid, + BQ2050HREGS.lmd, + BQ2050HREGS.flgs2, + BQ2050HREGS.ppd, + BQ2050HREGS.ppu, + BQ2050HREGS.cpi, + BQ2050HREGS.vsb, + BQ2050HREGS.vts, + BQ2050HREGS.cact, + BQ2050HREGS.cacd, + BQ2050HREGS.saeh, + BQ2050HREGS.sael, + BQ2050HREGS.rcac, + BQ2050HREGS.vsrh, + BQ2050HREGS.vsrl, + BQ2050HREGS.nmcv, + BQ2050HREGS.nacl, + BQ2050HREGS.dcr, + BQ2050HREGS.ppfc, + BQ2050HREGS.intss, + BQ2050HREGS.rst, + BQ2050HREGS.hexff + ); + vdprintk("LEAVE: bmi_swi_dumpstruct()\n"); +} +#endif /* DEBUG */ + +static void +bmi_swi_fillstruct(void) +{ + u_char *member; + u_char i; + uint32_t data; + int nAttempts; + int sts; + + vdprintk("ENTER: bmi_swi_fillstruct()\n"); + + member = (u_char *)&BQ2050HREGS; + for (i = 1; i < sizeof(BQ2050HREGS); i++) { + /* Skip the BQ2050HREGS reserved registers */ + if (i == 0xa || i == 0x14 || i == 0x16) + i++; + else if (i == 0x19 || i == 0x3a) + i += 5; + else if (i == 0x1f) + i += 25; + + /* Read the BQ2050HREGS registers */ + for (nAttempts = 0; nAttempts < NTXRXATTEMPTS; nAttempts++) { + /* Preset in case send fails on last retry */ + data = -1; + /* Send the READ command */ + sts = bmi_swi_send_data(i); + if (sts == -1) { + bmi_swi_break(bmi_device); + continue; /* Retry if invalid send */ + } + /* Read the return data */ + data = bmi_swi_recv_data(); + if (sts == -1) { + bmi_swi_break(bmi_device); + continue; /* Retry if invalid read */ + } + break; + } + /* JMG ??? If data is still == -1 should we do a reset ??? */ + member[i - 1] = (u_char)data; /* Store the data */ + } +#ifdef DEBUG + bmi_swi_dumpstruct(); +#endif /* DEBUG */ + + vdprintk("LEAVE: bmi_swi_fillstruct()\n"); +} + +static void +bmi_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + vdprintk("ENTER: bmi_interrupt()\n"); + + /* See if the break sequence has completed */ + if ((bmiswi->isr & SWIISR_BRIS) || (bmiswi->u.risr & SWIRISR_RBRIS)) { + bmiswi->u.eoi |= SWIEOI_RBRIS; /* clear interupt */ + vdprintk("LH7A400 BMI: bmi_interrupt(): BREAK RECOVERED\n"); + } +#ifdef USE_RX_INTERRUPT + /* See if the data word has been read from the SWI peripheral */ + if ((bmiswi->isr & SWIISR_WRIS) || (bmiswi->u.risr & SWIRISR_RWRIS)) { + vdprintk("LH7A400 BMI: bmi_interrupt(): WORD RECEIVED\n"); + bmiswi_dr = bmiswi->dr; /* clear interupt */ + vdprintk("", bmiswi_dr); + } +#endif /* USE_RX_INTERRUPT */ +#ifdef USE_TX_INTERRUPT + /* See if the data word has been written to the SWI peripheral */ + if ((bmiswi->isr & SWIISR_WTIS) || (bmiswi->u.risr & SWIRISR_RWTIS)) { + vdprintk("LH7A400 BMI: bmi_interrupt(): WORD TRANSMITTED\n"); + bmiswi->u.eoi |= SWIEOI_RWTIS; /* clear interupt */ + } +#endif /* USE_TX_INTERRUPT */ + wake_up_interruptible(&bmi_wait_q); /* Wake up our waiting processes */ + + vdprintk("LEAVE: bmi_interrupt()\n"); +} + +static void +initialize_swi(u_char device) +{ + vdprintk("ENTER: initialize_swi()\n"); + + bmiswi->cr = (SWICR_RDSS(swi_settings[device].read_size) | + SWICR_WDCS(swi_settings[device].write_size) | + ((swi_settings[device].ss_invert) ? + SWICR_SP_INVERT : 0) | + ((swi_settings[device].data_invert) ? + SWICR_SWIDINV : 0)); + + bmi_swi_enable(); + bmi_swi_break(device); + /* + * Force bmi_swi_fillstruct() to be manually called each time... + * bmi_swi_fillstruct(); + */ + vdprintk("LEAVE: initialize_swi()\n"); + + return; +} + +void +kev7a400_apm_get_power_status(u_char *ac_line_status, + u_char *battery_status, + u_char *battery_flag, + u_char *battery_percentage, + u_short *battery_life) +{ + int on_battery; + + vdprintk("ENTER: kev7a400_apm_get_power_status()\n"); + + /* See if we are on AC/DC */ + dprintk("clksc->pwrsr = 0x%08X\n", clksc->pwrsr); + if (clksc->pwrsr & (PWRSR_NBFLG | PWRSR_RSTFLG | + PWRSR_PFFLG | PWRSR_CLDFLG)) + { + vdprintk("Clearing (PWRSR_NBFLG | PWRSR_RSTFLG | PWRSR_PFFLG | PWRSR_CLDFLG)\n"); + clksc->stfclr = clksc->pwrsr; + dprintk("clksc->pwrsr = 0x%08X\n", clksc->pwrsr); + } + on_battery = clksc->pwrsr & PWRSR_DCDET; + + /* Talk to the battery and tell us what it thinks */ + bmi_swi_fillstruct(); + + /* + * Get the AC LINE STATUS + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * + * NOTE: See line in BATTERY STATUS section that adjust (a little) for + * the fact that the DCDET line doesn't work. + */ + if (on_battery) { + *ac_line_status = 0x00; + } else { + *ac_line_status = 0x01; + } + + /* + * Get the BATTERY STATUS + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + */ + if (BQ2050HREGS.flgs1 == 0xFF) { + *battery_status = 0xFF; /* Unknown */ + } else { + *battery_status = 0x00; /* High ( > 50% ) */ + if (BQ2050HREGS.flgs1 & 0x80) { + *battery_status |= 0x03; /* Charging */ + /* Account for the fact that the DCDET bit doesn't work */ + *ac_line_status = 0x01; /* AC ON-LINE */ + } else if (BQ2050HREGS.flgs1 & 0x03) { + *battery_status |= 0x02; /* Critical */ + } else if (BQ2050HREGS.rcac != 0xFF) { + if (BQ2050HREGS.rcac <= 50 ) { + *battery_status |= 0x01; /* Low ( <= 50% ) */ + } + } else { + *battery_status = 0xFF; /* Unknown */ + } + } + + /* + * Get the BATTERY FLAG + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + */ + *battery_flag = *battery_status; + + /* + * Get the BATTERY PERCENTAGE + * 0-100: valid + * 0xFF == -1: Unknown + */ + *battery_percentage = BQ2050HREGS.rcac; + + /* + * Get the BATTERY LIFE + * Number of remaining minutes or seconds (size == 0x7FFF) + * bit 0x8000: + * 0 == sec = seconds + * 1 == min = minutes + * 0xFFFF == -1: Unknown + */ +/* I'm not sure what to do here and my batteries won't hold up to find out */ + *battery_life = 0xFFFF; + + vdprintk("LEAVE: kev7a400_apm_get_power_status()\n"); +} + +void kev7a400_apm_init(void) +{ + int sts; + + vdprintk("ENTER: kev7a400_apm_init()\n"); + + printk("Sharp KEV7A400 BMI Driver Copyright 2002 Embedix\n"); + bmiswi = &bmi->swi; + bmisbi = &bmi->sbi; + init_waitqueue_head(&bmi_wait_q); + sts = request_irq(IRQ_BMI, bmi_interrupt, + SA_INTERRUPT | SA_SAMPLE_RANDOM, "bmi", NULL); + if (sts == 0) { + /* Enable Ints for Break Recovered/Word Received/Transmitted */ + bmiswi->ie = SWIIE_BRIE; +#ifdef USE_RX_INTERRUPT + bmiswi->ie |= SWIIE_WRIE; +#endif /* USE_RX_INTERRUPT */ +#ifdef USE_TX_INTERRUPT + bmiswi->ie |= SWIIE_WTIE; +#endif /* USE_TX_INTERRUPT */ + bmi_irq_enabled++; + printk("KEV7A400 BMI: IRQ %d Enabled.\n", IRQ_BMI); + } else { + printk(KERN_ERR "KEV7A400 BMI: IRQ %d already in use.\n", + IRQ_BMI); + } + + /* turn off leds D18 and D19 */ + gpio->pbdr = _BIT(1) | _BIT(2); + gpio->pcdr |= _BIT(0); + + /* Initialize the BMI SWI */ + initialize_swi(bmi_device); + + vdprintk("LEAVE: kev7a400_apm_init()\n"); +} + +void kev7a400_apm_exit(void) +{ + vdprintk("ENTER: kev7a400_apm_exit()\n"); + + bmiswi->ie = 0; /* Disable interrupts */ + free_irq (IRQ_BMI, NULL); + bmi_irq_enabled = 0; + printk("KEV7A400 BMI: IRQ %d Disabled.\n", IRQ_BMI); + + vdprintk("LEAVE: kev7a400_apm_exit()\n"); +} + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/arch.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/arch.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/arch.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/arch.c Sat Oct 18 10:38:17 2003 @@ -0,0 +1,57 @@ +/* + * linux/arch/arm/mach-lh7a400/arch.c + * + * Architecture specific fixups. + * + * Copyright (C) 2001 Lineo, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern u32 cpufreq_get( int); +extern u32 hclkfreq_get( void); +extern u32 pclkfreq_get( void); + +int lh7a400_stepping; + +void +lh7a400_show_freq_and_stepping(void) +{ + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + +#ifndef CONFIG_CPU_FREQ + printk( "FCLK=%d.%d MHz, HCLK=%d.%d MHz, PCLK=%d.%d MHz\n", + cpufreq_get(0) / 1000, cpufreq_get(0) % 1000, + hclkfreq_get() / 1000, hclkfreq_get() % 1000, + pclkfreq_get() / 1000, pclkfreq_get() % 1000); +#endif + + lh7a400_stepping = (clksc->pwrsr & PWRSR_CHIPI) >> 16; + printk( "Stepping = %d\n", lh7a400_stepping); +} + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/cpu_lh7a400.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/cpu_lh7a400.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/cpu_lh7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/cpu_lh7a400.c Thu Oct 16 16:33:58 2003 @@ -0,0 +1,83 @@ +/* + * cpu-lh7a400.c: SDRAM support for clock scaling for the Sharp LH7A400 + * Copyright (C) Embedix, Inc. + * + * based on cpu-sa1100.c, which is + * + * Copyright (C) 2000 2001, The Delft University of Technology + * + * 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 + +#define DEBUG 0 + +#if DEBUG +# define DPRINTK( args...) printk( args) +#else +# define DPRINTK( args...) +#endif + + +static int hclk_clkchg_notifier(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct hclkfreq_info *hi = data; + sdramRegs_t *sdram = (sdramRegs_t *)IO_ADDRESS(SDRAM_REGS_PHYS); + + switch(val) { + case HCLKFREQ_PRECHANGE: + if(hi->new_freq < hi->old_freq) { + DPRINTK( __FUNCTION__ ": going slower, do it before\n"); + DPRINTK( __FUNCTION__ ": reftimer = %d\n", sdram->refreshTimer); + DPRINTK( __FUNCTION__ ": setting reftimer to %d\n", + SDRAM_REFTMR_REFCNT((hi->new_freq / 64) + 1)); + sdram->refreshTimer = SDRAM_REFTMR_REFCNT((hi->new_freq / 64) + 1); + } + break; + + case HCLKFREQ_POSTCHANGE: + if(hi->new_freq > hi->old_freq) { + DPRINTK( __FUNCTION__ ": going faster, do it after\n"); + DPRINTK( __FUNCTION__ ": reftimer = %d\n", sdram->refreshTimer); + DPRINTK( __FUNCTION__ ": setting reftimer to %d\n", + SDRAM_REFTMR_REFCNT((hi->new_freq / 64) + 1)); + sdram->refreshTimer = SDRAM_REFTMR_REFCNT((hi->new_freq / 64) + 1); + } + break; + } + + return 0; +} + + +static struct notifier_block hclk_block = { + notifier_call: hclk_clkchg_notifier, +}; + + +static int __init lh7a400_sdram_init(void) +{ + return hclkfreq_register_notifier( &hclk_block); +} + +__initcall(lh7a400_sdram_init); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/dma.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/dma.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/dma.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/dma.c Mon Oct 20 16:21:50 2003 @@ -0,0 +1,1255 @@ +/* + * arch/arm/mach-lh7a400/dma.c + * + * Support functions for the Sharp LH7A400 internal DMA channels. + * + * Copyright (C) 2002 Embedix, Inc. + * + * Based on arch/arm/mach-lh79520/dma.c + * Copyright (C) 2002 Embedix, Inc. + * Based on arch/arm/mach-sa1100/dma-sa1100.c, which is + * Copyright (C) 2000 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. + * + */ + +/* +* To the best of my understanding, the LH7A400 DMA operates as follows: +* Jim Gleason - Embedix, Inc. +* +* +---------------+ +* | + +* | "IDLE" STATE | +* | +<----+ +* +-------+-------+ | +* | | +* a) IDLE -> STALL (a) | (x) | x) STALL -> IDLE +* The control register | | The control register +* has had the ENABLE | | has had the enable +* bit set. \|/ | bit cleared. +* +---------------+ | +* | +->>>-+ +* | "STALL" STATE | +* | +<----+ +* +-------+-------+ | +* | | +* b) STALL -> ON (b) | (y) | y) ON -> STALL +* The control register | | The DMA has no more +* has had its first | | buffers to work with. +* base[nextbuffer] \|/ | (zero buffers full) +* value set. +---------------+ | !!! This can generate +* (one buffer full) | +->>>-+ !!! a "STALL" interrupt. +* | "ON" STATE | +* | +<----+ +* +-------+-------+ | +* | | +* c) ON -> NEXT (c) | (z) | z) NEXT -> ON +* The control register | | The DMA finished its +* has had its second | | current buffer and has +* base[nextbuffer] \|/ | switched to its alternate +* value set. +---------------+ | buffer. +* (two buffers full) | +->>>-+ (one buffer full) +* | "NEXT" STATE | !!! This can generate +* | + !!! a "NFB" interrupt. +* +---------------+ +* +* !!! A "CHERROR" interrupt can also be generated on transmission errors. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "dma.h" + +#if 0 +#define DEBUG +#define VERBOSE +#else +#undef DEBUG +#undef VERBOSE +#endif + +#define DRVNAME "LH7X DMA" + +#ifdef DEBUG +#define DPRINTK( s, arg... ) \ + dprintk( "dma<%s>: " s, channel_context->channel_name , ##arg ) +#else /* DEBUG */ +#define DPRINTK( s, arg... ) +#endif /* DEBUG */ + +dma_regs_t *dma_regs = (dma_regs_t *)IO_ADDRESS(DMAC_PHYS); +//cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + +lh7a400_dma_context_t *lh7a400_dma_context = NULL; + +#define vdprintk if (0) printk +#define dprintk if (0) printk + +#ifdef DEBUG +/********************************************************************** +* Function: lh7a400_dump_dma_queue() +**********************************************************************/ +static inline void +lh7a400_dump_dma_queue(lh7a400_dma_channel_context_t *channel_context) +{ + dma_buf_list_t *p = channel_context->tail; + + dprintk("Q: curr=0x%p, tail=0x%p, head=0x%p, bid: ", + channel_context->curr, channel_context->tail, + channel_context->head); + + while (p) { + printk( "(0x%p 0x%p), ", p, p->id); + p = p->next; + } + printk("\n"); + + return; +} /* lh7a400_dump_dma_queue() */ +#else /* DEBUG */ +#define lh7a400_dump_dma_queue(d) +#endif /* DEBUG */ + +/* +* DMA processing... +*/ + +/********************************************************************** +* Function: lh7a400_start_dma() +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +static inline int +lh7a400_start_dma(lh7a400_dma_channel_context_t *channel_context, + dma_addr_t dma_ptr, int size) +{ + dma_channel_regs_t *channel_regs = channel_context->channel_regs; + uint32_t status; + int state; + + vdprintk("ENTER: %s()\n", __FUNCTION__); + + status = channel_regs->status; + state = status & DMAC_STATE_MASK; + + /* If both DMA buffers are started, there's nothing else we can do. */ + if (state == DMAC_STATE_NEXT) { + vdprintk("%s() - BUSY\n", __FUNCTION__); + return(-EBUSY); + } + +#if 0 // DDD + /* If there is an interrupt pending, let it happen first. */ + if (channel_regs->interrupt) { + vdprintk("%s() - IRQ Pending\n", __FUNCTION__); + return(-EAGAIN); + } +#endif + + /* + * We have an available buffer, + * Update the base[01] and maxcnt[01] register pair + * and Start the DMA for this channel and buffer + * + * NOTE: DMAC_ENABLE must be set FIRST + * and the base[01] register must be set LAST + */ + + vdprintk("%s(dma_ptr=%#x, size=%d) - buff(%d)\n", + __FUNCTION__, dma_ptr, size, status & DMAC_NEXTBUFFER ? 1:0); + + if( state == DMAC_STATE_IDLE) { + channel_regs->control = + DMAC_STALL /* Enable STALL interrupt gen */ + | DMAC_CHERROR /* Enable CHERROR interrupt gen */ + | DMAC_ENABLE /* Enable the Channel */ + /* | DMAC_ABORT *//* ??? */ + | DMAC_ICE; /* ??? */ + } + + if ((status & DMAC_NEXTBUFFER) == 0 ) { + /* Update the base0 and maxcnt0 register pair */ + channel_regs->maxcnt0 = size; + channel_regs->base0 = dma_ptr; + } else { + channel_regs->maxcnt1 = size; + channel_regs->base1 = dma_ptr; + } + + /* want to get NFB ints. */ + channel_regs->control |= DMAC_NFB; + + vdprintk("LEAVE: %s()\n", __FUNCTION__); + + return(0); +} /* lh7a400_start_dma() */ + +/********************************************************************** +* Function: lh7a400_process_dma() +* +* NOTE: This must be called with IRQ disabled +* +**********************************************************************/ +static void +lh7a400_process_dma(lh7a400_dma_channel_context_t *channel_context) +{ + dma_buf_list_t *buf; + int chunksize; + + vdprintk("ENTER: %s( channel_context=0x%p)\n", + __FUNCTION__, channel_context); + + lh7a400_dump_dma_queue(channel_context); + + for ( ; ; ) { + buf = channel_context->tail; + + if (!buf || channel_context->stopped) { + /* no more data available */ + DPRINTK("process: no more buf (dma %s), " + "buf=0x%p, stopped=%d, spin_size=%d, " + "spin_ref=%d\n", + channel_context->curr ? "active" : "inactive", + buf, channel_context->stopped, + channel_context->spin_size, + channel_context->spin_ref); + /* + * Some devices may require DMA still sending data + * at any time for clock reference, etc. + * Note: if there is still a data buffer being + * processed then the ref count is negative. This + * allows for the DMA termination to be accounted in + * the proper order. + */ + if (channel_context->spin_size && + channel_context->spin_ref >= 0) + { + chunksize = channel_context->spin_size; + if (chunksize > MAX_DMA_SIZE) + chunksize = (1 << MAX_DMA_ORDER); + while (lh7a400_start_dma( + channel_context, + channel_context->spin_addr, + chunksize) == 0) + { + channel_context->spin_ref++; + } + if (channel_context->curr != NULL) { + channel_context->spin_ref = + -channel_context->spin_ref; + } + } + break; + } + + /* + * Let's try to start DMA on the current buffer. + * If DMA is busy then we break here. + */ + chunksize = buf->size; + if (chunksize > MAX_DMA_SIZE) + chunksize = (1 << MAX_DMA_ORDER); + + DPRINTK("process: bid=%#x s=%d\n", (int) buf->id, buf->size); + + if (lh7a400_start_dma(channel_context, buf->dma_ptr, + chunksize) != 0) + break; + + if (!channel_context->curr) { + channel_context->curr = buf; + DPRINTK("process: set curr to %p\n", + channel_context->curr); + } + + buf->ref++; + buf->dma_ptr += chunksize; + buf->size -= chunksize; + if (buf->size == 0) { + /* current buffer is done: move tail to the next one */ + channel_context->tail = buf->next; + DPRINTK("process: set tail b=%#x\n", + (int) channel_context->tail); + } + } + + lh7a400_dump_dma_queue(channel_context); + + vdprintk("LEAVE: %s()\n", __FUNCTION__); +} /* lh7a400_process_dma() */ + +/********************************************************************** +* Function: lh7a400_dma_done() +* +* NOTE: This must be called with IRQ disabled +**********************************************************************/ +void +lh7a400_dma_done(lh7a400_dma_channel_context_t *channel_context) +{ + dma_buf_list_t *buf = channel_context->curr; + + vdprintk("ENTER: %s()\n", __FUNCTION__); + vdprintk( "spin_ref=%d buf=%p\n", channel_context->spin_ref, buf); + + if (channel_context->spin_ref > 0) { + channel_context->spin_ref--; + } else if (buf) { + buf->ref--; + if (buf->ref == 0 && buf->size == 0) { + /* + * Current buffer is done. + * Move current reference to the next one and send + * the processed buffer to the callback function, + * then discard it. + */ + DPRINTK("IRQ: buf done: set curr to %p\n", buf->next); + channel_context->curr = buf->next; + if (channel_context->curr == NULL) + channel_context->spin_ref = + -channel_context->spin_ref; + + if (channel_context->head == buf) + channel_context->head = NULL; + + if (channel_context->callback) { + int size = buf->dma_ptr - buf->dma_start; + channel_context->callback(buf->id, size); + } + + kfree(buf); + } + } + + lh7a400_process_dma(channel_context); + + vdprintk("LEAVE: %s()\n", __FUNCTION__); + + return; +} /* lh7a400_dma_done() */ + +/********************************************************************** +* Function: lh7a400_dma_channel_stall_irq_handler() +* +* This interrupt handler handles the "stall" interrupt +* for the IRQ for the channel specified +* by lh7a400_dma_channel_irq_handler(). +* +* NOTE: The DMA doesn't have any buffers to work with (both are empty). +* +**********************************************************************/ +static inline void +lh7a400_dma_channel_stall_irq_handler(lh7a400_dma_context_t *dma_context, + lh7a400_dma_channel_context_t *channel_context) +{ + vdprintk( "channel_context=0x%p channel_regs=0x%p\n", + channel_context, channel_context->channel_regs); + lh7a400_dma_done(channel_context); + + /* + * Turn off the controller to prevent aflood of + * these stall interrupts. + */ + channel_context->channel_regs->control &= ~DMAC_ENABLE; + /* JMG - Further action TBD */ +} /* lh7a400_dma_channel_stall_irq_handler() */ + +/********************************************************************** +* Function: lh7a400_dma_channel_nfb_irq_handler() +* +* This interrupt handler handles the "nfb" interrupt +* for the IRQ for the channel specified +* by lh7a400_dma_channel_irq_handler(). +* +* NOTE: The DMA has finished a buffer and is now working on the alternate. +* +**********************************************************************/ +static inline void +lh7a400_dma_channel_nfb_irq_handler(lh7a400_dma_context_t *dma_context, + lh7a400_dma_channel_context_t *channel_context) +{ + lh7a400_dma_done(channel_context); + /* JMG - Further action TBD */ +} /* lh7a400_dma_channel_nfb_irq_handler() */ + +/********************************************************************** +* Function: lh7a400_dma_channel_cherror_irq_handler() +* +* This interrupt handler handles the "cherror" interrupt +* for the IRQ for the channel specified +* by lh7a400_dma_channel_irq_handler(). +* +* NOTE: The last buffer transfer terminated with an error. +* +**********************************************************************/ +static inline void +lh7a400_dma_channel_cherror_irq_handler(lh7a400_dma_context_t *dma_context, + lh7a400_dma_channel_context_t *channel_context) +{ + /* Clear the error by writing "anything" to the interrupt register */ + channel_context->channel_regs->interrupt = DMAC_CHERROR; + dprintk("DMAC_CHERROR on %s\n", channel_context->channel_name); + /* JMG - Further action TBD */ +} /* lh7a400_dma_channel_cherror_irq_handler() */ + +/********************************************************************** +* Function: lh7a400_dma_channel_irq_handler() +* +* This interrupt handler handles the IRQ for the channel specified +* by lh7a400_dma_irq_handler(). +* +**********************************************************************/ +static inline void +lh7a400_dma_channel_irq_handler(lh7a400_dma_context_t *dma_context, + lh7a400_dma_channel_context_t *channel_context) +{ + uint32_t interrupt = channel_context->channel_regs->interrupt; + + vdprintk("%s regs=%p, chan_interrupt=0x%x\n", + __FUNCTION__, channel_context->channel_regs, interrupt); + + if (interrupt & DMAC_CHERROR) { + /* The last buffer transfer terminated with an error */ + lh7a400_dma_channel_cherror_irq_handler(dma_context, + channel_context); + } + if (interrupt & DMAC_STALL) { + /* DMA has no buffers to work with (both empty) */ + lh7a400_dma_channel_stall_irq_handler(dma_context, + channel_context); + } + if (interrupt & DMAC_NFB) { + dma_channel_regs_t *channel_regs = + channel_context->channel_regs; + + channel_regs->control &= ~DMAC_NFB; // only need one + /* DMA has finished a buffer and is working on the alternate */ + lh7a400_dma_channel_nfb_irq_handler(dma_context, + channel_context); + } + + return; +} /* lh7a400_dma_channel_irq_handler() */ + +/********************************************************************** +* Function: lh7a400_dma_irq_handler() +* +* This interrupt handler only directs traffic for the interrupts +* by forwarding on the call to the appropriate interrupt handler. +* +**********************************************************************/ +static void +lh7a400_dma_irq_handler(int irq, void *context, struct pt_regs *regs) +{ + lh7a400_dma_context_t *dma_context = (lh7a400_dma_context_t *)context; + lh7a400_dma_channel_context_t *channel_context = NULL; + uint32_t global_int; + int bit; + int channel_num; + + dma_regs_t *dma_regs = dma_context->dma_regs; + + /* Find out all who are interrupting, and act accordingly */ + global_int = dma_regs->dma_global_int & DMAC_INTMASK; + + vdprintk("\nENTER: %s() global_int=0x%x\n", __FUNCTION__, global_int); + + channel_num = 0; + for (bit = 1; bit & DMAC_INTMASK; bit <<= 1) { + if (bit & global_int) { + channel_context = + &dma_context->channel_context[channel_num]; + + vdprintk( "channel_num=%d\n", channel_num); + + lh7a400_dma_channel_irq_handler(dma_context, + channel_context); + } + channel_num++; + } + + vdprintk("LEAVE: %s()\n", __FUNCTION__); + + return; +} /* lh7a400_dma_irq_handler() */ + +/* +* DMA interface functions +*/ + +static spinlock_t lh7a400_dma_list_lock; + +/********************************************************************** +* Function: lh7a400_request_dma() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_request_dma(dmach_t *channel, const char *device_name, + dma_channel_t channel_requested) +{ + lh7a400_dma_channel_context_t *channel_context = NULL; + int err = 0; + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + + dprintk("ENTER: %s(device_name=%s, channel_requested=%d)\n", + __FUNCTION__, device_name, (int)channel_requested); + + /* be sure we catch the freeing of misregistered channels */ + *channel = -1; + + if ((unsigned)channel_requested >= n_LH7A400_DMA_CHANNELS) + return(-ECHRNG); /* Channel number out of range */ + + if (lh7a400_dma_context->channel_context[channel_requested].in_use) + return(-EBUSY); + + spin_lock(&lh7a400_dma_list_lock); + + /* + * Allocate a channel on the LH7A400. + * On the lh7a400 channels are as follows (see dma_channel_t): + * 0 == Universal Serial bus (USB) Rx + * 1 == Universal Serial bus (USB) Tx + * 2 == Multi-Media Card (MMC) Rx + * 3 == Multi-Media Card (MMC) Tx + * 4 == Advanced Audio Controller (AAC) 0 Rx + * 5 == Advanced Audio Controller (AAC) 0 Tx + * 6 == Advanced Audio Controller (AAC) 1 Rx + * 7 == Advanced Audio Controller (AAC) 1 Tx + * 8 == Advanced Audio Controller (AAC) 2 Rx + * 9 == Advanced Audio Controller (AAC) 2 Tx + */ + + switch( channel_requested) { + case DMA_USB_Rx: + case DMA_USB_Tx: + case DMA_MMC_Rx: + case DMA_MMC_Tx: + case DMA_AAC_0_Rx: + case DMA_AAC_0_Tx: + case DMA_AAC_1_Rx: + case DMA_AAC_1_Tx: + case DMA_AAC_2_Rx: + case DMA_AAC_2_Tx: + break; + + default: + err = -ENOSR; + break; + } + + if ( ! err) { + *channel = channel_requested; + channel_context = + &lh7a400_dma_context->channel_context[*channel]; + channel_context->in_use = 1; + } + + spin_unlock(&lh7a400_dma_list_lock); + + if (err) + return(err); + + channel_context->callback = NULL; + channel_context->spin_size = 0; + + dprintk("ENTER: %s(channel=%d,device_name=%s,channel_requested=%d)\n", + __FUNCTION__, *channel, device_name, (int)channel_requested); + + /* turn on the clock to this DMA channel */ + clksc->pwrcnt |= 1 << (channel_requested + 16); + + return(0); +} /* lh7a400_request_dma() */ + +/********************************************************************** +* Function: lh7a400_dma_set_callback() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_set_callback(dmach_t channel, dma_callback_t cb) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || !channel_context->in_use) + return(-EINVAL); + + channel_context->callback = cb; + + vdprintk("LEAVE: %s(channel=%d, cb=%p)\n", + __FUNCTION__, (int)channel, cb); + + return(0); +} /* lh7a400_dma_set_callback() */ + +/********************************************************************** +* Function: lh7a400_dma_set_spin() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_set_spin(dmach_t channel, dma_addr_t addr, int size) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int flags; + + vdprintk("ENTER: %s(channel=%d,size=%d,addr=%#x,channel_context=%p)\n", + __FUNCTION__, (int)channel, size, addr, channel_context); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + local_irq_save(flags); + + channel_context->spin_addr = addr; + channel_context->spin_size = size; + + if (size) + lh7a400_process_dma(channel_context); + + local_irq_restore(flags); + + vdprintk("LEAVE: %s(channel=%d, size=%d, addr=%#x)\n", + __FUNCTION__, (int)channel, size, addr); + + return(0); +} /* lh7a400_dma_set_spin() */ + +/********************************************************************** +* Function: lh7a400_dma_queue_buffer() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_queue_buffer(dmach_t channel, void *buf_id, + dma_addr_t data, int size) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + dma_buf_list_t *buf; + int flags; + + vdprintk("ENTER: %s(channel=%d, buf_id=%#x, data=%#x, size=%d)\n", + __FUNCTION__, (int)channel, (int)buf_id, data, size); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + buf = kmalloc(sizeof(*buf), GFP_KERNEL | GFP_DMA | GFP_ATOMIC); + if (!buf) + return(-ENOMEM); + + buf->next = NULL; + buf->ref = 0; + buf->dma_ptr = buf->dma_start = data; + buf->size = size; + buf->id = buf_id; + + local_irq_save(flags); + + if (channel_context->head) + channel_context->head->next = buf; + + channel_context->head = buf; + if (!channel_context->tail) + channel_context->tail = buf; + + lh7a400_process_dma(channel_context); + + local_irq_restore(flags); + + vdprintk("LEAVE: %s(channel=%d, buf_id=%#x, data=%#x, size=%d)\n", + __FUNCTION__, (int)channel, (int)buf_id, data, size); + + return(0); +} /* lh7a400_dma_queue_buffer() */ + +/********************************************************************** +* Function: lh7a400_dma_get_current() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int flags, ret; + dma_channel_regs_t *channel_regs; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + channel_regs = channel_context->channel_regs; + local_irq_save(flags); + if (channel_context->curr && channel_context->spin_ref <= 0) { + dma_buf_list_t *buf = channel_context->curr; + + /* + * If we got here, that's because there is, or recently was, a + * buffer being processed. Two possibilities: either we are + * in the middle of a buffer, or the DMA controller just + * switched to the next toggle but the interrupt hasn't been + * serviced yet. The former case is straight forward. In + * the later case, we'll do like if DMA is just at the end + * of the previous toggle since all registers haven't been + * reset yet. This goes around the edge case and since we're + * always a little behind anyways it shouldn't make a big + * difference. If DMA has been stopped prior calling this + * then the position is always exact. + */ + if (buf_id) + *buf_id = buf->id; + + /* JMG - These current[01] registers may need swapped ??? */ + if ((channel_regs->status & DMAC_NEXTBUFFER) == 0) { + *addr = channel_regs->current0; + } else { + *addr = channel_regs->current1; + } + + vdprintk("%s(c0=%x c1=%x *addr=%x)\n", __FUNCTION__, + channel_regs->current0, channel_regs->current1, + *addr); + + /* + * Clamp funky pointers sometimes returned by the hardware + * on completed DMA transfers + */ + if (*addr < buf->dma_start || *addr > buf->dma_ptr) + *addr = buf->dma_ptr; + DPRINTK("curr_pos: b=%#x a=%#x\n", + (int)channel_context->curr->id, *addr); + ret = 0; + } else if (channel_context->tail && channel_context->stopped) { + dma_buf_list_t *buf = channel_context->tail; + if (buf_id) + *buf_id = buf->id; + *addr = buf->dma_ptr; + vdprintk("%s 1 ( *addr=%x)\n", __FUNCTION__, *addr); + ret = 0; + } else { + if (buf_id) + *buf_id = NULL; +#if 0 // DDD + *addr = 0; + ret = -ENXIO; +#else + if ((channel_regs->status & DMAC_NEXTBUFFER) == 0) { + *addr = channel_regs->current1; + } else { + *addr = channel_regs->current0; + } + + vdprintk("%s 2 (c0=%x c1=%x *addr=%x)\n", __FUNCTION__, + channel_regs->current0, channel_regs->current1, + *addr); + + ret = 0; +#endif + } + local_irq_restore(flags); + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(ret); +} /* lh7a400_dma_get_current() */ + +/********************************************************************** +* Function: lh7a400_dma_stop() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_stop(dmach_t channel) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int flags; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + if (channel_context->stopped) + return(0); + + local_irq_save(flags); + + channel_context->stopped = 1; + + /* + * Stop DMA and tweak state variables so everything could restart + * from there when resume/wakeup occurs. + */ + channel_context->channel_regs->control &= ~DMAC_ENABLE; + channel_context->channel_regs->control &= + ~(DMAC_STALL | DMAC_NFB | DMAC_CHERROR); + /* JMG - TBD if any additional tweaking needs done */ + + if (channel_context->curr) { + dma_buf_list_t *buf = channel_context->curr; + if (channel_context->spin_ref <= 0) { + dma_addr_t curpos; + lh7a400_dma_get_current(channel, NULL, &curpos); + buf->size += buf->dma_ptr - curpos; + buf->dma_ptr = curpos; + } + buf->ref = 0; + channel_context->tail = buf; + channel_context->curr = NULL; + } + channel_context->spin_ref = 0; + + lh7a400_process_dma(channel_context); + + local_irq_restore(flags); + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(0); +} /* lh7a400_dma_stop() */ + +/********************************************************************** +* Function: lh7a400_dma_resume() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_resume(dmach_t channel) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int flags; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + if (channel_context->stopped) { + save_flags_cli(flags); + channel_context->stopped = 0; + channel_context->spin_ref = 0; + lh7a400_process_dma(channel_context); + restore_flags(flags); + } + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(0); +} /* lh7a400_dma_resume() */ + +/********************************************************************** +* Function: lh7a400_dma_flush_all() +* +* NOTE: This function is exported! +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_flush_all(dmach_t channel) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + dma_buf_list_t *buf, *next_buf; + int flags; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + lh7a400_dump_dma_queue(channel_context); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + local_irq_save(flags); + + /* + * Disable the channel, and mask off its interrupts + */ + channel_context->channel_regs->control &= ~DMAC_ENABLE; + channel_context->channel_regs->control &= + ~(DMAC_STALL | DMAC_NFB | DMAC_CHERROR); + /* JMG - TBD if any additional "tweaking needs done */ + + buf = channel_context->curr; + if (!buf) + buf = channel_context->tail; + + channel_context->curr = NULL; + channel_context->head = NULL; + channel_context->tail = NULL; + channel_context->stopped = 0; + channel_context->spin_ref = 0; + + lh7a400_process_dma(channel_context); + + local_irq_restore(flags); + + while (buf) { + next_buf = buf->next; + kfree(buf); + buf = next_buf; + } + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(0); +} /* lh7a400_dma_flush_all() */ + +/********************************************************************** +* Function: lh7a400_free_dma() +* +* NOTE: This function is exported! +* +**********************************************************************/ +void +lh7a400_free_dma(dmach_t channel) +{ + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS) { + printk(KERN_ERR "Freeing invalid DMA channel (%d)\n", + (int)channel); + return; + } + if (!channel_context->in_use) { + printk(KERN_ERR "Freeing unallocated DMA channel (%d)\n", + (int)channel); + return; + } + + lh7a400_dma_set_spin(channel, 0, 0); + lh7a400_dma_flush_all(channel); + + channel_context->in_use = 0; + + /* turn off the clock to this DMA channel */ + clksc->pwrcnt &= ~(1 << (channel_context->channel_num + 16) ); + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return; +} /* lh7a400_free_dma() */ + +#if 1 || defined(CONFIG_SYMTAB) +EXPORT_SYMBOL(lh7a400_request_dma); +EXPORT_SYMBOL(lh7a400_dma_set_callback); +EXPORT_SYMBOL(lh7a400_dma_set_spin); +EXPORT_SYMBOL(lh7a400_dma_queue_buffer); +EXPORT_SYMBOL(lh7a400_dma_get_current); +EXPORT_SYMBOL(lh7a400_dma_stop); +EXPORT_SYMBOL(lh7a400_dma_resume); +EXPORT_SYMBOL(lh7a400_dma_flush_all); +EXPORT_SYMBOL(lh7a400_free_dma); +#endif /* CONFIG_SYMTAB */ + +#ifdef CONFIG_PM +/********************************************************************** +* Function: lh7a400_dma_sleep() +* +* NOTE: This function is exported! +* +* NOTE: Drivers should call this from their PM callback function. +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_sleep(dmach_t channel) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int orig_state; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + orig_state = channel_context->stopped; + lh7a400_dma_stop(channel); + channel_context->channel_regs->control &= ~DMAC_ENABLE; + channel_context->channel_regs->control &= + ~(DMAC_STALL | DMAC_NFB | DMAC_CHERROR); + /* JMG - TBD if any additional "tweaking needs done */ + + channel_context->stopped = orig_state; + channel_context->spin_ref = 0; + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(0); +} /* lh7a400_dma_sleep() */ + +/********************************************************************** +* Function: lh7a400_dma_wakeup() +* +* NOTE: This function is exported! +* +* NOTE: Drivers should call this from their PM callback function. +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +int +lh7a400_dma_wakeup(dmach_t channel) +{ + lh7a400_dma_channel_context_t *channel_context = + &lh7a400_dma_context->channel_context[channel]; + int flags; + + vdprintk("ENTER: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + if ((unsigned)channel >= n_LH7A400_DMA_CHANNELS || + !channel_context->in_use) + return(-EINVAL); + + channel_context->channel_regs->control &= ~DMAC_ENABLE; + channel_context->channel_regs->control &= + ~(DMAC_STALL | DMAC_NFB | DMAC_CHERROR); + /* JMG - TBD if any additional "tweaking needs done */ + + local_irq_save(flags); + + lh7a400_process_dma(channel_context); + + local_irq_restore(flags); + + vdprintk("LEAVE: %s(channel=%d)\n", __FUNCTION__, (int)channel); + + return(0); +} /* lh7a400_dma_wakeup */ + +#if 1 || defined(CONFIG_SYMTAB) +EXPORT_SYMBOL(lh7a400_dma_sleep); +EXPORT_SYMBOL(lh7a400_dma_wakeup); +#endif /* CONFIG_SYMTAB */ + +#endif /* CONFIG_PM */ + +/********************************************************************** +* Function: lh7a400_init_dma_channel() +* +* NOTE: Prior to this being called, everything was zeroed... +* +**********************************************************************/ +static void +lh7a400_init_dma_channel(lh7a400_dma_channel_context_t *channel_context, + const char *channel_name, dma_channel_t channel_num, + dma_channel_regs_t *channel_regs, dma_direction_t direction) +{ + vdprintk("ENTER: %s()\n", __FUNCTION__); + + /* Context variables */ + channel_context->channel_name = channel_name; + channel_context->channel_num = channel_num; + channel_context->channel_regs = channel_regs; + channel_context->direction = direction; + + /* Control variable(s) */ + channel_regs->control = 0; + + /* Buffer 0 variables */ + channel_regs->maxcnt0 = 0; + channel_regs->base0 = 0; + channel_regs->current0 = 0; + + /* Buffer 1 variables */ + channel_regs->maxcnt1 = 0; + channel_regs->base1 = 0; + channel_regs->current1 = 0; + + vdprintk("LEAVE: %s()\n", __FUNCTION__); + + return; +} + +/********************************************************************** +* Function: lh7a400_init_dma() +* +* Returns: +* SUCCESS == 0 +* FAILURE != 0 +* +**********************************************************************/ +static int __init +lh7a400_init_dma(void) +{ + int channel_num; + lh7a400_dma_channel_context_t *channel_context; + char *channel_name = NULL; + dma_channel_regs_t *channel_regs = NULL; + dma_direction_t direction = DMA_RX; /* Init to quiet gcc */ + int sts; + + vdprintk("ENTER: %s()\n", __FUNCTION__); + + /* + * Initialize the context structure(s) + */ + lh7a400_dma_context = &static_lh7a400_dma_context; + + /* Zero out everything */ + memset(lh7a400_dma_context, 0, sizeof(lh7a400_dma_context_t)); + + /* Point to the actual DMA registers */ + lh7a400_dma_context->dma_regs = (dma_regs_t *)IO_ADDRESS(DMAC_PHYS); + + /* Initialize the individual stream and channel context structures */ + for (channel_num = 0; channel_num < n_LH7A400_DMA_CHANNELS; channel_num++) { + channel_context = &lh7a400_dma_context->channel_context[channel_num]; + switch (channel_num) { + case DMA_USB_Rx: + channel_name = "USB_RX"; + channel_regs = &lh7a400_dma_context->dma_regs->usb_rx; + direction = DMA_RX; + break; + case DMA_USB_Tx: + channel_name = "USB_TX"; + channel_regs = &lh7a400_dma_context->dma_regs->usb_tx; + direction = DMA_TX; + break; + case DMA_MMC_Rx: + channel_name = "MMC_RX"; + channel_regs = &lh7a400_dma_context->dma_regs->mmc_rx; + direction = DMA_RX; + break; + case DMA_MMC_Tx: + channel_name = "MMC_TX"; + channel_regs = &lh7a400_dma_context->dma_regs->mmc_tx; + direction = DMA_TX; + break; + case DMA_AAC_0_Rx: + channel_name = "AAC_0_RX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_0_rx; + direction = DMA_RX; + break; + case DMA_AAC_0_Tx: + channel_name = "AAC_0_TX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_0_tx; + direction = DMA_TX; + break; + case DMA_AAC_1_Rx: + channel_name = "AAC_1_RX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_1_rx; + direction = DMA_RX; + break; + case DMA_AAC_1_Tx: + channel_name = "AAC_1_TX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_1_tx; + direction = DMA_TX; + break; + case DMA_AAC_2_Rx: + channel_name = "AAC_2_RX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_2_rx; + direction = DMA_RX; + break; + case DMA_AAC_2_Tx: + channel_name = "AAC_2_TX"; + channel_regs = &lh7a400_dma_context->dma_regs->aac_2_tx; + direction = DMA_TX; + break; + } + + lh7a400_init_dma_channel(channel_context, channel_name, + channel_num, channel_regs, direction); + } + + lh7a400_dma_context->irq = IRQ_DMA; + sts = request_irq(lh7a400_dma_context->irq, lh7a400_dma_irq_handler, + SA_INTERRUPT, DRVNAME, (void *)lh7a400_dma_context); + if (sts) { + printk(KERN_ERR "unable to request IRQ %d for DMA.\n", + lh7a400_dma_context->irq); + return(sts); + } + + vdprintk("LEAVE: %s()\n", __FUNCTION__); + + return(0); +} /* lh7a400_init_dma() */ + +__initcall(lh7a400_init_dma); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/dma.h linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/dma.h --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/dma.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/dma.h Sun Feb 8 20:39:36 2004 @@ -0,0 +1,224 @@ +/* + * linux/arch/arm/mach-lh7a400/dma.h + * + * Based on arch/arm/mach-lh79520/dma.h + * Copyright (C) 2002 Embedix, Inc. + * Based on arch/arm/mach-sa1100/dma.h which is + * (C) 2000 Nicolas Pitre + * + * Copyright (C) 2002 Embedix, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * References: + * Sharp LH7A400 Programming Manual + */ + +#ifndef _ARCH_ARM_MACH_LH7A400_DMA_H +#define _ARCH_ARM_MACH_LH7A400_DMA_H + +#include +#include +//#include + +#include + +/* +* DMA buffer list structure +*/ + +typedef struct dma_buf_list_t dma_buf_list_t; +struct dma_buf_list_t { + int size; /* buffer size */ + dma_addr_t dma_start; /* starting DMA address */ + dma_addr_t dma_ptr; /* next DMA pointer to use */ + int ref; /* number of DMA references */ + void *id; /* to identify buffer from outside */ + dma_buf_list_t *next; /* next buffer to process */ +}; + +typedef enum { + DMA_OUT, + DMA_IN +} dma_direction_t; +#define DMA_RX DMA_IN +#define DMA_TX DMA_OUT + +/* +* DMA channel registers structure +* +* The following structure declaration allows referencing the status +* register either by bit field or by 32-bit register. +* This allows any of the following constructs to be used, to retrieve +* the currentstate bit field for example, once DMAC is defined properly, +* e.g., #define DMAC ((DMACREGS *)(DMAC_REGS_BASE)): +* +* tmp = DMAC->usbrx.status.bf.currentstate; +* or +* tmp = DMAC_CURRENTSTATE(DMAC->usbrx.status.r); +* or +* tmp = (DMAC->usbrx.status.r & 0x30) >> 4; +*/ +typedef struct dma_status_bits_t dma_status_bits_t; +struct dma_status_bits_t { + volatile uint32_t stall : 1; + volatile uint32_t nfb : 1; + const uint32_t: 1; + volatile uint32_t cherror : 1; + volatile uint32_t currentstate : 2; + volatile uint32_t nextbuffer : 1; + volatile uint32_t bytes : 5; + const uint32_t: 0; +}; + +typedef struct dma_channel_regs_t dma_channel_regs_t; +struct dma_channel_regs_t { + volatile uint32_t control; /* Control */ + volatile uint32_t interrupt; /* Interrupt */ + volatile uint32_t reserved1; + volatile uint32_t status; /* Status */ + volatile uint32_t reserved2; + volatile uint32_t remain; /* Bytes Remaining */ + volatile uint32_t reserved3[2]; + volatile uint32_t maxcnt0; /* Maximum byte count */ + volatile uint32_t base0; /* Base Address */ + volatile uint32_t current0; /* Current Address */ + volatile uint32_t reserved4; + volatile uint32_t maxcnt1; /* Maximum byte count */ + volatile uint32_t base1; /* Base Address */ + volatile uint32_t current1; /* Current Address */ + volatile uint32_t reserved5; +}; + +/* +* DMA channel registers structure +*/ +typedef struct dma_regs_t dma_regs_t; +struct dma_regs_t { + dma_channel_regs_t usb_rx; + dma_channel_regs_t usb_tx; + dma_channel_regs_t mmc_rx; + dma_channel_regs_t mmc_tx; + dma_channel_regs_t reserved0[4]; + dma_channel_regs_t aac_0_rx; + dma_channel_regs_t aac_0_tx; + dma_channel_regs_t aac_1_rx; + dma_channel_regs_t aac_1_tx; + dma_channel_regs_t aac_2_rx; + dma_channel_regs_t aac_2_tx; + dma_channel_regs_t reserved1; + volatile uint32_t dma_global_int; + volatile uint32_t reserved2[15]; +}; + +/*********************************************************************** +* DMA Channel Control Register Bit Fields +* DMA Channel Interrupt Register Bit Fields +* DMA Channel Status Register Bit Fields +**********************************************************************/ +#define DMAC_STALL _BIT(0) +#define DMAC_NFB _BIT(1) +#define DMAC_CHERROR _BIT(3) +#define DMAC_ENABLE _BIT(4) +#define DMAC_ABORT _BIT(5) +#define DMAC_ICE _BIT(6) +#define DMAC_NEXTBUFFER _BIT(6) +#define DMAC_CURRENTSTATE(n) (((n)&0x30) >> 4) +#define DMAC_STATUS_BYTES(n) (((n)&0xF80) >> 7) + +/* +* Note: The following STATE values have NOT been shifted +* and would need shifted with/if using the DMAC_CURRENTSTATE(n) macro. +*/ +#define DMAC_STATE_IDLE 0x0000 +#define DMAC_STATE_STALL 0x0010 +#define DMAC_STATE_ON 0x0020 +#define DMAC_STATE_NEXT 0x0030 +#define DMAC_STATE_MASK 0x0030 + +/*********************************************************************** +* DMA Global Interrupt Register Bit Fields +**********************************************************************/ +#define DMAC_USBTXINT _BIT(0) +#define DMAC_USBRXINT _BIT(1) +#define DMAC_MMCTXINT _BIT(2) +#define DMAC_MMCRXINT _BIT(3) +#define DMAC_AACRX0INT _BIT(4) +#define DMAC_AACTX0INT _BIT(5) +#define DMAC_AACRX1INT _BIT(6) +#define DMAC_AACTX1INT _BIT(7) +#define DMAC_AACRX2INT _BIT(8) +#define DMAC_AACTX2INT _BIT(9) + +#define DMAC_INTMASK \ + ( \ + DMAC_USBTXINT | \ + DMAC_USBRXINT | \ + DMAC_MMCTXINT | \ + DMAC_MMCRXINT | \ + DMAC_AACRX0INT | \ + DMAC_AACTX0INT | \ + DMAC_AACRX1INT | \ + DMAC_AACTX1INT | \ + DMAC_AACRX2INT | \ + DMAC_AACTX2INT \ + ) + +#define n_LH7A400_DMA_CHANNELS (5 * 2) + +/* +* DMA context structures. +*/ + +typedef struct lh7a400_dma_channel_context_t lh7a400_dma_channel_context_t; +struct lh7a400_dma_channel_context_t { + const char *channel_name; /* Channel name */ + dma_channel_t channel_num; /* Channel number */ + dma_channel_regs_t *channel_regs;/* Adrress of actual DMA Registers */ + + dma_direction_t direction; /* DMA direction: 0=Out / 1=In */ + + dma_buf_list_t *head; /* where to insert buffers */ + dma_buf_list_t *tail; /* where to remove buffers */ + dma_buf_list_t *curr; /* buffer currently DMA'ed */ + + unsigned int in_use; /* Stream is allocated */ + int stopped; /* 1 if DMA is stalled */ + + dma_callback_t callback; /* What to call when buffers are done */ + + int spin_size; /* > 0 when DMA should spin when no more buffer */ + dma_addr_t spin_addr; /* DMA address to spin onto */ + int spin_ref; /* number of spinning references */ +}; + +typedef struct lh7a400_dma_context_t lh7a400_dma_context_t; + +struct lh7a400_dma_context_t { + int irq; /* All channels share a common IRQ */ + dma_regs_t *dma_regs; + lh7a400_dma_channel_context_t channel_context[n_LH7A400_DMA_CHANNELS]; +}; + +lh7a400_dma_context_t static_lh7a400_dma_context; + +/* +* Maximum physical DMA buffer size +*/ +#define MAX_DMA_SIZE 0xffff +#define MAX_DMA_ORDER 15 + +#endif /* _ARCH_ARM_MACH_LH7A400_DMA_H */ + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/eframe.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/eframe.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/eframe.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/eframe.c Wed Nov 19 22:04:09 2003 @@ -0,0 +1,138 @@ +/* + * linux/arch/arm/mach-lh7a400/eframe.c + * + * Machine (board) specific fixups. + * + * Copyright (C) 2003 Brad Parker + * + * 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 + +extern void genarch_init_irq( void); +extern void lh7a400_show_freq_and_stepping(void); + +#define USE_BLOB_PARAMS + +#define IO_RW DOMAIN_IO, 0, 1, 0, 0 + +static struct map_desc lh7a400_io_desc[] __initdata = { +/* virt phys size r w c b */ +{ FLASH_BASE, FLASH_START, FLASH_SIZE, IO_RW }, +{ INT_SRAM_BASE, INT_SRAM_START, INT_SRAM_SIZE, IO_RW }, +{ CPLD_BASE, CPLD_START, CPLD_SIZE, IO_RW }, +{ CS8900_BASE, CS8900_START, CS8900_SIZE, IO_RW }, +{ IDE_BASE, IDE_START, IDE_SIZE, IO_RW }, +{ IDE2_BASE, IDE2_START, IDE2_SIZE, IO_RW }, +{ EXPBRD_BASE, EXPBRD_START, EXPBRD_SIZE, IO_RW }, +{ APB_BASE, APB_START, APB_SIZE, IO_RW }, +{ AHB_BASE, AHB_START, AHB_SIZE, IO_RW }, +{ PCMCIA_IO_0_BASE, PCMCIA_IO_0_START, PCMCIA_IO_0_SIZE, IO_RW }, +{ PCMCIA_IO_1_BASE, PCMCIA_IO_1_START, PCMCIA_IO_1_SIZE, IO_RW }, +{ PCMCIA_STATUS_BASE, PCMCIA_STATUS_START, PCMCIA_STATUS_SIZE, IO_RW }, +LAST_DESC +}; + +void __init lh7a400_map_io(void) +{ + iotable_init(lh7a400_io_desc); +} + +static void __init +fixup_lh7a400(struct machine_desc *desc, struct param_struct *unused, + char **cmdline, struct meminfo *mi) +{ +#ifndef USE_BLOB_PARAMS + /* 16 banks: 64 MB SDRAM 8 nodes */ + mi->nr_banks = 16; + + for (i = 0; i < 16; i++) { + mi->bank[i].start = 0; + mi->bank[i].size = (4*1024*1024); + mi->bank[i].node = i/2; + } + + mi->bank[0].start = 0xc0000000; + mi->bank[1].start = 0xc1000000; + mi->bank[2].start = 0xc4000000; + mi->bank[3].start = 0xc5000000; + mi->bank[4].start = 0xc8000000; + mi->bank[5].start = 0xc9000000; + mi->bank[6].start = 0xcc000000; + mi->bank[7].start = 0xcd000000; + + mi->bank[8].start = 0xd0000000; + mi->bank[9].start = 0xd1000000; + mi->bank[10].start = 0xd4000000; + mi->bank[11].start = 0xd5000000; + mi->bank[12].start = 0xd8000000; + mi->bank[13].start = 0xd9000000; + mi->bank[14].start = 0xdc000000; + mi->bank[15].start = 0xdd000000; + +#if 0 /* use ramdisk root */ + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); + setup_initrd( __phys_to_virt(0xc4000000), 3 * 1024 * 1024); + + /* Serial Console on UART 1, root on ramdisk */ + strcpy( *cmdline, "console=ttyAM1,115200 root=/dev/ram0 ip=bootp"); +#else /* use nfs root */ + /* Serial Console on UART 1 root over NFS */ + strcpy( *cmdline, "console=ttyAM1,115200 noinitrd root=/dev/nfs ip=bootp"); +#endif /* ramdisk or nfs root */ + +#endif /* USE_BLOB_PARAMS */ + + lh7a400_show_freq_and_stepping(); +} + +void +lh7a400_apm_get_power_status(u_char *ac_line_status, + u_char *battery_status, + u_char *battery_flag, + u_char *battery_percentage, + u_short *battery_life) +{ + *ac_line_status = 0x01; + *battery_status = 0xFF; /* Unknown */ + *battery_flag = *battery_status; + *battery_percentage = 0xff; + *battery_life = 0xFFFF; +} + +MACHINE_START(LH7A400EVB, "Heeltoe eframe board") + MAINTAINER("brad@heeltoe.com") + BOOT_MEM(0xC0000000, 0x80000000, 0xF8000000) // pio, vio must be 8MB +#ifdef USE_BLOB_PARAMS + BOOT_PARAMS(0xC0000100) +#endif /* USE_BLOB_PARAMS */ + FIXUP(fixup_lh7a400) + MAPIO(lh7a400_map_io) + INITIRQ(genarch_init_irq) +MACHINE_END + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/fiqhandler.S linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/fiqhandler.S --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/fiqhandler.S Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/fiqhandler.S Thu Oct 16 14:12:30 2003 @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/lib/lh7a400-fiqhandler.S + * Copyright (C) 2002, Lineo, Inc. + * based on linux/arch/arm/lib/floppydma.S, which is + * Copyright (C) 1995, 1996 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 + .text + + .global SYMBOL_NAME(fiqhandler_end) + + @ register usage: + @ r8 &interrupt controller registers + @ r9 &gpio registers + @ r11 work + @ r12 work + +ENTRY(fiqhandler) + + @ read the status register to find out which FIQ this is + + ldr r12, [r8] @ intc->status + and r12, r12, #0xf @ only interested in low-order 4 bits + + @ translate FIQ 0:3 to IRQ 23:26 + @ disable this FIQ and enable the corresponding IRQ + + str r12, [r8, #0xc] @ disable this FIQ + mov r12, r12, lsl #23 @ get the corresopnding IRQ bit + str r12, [r8, #0x8] @ enable that IRQ + + subs pc, lr, #4 +SYMBOL_NAME(fiqhandler_end): + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/generic.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/generic.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/generic.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/generic.c Fri Oct 17 11:24:28 2003 @@ -0,0 +1,339 @@ +/* + * linux/arch/arm/mach-lhlh7a400/generic.c + * + * Common code for all LH7A400 based machines. + * + * Copyright (C) 2001 Lineo, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_MACH_KEV7A400 +u16 g_ioBrdCtl = 0; /* shadow copy of CPLD->ioBrdCtl */ +EXPORT_SYMBOL(g_ioBrdCtl); +#endif /* CONFIG_MACH_KEV7A400*/ + +void hclkfreq_notify(unsigned long event, unsigned int old_freq, + unsigned int new_freq); + +#define DEBUG 0 +#if DEBUG +# define DPRINTK( args...) printk( args) +#else +# define DPRINTK( args...) +#endif + +/* + * return FCLK in Hz. + */ +static inline unsigned int +fclkfreq_get(void) +{ + u32 mainDiv1, mainDiv2, preDiv, ps, clkset; + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + + clkset = clksc->clkset; + + mainDiv1 = (clkset >> 7) & 0x0f; + mainDiv2 = (clkset >> 11) & 0x1f; + preDiv = (clkset >> 2) & 0x1f; + ps = (clkset >> 18) & 0x03; + + return XTAL_IN / ((preDiv + 2) * (1 << ps)) * + (mainDiv1 +2) * (mainDiv2 + 2); +} + +#ifdef CONFIG_CPU_FREQ +unsigned int hclkfreq_get(void); + +/* Do: + * clksc->clkset = value; + * so that it fits in one cache line. + */ +static inline void +set_clkset(u32 value) +{ + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + + __asm__ __volatile__ (" + b 1f + .align 5 +1: str %1, [%0,#0] + nop + nop + nop + nop + nop + nop + nop" + : /* no outputs */ + : "r" (&clksc->clkset), "r" (value) ); + + mdelay(20); /* allow clocks to settle */ +} + + + +typedef struct { + u32 fclk_khz; /* FCLK (CPU) clock rate, in kHz. */ + u32 clkset; /* corresponding CLKSET register settings */ +} clksetParams_t; + +clksetParams_t clksetParams[] = { + { 199987, CLKSET_MAINDIV1(12) | CLKSET_MAINDIV2(29) | CLKSET_PREDIV(14) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 190464, CLKSET_MAINDIV1(13) | CLKSET_MAINDIV2(29) | CLKSET_PREDIV(16) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 184320, CLKSET_MAINDIV1(13) | CLKSET_MAINDIV2(28) | CLKSET_PREDIV(16) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 174618, CLKSET_MAINDIV1(13) | CLKSET_MAINDIV2(28) | CLKSET_PREDIV(17) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 165888, CLKSET_MAINDIV1(13) | CLKSET_MAINDIV2(28) | CLKSET_PREDIV(18) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 150088, CLKSET_MAINDIV1(13) | CLKSET_MAINDIV2(17) | CLKSET_PREDIV(12) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 133120, CLKSET_MAINDIV1(11) | CLKSET_MAINDIV2(23) | CLKSET_PREDIV(16) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 99993, CLKSET_MAINDIV1( 5) | CLKSET_MAINDIV2(29) | CLKSET_PREDIV(14) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 75010, CLKSET_MAINDIV1(11) | CLKSET_MAINDIV2(16) | CLKSET_PREDIV(21) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 65967, CLKSET_MAINDIV1(15) | CLKSET_MAINDIV2( 8) | CLKSET_PREDIV(17) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 50006, CLKSET_MAINDIV1(11) | CLKSET_MAINDIV2(10) | CLKSET_PREDIV(21) | CLKSET_PS1 | CLKSET_PCLKDIV2}, + { 32983, CLKSET_MAINDIV1(15) | CLKSET_MAINDIV2( 8) | CLKSET_PREDIV(17) | CLKSET_PS2 | CLKSET_PCLKDIV2}, + { 0, 0 } /* mark the end */ +}; + + +/* + * validate the desired CPU speed. + * return the CPU speed that is closest to the desired + * speed, without going over. + */ +static unsigned int +lh7a400_validateCPUspeed(unsigned int want_khz) +{ + clksetParams_t *cp = clksetParams; + + /* find the closest available CPU speed */ + while (cp->fclk_khz) { + if (cp->fclk_khz <= want_khz) + break; + cp++; + } + + if (cp->fclk_khz == 0) /* fell off the end */ + cp--; /* set to slowest speed */ + + DPRINTK(__FUNCTION__ ": want_khz=%d got %d\n", + want_khz, cp->fclk_khz); + + return cp->fclk_khz; +} + + + +static void +lh7a400_setCPUspeed(unsigned int new_khz) +{ + u32 curr_khz = fclkfreq_get() / 1000; + clksetParams_t *cp = clksetParams; + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + u32 hclkDiv; + u32 new_hclk_khz = 0; + u32 curr_hclk_khz; + + /* find clkset parameters for the new speed */ + while (cp->fclk_khz) { + if (cp->fclk_khz <= new_khz) + break; + cp++; + } + + /* + * find a new HCLK divisor such that the new HCLK + * is as close as possible to the current HCLK without + * going over. + */ + hclkDiv = (clksc->clkset & 0x3) + 1; + + curr_hclk_khz = curr_khz / hclkDiv; + + for (hclkDiv = 1; hclkDiv < 5; hclkDiv++) { + if ((new_hclk_khz = new_khz / hclkDiv) <= curr_hclk_khz) + break; + } + + if (hclkDiv > 4) + hclkDiv = 4; + + DPRINTK(__FUNCTION__ ": curr_hclk_khz=%d new_hclk_khz=%d new hclkDiv=%d\n", + curr_hclk_khz, new_hclk_khz, hclkDiv); + + /* + * if the new HCLK is different from the current HCLK, + * notify the drivers interested in HCLK changes before + * HCLK changes. + */ + if (new_hclk_khz != curr_hclk_khz) { + hclkfreq_notify(HCLKFREQ_PRECHANGE, curr_hclk_khz, + new_hclk_khz); + } + + /* set HCLK */ + set_clkset(cp->clkset | (hclkDiv - 1)); + + DPRINTK(__FUNCTION__ ": clkset = 0x%x\n", clksc->clkset); + + /* + * if the new HCLK is different from the current HCLK, + * notify the drivers interested in HCLK changes after + * HCLK has changed. + * + */ + if (new_hclk_khz != curr_hclk_khz) { + hclkfreq_notify(HCLKFREQ_POSTCHANGE, curr_hclk_khz, + new_hclk_khz); + } + + /* + * recompute minimum and maxmum HCLK values for + * this CPU clock speed. + */ + hclkfreq_set_minmax(cp->fclk_khz, new_hclk_khz); +} + + +/* + * validate the desired HCLK speed. + * return the HCLK speed that is closest to the desired + * speed, without going over. + */ +static unsigned int +lh7a400_validateHCLKspeed(unsigned int want_khz) +{ + int div; + u32 new_khz=0; + u32 fclk_khz = fclkfreq_get() / 1000; + + /* + * find the closest bus speed without going over. + */ + for (div = 1; div < 5; div++) { + if ((new_khz = fclk_khz / div) <= want_khz) + break; + } + + DPRINTK(__FUNCTION__ ": wanted %d got %d fclk=%d\n", + want_khz, new_khz, fclk_khz); + + return new_khz; +} + + +static void +lh7a400_setHCLKspeed(unsigned int want_khz) +{ + u32 fclk_khz = fclkfreq_get() / 1000; + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + u32 hclkDiv; + + DPRINTK(__FUNCTION__ ": want %d khz\n", want_khz); + + /* + * find the closest bus speed without going over. + */ + for (hclkDiv = 1; hclkDiv < 5; hclkDiv++) { + if ((fclk_khz / hclkDiv) <= want_khz) + break; + } + + /* set new HCLK */ + set_clkset((clksc->clkset & ~0x03) | (hclkDiv - 1)); + + DPRINTK(__FUNCTION__ ": clkset = 0x%x\n", clksc->clkset); +} + + +static int __init lh7a400_init_cpufreq(void) +{ + cpufreq_init(fclkfreq_get() / 1000 ); + cpufreq_setfunctions(lh7a400_validateCPUspeed, lh7a400_setCPUspeed); + + hclkfreq_init(hclkfreq_get()); + hclkfreq_setfunctions(lh7a400_validateHCLKspeed, lh7a400_setHCLKspeed); + + return 0; +} + +__initcall(lh7a400_init_cpufreq); + +#else +/* + * return the CPU clock frequency (FCLK) in kHz. + */ +unsigned int +cpufreq_get(int cpu) +{ + return fclkfreq_get() / 1000; +} + +EXPORT_SYMBOL(cpufreq_get); +#endif + + +/* + * return the AHB bus clock frequency (HCLK) in kHz. + */ +unsigned int +hclkfreq_get(void) +{ + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + u32 hclkDiv; + + hclkDiv = (clksc->clkset & 0x3) + 1; + DPRINTK("fclk=%d hclkDiv = %d\n", fclkfreq_get() / 1000, hclkDiv); + + return fclkfreq_get() / 1000 / hclkDiv; +} + +EXPORT_SYMBOL(hclkfreq_get); + + +/* + * return the APB bus clock frequency (PCLK) in kHz. + */ +unsigned int +pclkfreq_get(void) +{ + clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + u32 pclkDiv; + + pclkDiv = 2 ^ ((clksc->clkset >> 16) & 0x3); + DPRINTK("pclkDiv = %d\n", pclkDiv); + + return hclkfreq_get() / pclkDiv; +} + +EXPORT_SYMBOL(pclkfreq_get); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/hclkfreq.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/hclkfreq.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/hclkfreq.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/hclkfreq.c Thu Oct 16 16:33:58 2003 @@ -0,0 +1,431 @@ +/* + * arch/arm/mach-lh7a400/hclkfreq.c + * Copyright (C) 2002 Embedix, Inc. + * + * Based on + * linux/kernel/cpufreq.c + * which is + * Copyright (C) 2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * HCLK bus speed changing core functionality. We provide the following + * services to the system: + * - notifier lists to inform other code of the freq change both + * before and after the freq change. + * - the ability to change the freq speed + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* requires system.h */ + +#define DEBUG 0 +#if DEBUG +# define DPRINTK( args...) printk( args) +#else +# define DPRINTK( args...) +#endif + +/* + * This list is for kernel code that needs to handle + * changes to devices when the HCLK bus clock speed changes. + */ +static struct notifier_block *hclkfreq_notifier_list; +static DECLARE_MUTEX_LOCKED(hclkfreq_sem); +static int hclkfreq_initialised; +static unsigned int (*hclkfreq_validatespeed)(unsigned int); +static void (*hclkfreq_setspeed)(unsigned int); + +#ifndef CONFIG_SMP +static unsigned int __hclkfreq_max; +static unsigned int __hclkfreq_min; +static unsigned int __hclkfreq_cur; +#endif + +extern unsigned int hclkfreq_get( void); + + + +/** + * hclkfreq_register_notifier - register a driver with hclkfreq + * @nb: notifier function to register + * + * Add a driver to the list of drivers that which to be notified about + * HCLK clock rate changes. The driver will be called three times on + * clock change. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_register. + */ +int hclkfreq_register_notifier(struct notifier_block *nb) +{ + int ret; + + down(&hclkfreq_sem); + ret = notifier_chain_register(&hclkfreq_notifier_list, nb); + up(&hclkfreq_sem); + + return ret; +} + +EXPORT_SYMBOL(hclkfreq_register_notifier); + +/** + * hclkfreq_unregister_notifier - unregister a driver with hclkfreq + * @nb: notifier block to be unregistered + * + * Remove a driver from the HCLK frequency notifier lists. + * + * This function may sleep, and has the same return conditions as + * notifier_chain_unregister. + */ +int hclkfreq_unregister_notifier(struct notifier_block *nb) +{ + int ret; + + down(&hclkfreq_sem); + ret = notifier_chain_unregister(&hclkfreq_notifier_list, nb); + up(&hclkfreq_sem); + + return ret; +} + +EXPORT_SYMBOL(hclkfreq_unregister_notifier); + + + +void +hclkfreq_notify( unsigned long event, unsigned int old_freq, unsigned int new_freq) +{ + struct hclkfreq_info clkinfo; + + clkinfo.old_freq = old_freq; + clkinfo.new_freq = new_freq; + + notifier_call_chain( &hclkfreq_notifier_list, event, &clkinfo); +} + + +/** + * hclk_setfreq - change the HCLK clock frequency. + * @freq: frequency (in kHz) at which we should run. + * + * Set the HCLK clock frequency, informing all registered users of + * the change. We bound the frequency according to the hclkfreq_max + * command line parameter, and the parameters the registered users + * will allow. + * + * This function must be called from process context, and on the + * cpu that we wish to change the frequency of. + * + * We return 0 if successful. (we are currently always successful). + */ +int hclkfreq_set(unsigned int freq) +{ + unsigned long old_cpus; + // DDD struct hclkfreq_info clkinfo; + struct hclkfreq_minmax minmax; + int cpu = smp_processor_id(); + int ret; + unsigned int old_freq; + + if (!hclkfreq_initialised) + panic("hclkfreq_set() called before initialisation!"); + if (in_interrupt()) + panic("hclkfreq_set() called from interrupt context!"); + + /* + * Bind to the current CPU. + */ + old_cpus = current->cpus_allowed; + current->cpus_allowed = 1UL << cpu_logical_map(cpu); + + down(&hclkfreq_sem); + ret = -ENXIO; + if (!hclkfreq_setspeed || !hclkfreq_validatespeed) + goto out; + + /* + * Don't allow the CPU to be clocked over the limit. + */ + minmax.min_freq = hclkfreq_min(cpu); + minmax.max_freq = hclkfreq_max(cpu); + minmax.cur_freq = hclkfreq_current(cpu); + minmax.new_freq = freq; + + /* + * Find out what the registered devices will currently tolerate, + * and limit the requested clock rate to these values. Drivers + * must not rely on the 'new_freq' value - it is only a guide. + */ + notifier_call_chain(&hclkfreq_notifier_list, HCLKFREQ_MINMAX, &minmax); + if (freq < minmax.min_freq) + freq = minmax.min_freq; + if (freq > minmax.max_freq) + freq = minmax.max_freq; + + /* + * Ask the CPU specific code to validate the speed. If the speed + * is not acceptable, make it acceptable. Current policy is to + * round the frequency down to the value the processor actually + * supports. + */ + freq = hclkfreq_validatespeed(freq); + + if (hclkfreq_current(cpu) != freq) { + old_freq = hclkfreq_current(cpu); + hclkfreq_notify( HCLKFREQ_PRECHANGE, old_freq, freq); + + /* + * Actually set the HCLK frequency. + */ + hclkfreq_setspeed(freq); + hclkfreq_current(cpu) = freq; + + hclkfreq_notify( HCLKFREQ_POSTCHANGE, old_freq, freq); + } + + ret = 0; + + out: + up(&hclkfreq_sem); + + current->cpus_allowed = old_cpus; + + return ret; +} + +EXPORT_SYMBOL(hclkfreq_set); + + + +#ifdef CONFIG_SYSCTL + +static int +hclkfreq_procctl(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + char buf[16], *p; + int len, left = *lenp; + + if (!left || (filp->f_pos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + unsigned int freq; + + len = left; + if (left > sizeof(buf)) + left = sizeof(buf); + if (copy_from_user(buf, buffer, left)) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + + freq = simple_strtoul(buf, &p, 0); + hclkfreq_set(freq); + } else { + len = sprintf(buf, "%d\n", hclkfreq_get()); + if (len > left) + len = left; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + } + + *lenp = len; + filp->f_pos += len; + return 0; +} + +static int +hclkfreq_sysctl(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + if (oldval && oldlenp) { + size_t oldlen; + + if (get_user(oldlen, oldlenp)) + return -EFAULT; + + if (oldlen != sizeof(unsigned int)) + return -EINVAL; + + if (put_user(hclkfreq_get(), (unsigned int *)oldval) || + put_user(sizeof(unsigned int), oldlenp)) + return -EFAULT; + } + if (newval && newlen) { + unsigned int freq; + + if (newlen != sizeof(unsigned int)) + return -EINVAL; + + if (get_user(freq, (unsigned int *)newval)) + return -EFAULT; + + hclkfreq_set(freq); + } + return 1; +} + +enum { + HCLK_FREQ_MAX = 1, + HCLK_FREQ_MIN = 2, + HCLK_FREQ = 3 +}; + +static ctl_table ctl_hclk_vars[4] = { + { + ctl_name: HCLK_FREQ_MAX, + procname: "hclk-max", + data: &hclkfreq_max(0), + maxlen: sizeof(hclkfreq_max(0)), + mode: 0444, + proc_handler: proc_dointvec, + }, + { + ctl_name: HCLK_FREQ_MIN, + procname: "hclk-min", + data: &hclkfreq_min(0), + maxlen: sizeof(hclkfreq_min(0)), + mode: 0444, + proc_handler: proc_dointvec, + }, + { + ctl_name: HCLK_FREQ, + procname: "hclk", + mode: 0644, + proc_handler: hclkfreq_procctl, + strategy: hclkfreq_sysctl, + }, + { + ctl_name: 0, + } +}; + +enum { + CPU_NR = 1, +}; + +static ctl_table ctl_cpu_nr[2] = { + { + ctl_name: CPU_NR, + procname: "0", + mode: 0555, + child: ctl_hclk_vars, + }, + { + ctl_name: 0, + } +}; + +static ctl_table ctl_cpu[2] = { + { + ctl_name: CTL_CPU, + procname: "cpu", + mode: 0555, + child: ctl_cpu_nr, + }, + { + ctl_name: 0, + } +}; + +static inline void hclkfreq_sysctl_init(void) +{ + register_sysctl_table(ctl_cpu, 0); +} + +#else +#define hclkfreq_sysctl_init() +#endif + +/** + * hclkfreq_setfunctions - Set HCLK clock functions + * @validate: pointer to validation function + * @setspeed: pointer to setspeed function + */ +void __init +hclkfreq_setfunctions(unsigned int (*validate)(unsigned int), + void (*setspeed)(unsigned int)) +{ + down(&hclkfreq_sem); + hclkfreq_validatespeed = validate; + hclkfreq_setspeed = setspeed; + up(&hclkfreq_sem); +} + +EXPORT_SYMBOL(hclkfreq_setfunctions); + +/** + * hclkfreq_set_minmax - Compute min and max HCLK values + * based on the current FCLK. + * + * @freq: current HCLK clock speed in kHz. + */ +void hclkfreq_set_minmax( unsigned int fclk_khz, unsigned int hclk_khz) +{ + /* + * Compute min and max HCLK values based on current + * CPU clock. + * + * Limit the max HCLK speed to ~ 100 MHZ. + * The min speed is FCLK/4 (the largest hclk divisor) + */ + hclkfreq_max(0) = fclk_khz; + + if(hclkfreq_max(0) > MAX_HCLK_KHZ) + hclkfreq_max(0) = fclk_khz / 2; + + hclkfreq_min(0) = fclk_khz / 4; + + hclkfreq_current(smp_processor_id()) = hclk_khz; + + DPRINTK( __FUNCTION__ ": hclk_khz=%d fclk_khz=%d current=%d min=%d max=%d\n", + hclk_khz, fclk_khz, hclkfreq_current(smp_processor_id()), + hclkfreq_min(0), hclkfreq_max(0)); +} + + +EXPORT_SYMBOL(hclkfreq_set_minmax); + +/** + * hclkfreq_init - Initialise the hclkfreq core + * @freq: current HCLK clock speed in kHz. + * + * Initialise the hclkfreq core. + */ +void hclkfreq_init(unsigned int freq) +{ + hclkfreq_set_minmax( cpufreq_get(0), freq); + + printk(KERN_INFO "HCLK bus clock: %d.%03d MHz (%d.%03d-%d.%03d MHz)\n", + freq / 1000, freq % 1000, + hclkfreq_min(0) / 1000, hclkfreq_min(0) % 1000, + hclkfreq_max(0) / 1000, hclkfreq_max(0) % 1000); + + hclkfreq_initialised = 1; + up(&hclkfreq_sem); + + hclkfreq_sysctl_init(); +} + +EXPORT_SYMBOL(hclkfreq_init); diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/irq_eframe.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/irq_eframe.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/irq_eframe.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/irq_eframe.c Fri Feb 6 15:58:04 2004 @@ -0,0 +1,234 @@ +/* + * arch/arm/mach-lh7a400/irq_eframe.c + * + * interrupts through the eframe cpld + * + * Copyright (C) 2003 Brad Parker + * + * 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 +#include + + +extern unsigned int do_IRQ(int irq, struct pt_regs *regs); +extern void genarch_init_irq(void); + +inline void cpld_enable_irq(unsigned int irq_nr) +{ + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_EFRAME_IRQ; + cpld[CPLD_INT_SET] = 1 << irq_nr; +} + + +inline void cpld_disable_irq(unsigned int irq_nr) +{ + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_EFRAME_IRQ; + cpld[CPLD_INT_RESET] &= ~(1 << irq_nr); +} + +inline void cpld_ack_irq(unsigned int irq_nr) +{ + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_EFRAME_IRQ; + cpld[CPLD_ACK_RESET] = 1 << irq_nr; +} + +static inline void mask_and_ack_irq(unsigned int irq_nr) +{ + cpld_disable_irq(irq_nr); + cpld_ack_irq(irq_nr); +} + +static inline void mask_irq(unsigned int irq_nr) +{ + cpld_disable_irq(irq_nr); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + cpld_enable_irq(irq_nr); +} + +/* actual cpld interrupt */ +static void +cpld_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + unsigned int latched, i; + + gpio->eoi = GPIOF_INT(1); /* clear interrupt in GPIO */ + + latched = cpld[CPLD_ACK_READ] & 0x00ff; + if (0) printk("cpld_intr() latched %x\n", latched); + + /* map cpld interrupts into our the high range */ + for (i = 0; i < 7; i++) { + if (latched & (1 << i)) { + do_IRQ(FIRST_EFRAME_IRQ + i, regs); + } + } +} + +/* wire in the psuedo interrupts we generate from the cpld interrupt */ +void __init +eframe_cpld_irq_init(void) +{ + int irq; + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + + /* initialize the functions */ + for (irq = FIRST_EFRAME_IRQ; irq <= LAST_EFRAME_IRQ; irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 0; + irq_desc[irq].mask_ack = mask_and_ack_irq; + irq_desc[irq].mask = mask_irq; + irq_desc[irq].unmask = unmask_irq; + } + + /* clear int enables */ + cpld[CPLD_INT_RESET] = 0xff; + + /* clear pending ints */ + cpld[CPLD_ACK_RESET] = 0xff; +} + +void +eframe_cpld_irq_install(void) +{ + /* install the GPIO interrupt to call us */ + if (request_irq(IRQ_CPLD, cpld_intr, 0, "CPLD intr", NULL)) { + panic("eframe: can't get CPLD interrupt\n"); + } +} + +module_init(eframe_cpld_irq_install) + +static void mask_ack_pcmcia_slot1(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_SLOT1; /* ACK IRQ */ +} + + +static void mask_ack_pcmcia_cd1(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_CD1; /* ACK IRQ */ +} + + +static void lh7a400_mask_irq(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + + intc->clear = (1 << irq); +} + +static void lh7a400_unmask_irq(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + + intc->enable = (1 << irq); +} + + +void __init eframe_init_irq(void) +{ + int irq; + int rc; + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + /* clear all interrupt enables */ + intc->clear = 0xffffffff; + + for (irq = 0; irq < LH7A400_MAX_INTR; irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = lh7a400_mask_irq; + irq_desc[irq].mask = lh7a400_mask_irq; + irq_desc[irq].unmask = lh7a400_unmask_irq; + } + + /* pcmcia interrupts */ + irq_desc[IRQ_EFRAME_PCMCIA_CD1].mask_ack = mask_ack_pcmcia_cd1; + irq_desc[IRQ_EFRAME_PCMCIA1].mask_ack = mask_ack_pcmcia_slot1; + + /* + * deal with GPIO interrupts + */ + + /* disallow all interrupts thru GPIO */ + gpio->intEnable = 0; + barrier(); + + /* specify which Port F ints are edge triggered */ + gpio->intType1 = GPIOF_EDGE_TRIGGER; + + /* specify which Port F ints are active high */ + gpio->intType2 = GPIOF_ACTIVE_HIGH; + + /* clear all interrupts in GPIO */ + gpio->eoi = GPIOF_ALL_INT; + + /* enable GPIO Port F interrupts */ + gpio->intEnable = GPIOF_ALL_INT; + + /* add cpld interrupts */ + eframe_cpld_irq_init(); +} + +void +eframe_remove_irq(void) +{ + free_irq(IRQ_EFRAME_CPLD, NULL); +} + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/irq_kev7a400.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/irq_kev7a400.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/irq_kev7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/irq_kev7a400.c Sat Feb 7 16:38:25 2004 @@ -0,0 +1,314 @@ +/* + * arch/arm/mach-lh7a400/cpld_irq_kev7a400.c + * + * interrupts through the kev7a400 cpld + * + * Copyright (C) 2003 Brad Parker + * Copyright (C) 2001 Lineo, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +extern unsigned int do_IRQ(int irq, struct pt_regs *regs); +extern void genarch_init_irq(void); + +inline void cpld_enable_irq(unsigned int irq_nr) +{ + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_KEV7A400_IRQ; + cpld->u3.latchedIntMask |= 1 << irq_nr; +} + + +inline void cpld_disable_irq(unsigned int irq_nr) +{ + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_KEV7A400_IRQ; + cpld->u3.latchedIntMask &= ~(1 << irq_nr); +} + +inline void cpld_ack_irq(unsigned int irq_nr) +{ + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + /* map the intr # to a cpld enable bit */ + irq_nr -= FIRST_KEV7A400_IRQ; + cpld->latchedInts = 1 << irq_nr; +} + +static inline void mask_and_ack_irq(unsigned int irq_nr) +{ +// cpld_disable_irq(irq_nr); + cpld_ack_irq(irq_nr); +} + +static inline void mask_irq(unsigned int irq_nr) +{ + cpld_disable_irq(irq_nr); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + cpld_enable_irq(irq_nr); +} + +void +cpld_check(void) +{ + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + printk("cpld_check() latchedInts %08x, lastIntMask %08x\n", + cpld->latchedInts, + cpld->u3.latchedIntMask); + printk(" intEnable %08x, intStatus %08x, rawIntStatus %08x\n", + gpio->intEnable, gpio->intStatus, gpio->rawIntStatus); +} + +/* actual cpld interrupt */ +static void +cpld_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + unsigned int latched, i; + + latched = cpld->latchedInts & CPLD_INT_MASK; + if (0) printk("cpld_intr() latched %x\n", latched); + + /* map cpld interrupts into our the high range */ + for (i = 0; i < 5; i++) { + if (latched & (1 << i)) { + do_IRQ(FIRST_KEV7A400_IRQ + i, regs); + } + } +} + +/* wire in the psuedo interrupts we generate from the cpld interrupt */ +void __init kev7a400_cpld_irq_init(void) +{ + int irq; + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + /* initialize cpld */ + + /* initialize the functions */ + for (irq = FIRST_KEV7A400_IRQ; irq <= LAST_KEV7A400_IRQ; irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 0; + irq_desc[irq].mask_ack = mask_and_ack_irq; + irq_desc[irq].mask = mask_irq; + irq_desc[irq].unmask = unmask_irq; + } + + /* allow Ethernet and MMC detect external interrupts */ + cpld->u3.latchedIntMask = CPLD_INT_ENET | CPLD_INT_MMC; +} + +void __init +kev7a400_cpld_irq_install(void) +{ + /* install the GPIO interrupt to call us */ + if (request_irq(IRQ_KEV7A400_CPLD, cpld_intr, + SA_INTERRUPT/*0*/, "CPLD intr", NULL)) { + panic("kev7a400: can't get CPLD interrupt\n"); + } +} + +static void mask_ack_pcmcia_slot1(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_SLOT1; /* ACK IRQ */ +} + + +static void mask_ack_pcmcia_slot2(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_SLOT2; /* ACK IRQ */ +} + + +static void mask_ack_pcmcia_cd1(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_CD1; /* ACK IRQ */ +} + + +static void mask_ack_pcmcia_cd2(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << irq); + gpio->eoi = GPIOF_INT_PC_CD2; /* ACK IRQ */ +} + +/* + * Called by do_IRQ with an FIQ number. Mask the corresponding IRQ, + * and ACK the corresponding IRQ. + */ +static void mask_ack_fiq( u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + intc->clear = (1 << (irq + IRQ_GPIO_F4)); /* mask IRQ */ + gpio->eoi = (GPIOF_INT_F4 << irq); /* ACK IRQ */ +} + + +static struct fiq_handler fh = { + name: "tsfiq" +}; + +extern unsigned char fiqhandler, fiqhandler_end; + + +static void __init kev7a400_init_fiq(void) +{ + struct pt_regs regs; + int rc; + + init_FIQ(); + + /* + * set up our FIQ handler + */ + regs.ARM_r8 = IO_ADDRESS(INTC_PHYS); + regs.ARM_r9 = IO_ADDRESS(GPIO_PHYS); + + if( (rc = claim_fiq(&fh)) != 0) { + printk("%s couldn't get ts fiq. rc=%d\n", __FUNCTION__, rc); + return; + } + + set_fiq_handler(&fiqhandler, &fiqhandler_end - &fiqhandler); + set_fiq_regs(®s); + + irq_desc[IRQ_KEV7A400_TS].mask_ack = mask_ack_fiq; +} + +static void lh7a400_mask_irq(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + + intc->clear = (1 << irq); +} + +static void lh7a400_unmask_irq(u32 irq) +{ + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + + intc->enable = (1 << irq); +} + + +void __init kev7a400_init_irq(void) +{ + int irq; + intcRegs_t *intc = (intcRegs_t *)IO_ADDRESS(INTC_PHYS); + gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + + /* clear all interrupt enables */ + intc->clear = 0xffffffff; + + for (irq = 0; irq < LH7A400_MAX_INTR; irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = lh7a400_mask_irq; + irq_desc[irq].mask = lh7a400_mask_irq; + irq_desc[irq].unmask = lh7a400_unmask_irq; + } + + /* pcmcia interrupts */ + irq_desc[IRQ_KEV7A400_PCMCIA_CD1].mask_ack = mask_ack_pcmcia_cd1; + irq_desc[IRQ_KEV7A400_PCMCIA_CD2].mask_ack = mask_ack_pcmcia_cd2; + irq_desc[IRQ_KEV7A400_PCMCIA1].mask_ack = mask_ack_pcmcia_slot1; + irq_desc[IRQ_KEV7A400_PCMCIA2].mask_ack = mask_ack_pcmcia_slot2; + + /* + * deal with GPIO interrupts + */ + + /* disallow all interrupts thru GPIO */ + gpio->intEnable = 0; + barrier(); + + /* add cpld interrupts */ + kev7a400_cpld_irq_init(); + + /* specify which Port F ints are edge triggered */ + gpio->intType1 = GPIOF_EDGE_TRIGGER; + + /* specify which Port F ints are active high */ + gpio->intType2 = GPIOF_ACTIVE_HIGH; + + /* clear all interrupts in GPIO */ + gpio->eoi = GPIOF_ALL_INT; + + /* enable GPIO Port F interrupts */ + gpio->intEnable = GPIOF_ALL_INT; + + /* add fiq interrupts */ + kev7a400_init_fiq(); +} + +void +kev7a400_remove_irq(void) +{ + free_irq(IRQ_KEV7A400_CPLD, NULL); +} + + +module_init(kev7a400_cpld_irq_install); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/kev7a400.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/kev7a400.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/kev7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/kev7a400.c Fri Feb 6 15:19:10 2004 @@ -0,0 +1,173 @@ +/* + * linux/arch/arm/mach-lh7a400/kev7a400.c + * + * Machine (board) specific fixups. + * + * Copyright (C) 2001 Lineo, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern void genarch_init_irq( void); +extern void lh7a400_show_freq_and_stepping(void); +extern void kev7a400_init_irq(void); + +extern int lh7a400_stepping; + +//#define USE_BLOB_PARAMS +//#define SDRAM_64MB /* 16 banks: 64 MB SDRAM 8 nodes */ +#define SDRAM_32MB /* 8 banks: 32 MB SDRAM 4 nodes */ +//#define USE_RAMDISK_ROOT +#define USE_NFS_ROOT + + +#include + +#define IO_RW DOMAIN_IO, 0, 1, 0, 0 + +static struct map_desc lh7a400_io_desc[] __initdata = { +/* virt phys size r w c b */ +{ FLASH_BASE, FLASH_START, FLASH_SIZE, IO_RW }, +{ INT_SRAM_BASE, INT_SRAM_START, INT_SRAM_SIZE, IO_RW }, +{ EXT_SRAM_BASE, EXT_SRAM_START, EXT_SRAM_SIZE, IO_RW }, +{ CPLD_BASE, CPLD_START, CPLD_SIZE, IO_RW }, +{ CS8900_BASE, CS8900_START, CS8900_SIZE, IO_RW }, +{ IDE_BASE, IDE_START, IDE_SIZE, IO_RW }, +{ IDE2_BASE, IDE2_START, IDE2_SIZE, IO_RW }, +{ APB_BASE, APB_START, APB_SIZE, IO_RW }, +{ AHB_BASE, AHB_START, AHB_SIZE, IO_RW }, +#ifdef CONFIG_MTD_LH7A400_SYNCFLASH +{ SYNCFLASH_B0_BASE, SYNCFLASH_B0_START, SYNCFLASH_BANK_SIZE, IO_RW }, +{ SYNCFLASH_B1_BASE, SYNCFLASH_B1_START, SYNCFLASH_BANK_SIZE, IO_RW }, +{ SYNCFLASH_B2_BASE, SYNCFLASH_B2_START, SYNCFLASH_BANK_SIZE, IO_RW }, +{ SYNCFLASH_B3_BASE, SYNCFLASH_B3_START, SYNCFLASH_BANK_SIZE, IO_RW }, +#endif +#if defined(CONFIG_PCMCIA_LH7A400) || defined(CONFIG_PCMCIA_LH7A400_MODULE) +{ PCMCIA_IO_0_BASE, PCMCIA_IO_0_START, PCMCIA_IO_0_SIZE, IO_RW }, +{ PCMCIA_IO_1_BASE, PCMCIA_IO_1_START, PCMCIA_IO_1_SIZE, IO_RW }, +{ PCMCIA_STATUS_BASE, PCMCIA_STATUS_START, PCMCIA_STATUS_SIZE, IO_RW }, +#endif +LAST_DESC +}; + +void __init lh7a400_map_io(void) +{ + iotable_init( lh7a400_io_desc); +} + +static void __init +fixup_lh7a400(struct machine_desc *desc, struct param_struct *unused, + char **cmdline, struct meminfo *mi) +{ +#ifndef USE_BLOB_PARAMS +#ifdef SDRAM_64MB + int i; + + mi->nr_banks = 16; + + for (i = 0; i < 16; i++) { + mi->bank[i].start = 0; + mi->bank[i].size = (4*1024*1024); + mi->bank[i].node = i/2; + } + + mi->bank[0].start = 0xc0000000; + mi->bank[1].start = 0xc1000000; + mi->bank[2].start = 0xc4000000; + mi->bank[3].start = 0xc5000000; + mi->bank[4].start = 0xc8000000; + mi->bank[5].start = 0xc9000000; + mi->bank[6].start = 0xcc000000; + mi->bank[7].start = 0xcd000000; + + mi->bank[8].start = 0xd0000000; + mi->bank[9].start = 0xd1000000; + mi->bank[10].start = 0xd4000000; + mi->bank[11].start = 0xd5000000; + mi->bank[12].start = 0xd8000000; + mi->bank[13].start = 0xd9000000; + mi->bank[14].start = 0xdc000000; + mi->bank[15].start = 0xdd000000; + +#elif defined(SDRAM_32MB) + int i; + + mi->nr_banks = 8; + + for (i = 0; i < 8; i++) { + mi->bank[i].start = 0; + mi->bank[i].size = (4*1024*1024); + mi->bank[i].node = i/2; + } + + mi->bank[0].start = 0xc0000000; + mi->bank[1].start = 0xc1000000; + mi->bank[2].start = 0xc4000000; + mi->bank[3].start = 0xc5000000; + mi->bank[4].start = 0xc8000000; + mi->bank[5].start = 0xc9000000; + mi->bank[6].start = 0xcc000000; + mi->bank[7].start = 0xcd000000; + +#endif /* 32 or 64 Mb testing */ + + +#ifdef USE_RAMDISK_ROOT + /* use ramdisk root */ + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk(1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); + setup_initrd(__phys_to_virt(0xc4000000), 3 * 1024 * 1024); + + /* Serial Console on UART 1, root on ramdisk */ + strcpy(*cmdline, + "console=ttyAM1,115200 root=/dev/ram0 ip=bootp"); +#elif defined(USE_NFS_ROOT) + /* use nfs root */ + /* Serial Console on UART 1 root over NFS */ + strcpy(*cmdline, + "console=ttyAM1,115200 noinitrd root=/dev/nfs ip=bootp"); +#endif + +#endif /* USE_BLOB_PARAMS */ + + lh7a400_show_freq_and_stepping(); + +} + +MACHINE_START(KEV7A400, "Sharp LH7A400 Evaluation Board") + MAINTAINER("brad@heeltoe.com") + /* pio, vio must be 8MB */ + BOOT_MEM(0xC0000000, 0x80000000, 0xF8000000) +#ifdef USE_BLOB_PARAMS + BOOT_PARAMS(0xC0000100) +#endif + FIXUP(fixup_lh7a400) + MAPIO(lh7a400_map_io) + INITIRQ(kev7a400_init_irq) +MACHINE_END + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/lcd_eframe.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/lcd_eframe.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/lcd_eframe.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/lcd_eframe.c Wed Nov 19 22:03:43 2003 @@ -0,0 +1,64 @@ +/* + * arch/arm/mach-lh7a400/lcd-eframe.c + * + * lcd hardware "helper" routines + * + * Copyright (C) 2003 Brad Parker + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include + +#include +#include + +#include + +void +lh7a400_backlight_power(int on) +{ + volatile u32 *cpld = (volatile u32 *)CPLD_BASE; + + if (on) { + /* backlight on */ + cpld[CPLD_CTRL_SET] = CPLD_CTRL_BACKLIGHT; + } else { + /* backlight off */ + cpld[CPLD_CTRL_RESET] = CPLD_CTRL_BACKLIGHT; + } +} + +void +lh7a400_lcd_power(int on) +{ + if (on) { + /* power up lcd */ + cpld[CPLD_CTRL_SET] = CPLD_CTRL_LCDPWR; + } else { + /* power down lcd */ + cpld[CPLD_CTRL_RESET] = CPLD_CTRL_LCDPWR; + } +} + +void +eframe_lcd_enable(int on) +{ + if (on) { + /* enable lcd drive */ + cpld[CPLD_CTRL_SET] = CPLD_CTRL_LCDOE; + } else { + /* disable lcd drive */ + cpld[CPLD_CTRL_RESET] = CPLD_CTRL_LCDOE; + } +} + +int +eframe_get_bpp(void) +{ + return 16; +} diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/lcd_kev7a400.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/lcd_kev7a400.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/lcd_kev7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/lcd_kev7a400.c Sat Oct 18 16:10:47 2003 @@ -0,0 +1,142 @@ +/* + * arch/arm/mach-lh7a400/lcd-kev7a400.c + * + * lcd hardware "helper" routines + * + * Copyright (C) 2002 Lineo, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_ARCH_LH79520 +#include +#include +#include +#endif + +#ifdef CONFIG_ARCH_LH7A400 +#include +#include +#endif + +void +lh7a400_backlight_power(int on) +{ + if (on) { + /* backlight on */ +#ifdef CONFIG_ARCH_LH79520 + if( machine_is_lh79520evb()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl |= CPLD_BACKLIGHT_ON; + } +#endif +#ifdef CONFIG_ARCH_LH7A400 + if( machine_is_kev7a400()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl |= CPLD_BACKLIGHT_ON; + } +#endif + } else { + /* backlight off */ +#ifdef CONFIG_ARCH_LH79520 + if( machine_is_kev79520()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl &= ~CPLD_BACKLIGHT_ON; + } +#endif +#ifdef CONFIG_ARCH_LH7A400 + if( machine_is_kev7a400()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl &= ~CPLD_BACKLIGHT_ON; + } +#endif + } +} + +void +lh7a400_lcd_power(int on) +{ + if (on) { + /* power up lcd */ +#ifdef CONFIG_ARCH_LH79520 + if( machine_is_kev79520()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl |= CPLD_LCDP_EN; + } +#endif +#ifdef CONFIG_ARCH_LH7A400 + if( machine_is_kev7a400()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl |= (CPLD_LCDP_EN | CPLD_DISP_EN); + if( b0_stepping) + cpld->lcd_pwr_cntl |= CPLD_LCD_LOWVOLT_EN; + } +#endif + } else { + /* power down lcd */ +#ifdef CONFIG_ARCH_LH79520 + if( machine_is_kev79520()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl &= ~CPLD_LCDP_EN; + if( b0_stepping) + cpld->lcd_pwr_cntl &|= ~CPLD_LCD_LOWVOLT_EN; + } +#endif +#ifdef CONFIG_ARCH_LH7A400 + if( machine_is_kev7a400()) { + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + cpld->lcd_pwr_cntl &= ~(CPLD_LCDP_EN | CPLD_DISP_EN); + } +#endif + } + +} + +void +lh7a400_lcd_enable(int on) +{ +#if defined(CONFIG_MACH_KEV7A400) + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + if (on) { + /* enable lcd drive */ + cpld->lcd_pwr_cntl |= CPLD_LCD_OE; + } else { + /* disable lcd drive */ + cpld->lcd_pwr_cntl &= ~CPLD_LCD_OE; + } +#endif +} + +int +lh7a400_get_bpp(void) +{ +#if defined(CONFIG_ARCH_KEV79520) + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + u8 dipSw = (u8)~(cpld->display_dip_sw & 0xff); + + if( machine_is_kev79520()) { + /* set bpp based on LCD board dip switch 0 */ + return (dipSw & 1 ? 8 : 16); + } +#endif +#if defined(CONFIG_MACH_KEV7A400) + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + u8 dipSw = (u8)~(cpld->u3.dispDipSw & 0xff); + + if( machine_is_kev7a400()) { + /* set bpp based on LCD board dip switch 0 */ + return (dipSw & 1 ? 8 : 16); + } +#endif + return 8; +} diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/mmc.c linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/mmc.c --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/mmc.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/mmc.c Sun Oct 19 07:39:02 2003 @@ -0,0 +1,1020 @@ +/* + * Low-level MMC functions for the Sharp LH7A400 EVB. + * + * Portions Copyright (C) 2002 Embedix, Inc + * Strongly based on code for the iPAQ H3800, see below. + * + * 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 + */ + +/* + * Low-level MMC functions for the iPAQ H3800 + * + * Copyright 2002 Hewlett-Packard Company + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Many thanks to Alessandro Rubini and Jonathan Corbet! + * + * Author: Andrew Christian + * 6 May 2002 + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include /* LH7A400 specific interrupts */ +#include + +#include +#include + +#ifdef CONFIG_MACH_KEV7A400 +#include +#endif + +#ifdef CONFIG_CPU_FREQ +#include +#endif + +#include + +#include "mmc.h" + +/* gives 312500 Hz (divisor 6) to 20 MHz (d=0) at 100MHz HCLK */ +#define HCLK_DIVISOR 5 + +#undef LH7A400_EVB_01 /* define for older (-01) EVBs */ + +#ifdef LH7A400_EVB_01 +#define ROTATE_RESP_FIFO 1 +#else +#define ROTATE_RESP_FIFO 0 +#endif + +struct response_info { + int length; + u16 cdc_flags; +}; + +static struct response_info rinfo[] = { +{ 0, MMC_CMD_DATA_CONT_FORMAT_NO_RESPONSE }, /* R0 */ +{ 6, MMC_CMD_DATA_CONT_FORMAT_R1 }, /* R1 */ +{ 6, MMC_CMD_DATA_CONT_FORMAT_R1 | MMC_CMD_DATA_CONT_BUSY_BIT }, /* R1b */ +{ 17, MMC_CMD_DATA_CONT_FORMAT_R2 }, /* R2 CID */ +{ 17, MMC_CMD_DATA_CONT_FORMAT_R2 }, /* R2 CSD */ +{ 6, MMC_CMD_DATA_CONT_FORMAT_R3 }, /* R3 */ +{ 6, 0 }, /* R4 */ +{ 6, 0 }, /* R5 */ +}; + +enum lh7a400_request_type { + RT_NO_RESPONSE, + RT_RESPONSE_ONLY, + RT_READ, + RT_WRITE +}; + +struct lh7a400_mmc_data { + struct timer_list sd_detect_timer; + struct timer_list reset_timer; + struct timer_list irq_timer; /* Panic timer */ + u32 rate; /* Desired clock frequency */ + u32 clock; /* Current clock frequency */ + struct mmc_request *request; + enum lh7a400_request_type type; +}; + +static struct lh7a400_mmc_data g_lh7a400_data = {{{0}}}; +struct mmc_statistics g_lh7a400_mmc_statistics; + +#define MMC_IRQ_TIMEOUT (3 * HZ) + + +static __inline__ void mmc_delay( void ) { udelay(1); } +static int lh7a400_slot_is_empty( int slot ); + +extern unsigned int hclkfreq_get( void); + +/************************************************************************** + * Utility routines for debuging + **************************************************************************/ + +struct cmd_to_name { + int id; + char *name; +}; + +static struct cmd_to_name cmd_names[] = { + { MMC_CIM_RESET, "CIM_RESET" }, + { MMC_GO_IDLE_STATE, "GO_IDLE_STATE" }, + { MMC_SEND_OP_COND, "SEND_OP_COND" }, + { MMC_ALL_SEND_CID, "ALL_SEND_CID" }, + { MMC_SET_RELATIVE_ADDR, "SET_RELATIVE_ADDR" }, + { MMC_SET_DSR, "SET_DSR" }, + { MMC_SELECT_CARD, "SELECT_CARD" }, + { MMC_SEND_CSD, "SEND_CSD" }, + { MMC_SEND_CID, "SEND_CID" }, + { MMC_READ_DAT_UNTIL_STOP, "READ_DAT_UNTIL_STOP" }, + { MMC_STOP_TRANSMISSION, "STOP_TRANSMISSION" }, + { MMC_SEND_STATUS , "SEND_STATUS " }, + { MMC_GO_INACTIVE_STATE, "GO_INACTIVE_STATE" }, + { MMC_SET_BLOCKLEN, "SET_BLOCKLEN" }, + { MMC_READ_SINGLE_BLOCK, "READ_SINGLE_BLOCK" }, + { MMC_READ_MULTIPLE_BLOCK, "READ_MULTIPLE_BLOCK" }, + { MMC_WRITE_DAT_UNTIL_STOP, "WRITE_DAT_UNTIL_STOP" }, + { MMC_SET_BLOCK_COUNT, "SET_BLOCK_COUNT" }, + { MMC_WRITE_BLOCK, "WRITE_BLOCK" }, + { MMC_WRITE_MULTIPLE_BLOCK, "WRITE_MULTIPLE_BLOCK" }, + { MMC_PROGRAM_CID, "PROGRAM_CID" }, + { MMC_PROGRAM_CSD, "PROGRAM_CSD" }, + { MMC_SET_WRITE_PROT, "SET_WRITE_PROT" }, + { MMC_CLR_WRITE_PROT, "CLR_WRITE_PROT" }, + { MMC_SEND_WRITE_PROT, "SEND_WRITE_PROT" }, + { MMC_ERASE_GROUP_START, "ERASE_GROUP_START" }, + { MMC_ERASE_GROUP_END, "ERASE_GROUP_END" }, + { MMC_ERASE, "ERASE" }, + { MMC_FAST_IO, "FAST_IO" }, + { MMC_GO_IRQ_STATE, "GO_IRQ_STATE" }, + { MMC_LOCK_UNLOCK, "LOCK_UNLOCK" }, + { MMC_APP_CMD, "APP_CMD" }, + { MMC_GEN_CMD, "GEN_CMD" }, +}; + +static char * get_cmd_name( int cmd ) +{ + int i; + int len = sizeof(cmd_names) / sizeof(struct cmd_to_name); + for ( i = 0 ; i < len ; i++ ) + if ( cmd == cmd_names[i].id ) + return cmd_names[i].name; + + return "UNKNOWN"; +} + +struct status_bit_to_name { + u16 mask; + int shift; + char *name; +}; + +struct status_bit_to_name status_bit_names[] = { + { MMC_STATUS_READ_TIMEOUT, -1, "READ_TIMEOUT" }, + { MMC_STATUS_RESPONSE_TIMEOUT, -1, "RESPONSE_TIMEOUT" }, + { MMC_STATUS_CRC_WRITE_ERROR, -1, "CRC_WRITE_ERROR" }, + { MMC_STATUS_CRC_READ_ERROR, -1, "CRC_READ_ERROR" }, + { MMC_STATUS_SPI_READ_ERROR, -1, "SPI_READ_ERROR" }, + { MMC_STATUS_CRC_RESPONSE_ERROR, -1, "CRC_RESPONSE_ERROR" }, + { MMC_STATUS_FIFO_EMPTY, -1, "FIFO_EMPTY" }, + { MMC_STATUS_FIFO_FULL, -1, "FIFO_FULL" }, + { MMC_STATUS_CLOCK_STOPPED, -1, "CLOCK_STOPPED" }, +#ifndef CONFIG_ARCH_LH7A400 + { MMC_STATUS_WR_CRC_ERROR_CODE, 9, "WR_CRC_ERROR_CODE" }, +#endif + { MMC_STATUS_DATA_TRANSFER_DONE, -1, "DATA_TRANSFER_DONE" }, + { MMC_STATUS_END_PROGRAM, -1, "END_PROGRAM" }, + { MMC_STATUS_END_COMMAND_RESPONSE, -1, "END_COMMAND_RESPONSE" } +}; + +static void decode_status( u16 status ) +{ + int i; + int len = sizeof(status_bit_names)/sizeof(struct status_bit_to_name); + struct status_bit_to_name *b = status_bit_names; + for ( i = 0 ; i < len ; i++, b++ ) { + if ( status & b->mask ) { + if ( b->shift >= 0 ) + printk("%s[%d] ", b->name, ((status & b->mask) >> b->shift)); + else + printk("%s ", b->name); + } + } +} + +static void printk_request( struct mmc_request *request, char *header ) +{ + printk("%sindex %d\n", header, request->index ); + printk("%scmd %d\n", header, request->cmd ); + printk("%sarg 0x%08x\n", header, request->arg ); + printk("%srtype %d\n", header, request->rtype ); + printk("%snob %d\n", header, request->nob ); + printk("%sbl_len %d\n", header, request->block_len ); + printk("%sbuffer %p\n", header, request->buffer ); + printk("%sresult %d\n", header, request->result); +} + + +static void printk_mmc_state( char *header ) +{ + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + u16 status = mmc->Status; + + printk("%sStatus 0x%04x ", header, status ); + decode_status(status); + printk("\n%sClockRate 0x%02x\n", header, mmc->ClockRate ); + printk("%sPrediv 0x%02x\n", header, mmc->PreDivider ); + printk("%sCmdDataCont 0x%02x\n", header, mmc->CmdDataControl ); + printk("%sResponseTimeout 0x%02x\n", header, mmc->ResponseTimeout ); + printk("%sReadTimeout 0x%04x\n", header, mmc->ReadTimeout ); + printk("%sBlock Length 0x%04x\n", header, mmc->BlockLength ); + printk("%sNum of Blocks 0x%04x\n", header, mmc->NumOfBLocks ); + printk("%sInterruptMask 0x%02x\n", header, mmc->InterruptMask ); + printk("%sInterruptStatus 0x%02x\n", header, mmc->InterruptStatus ); + printk("%sCommandNumber 0x%02x %s\n", header, mmc->CommandNumber, get_cmd_name(mmc->CommandNumber) ); + printk("%sArgument 0x%04x\n", header, mmc->CommandArg ); + printk("%sBufferPartFull 0x%02x\n", header, mmc->BufferPartFull ); +} + +/************************************************************************** + * Clock routines + * + * We have to poll the status register until we're sure that the clock has stopped. + * This may be called in interrupt context, so we can't go to sleep! + **************************************************************************/ + +static int lh7a400_stop_clock( void ) +{ + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG( 1, "\n"); + + mmc->ClockControl = MMC_STOP_CLOCK; + mmc_delay(); + + while( !(mmc->Status & MMC_STATUS_CLOCK_STOPPED) ) /* wait for clock to stop */ + ; + + return 0; +} + +static void lh7a400_start_clock( void ) +{ + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG( 1,"\n"); + + mmc->ClockControl = MMC_START_CLOCK; /* Start the clock */ + mmc_delay(); + + /* Wait for MMC clock to start */ + while( mmc->Status & MMC_STATUS_CLOCK_STOPPED) + ; +} + +static int lh7a400_set_clock( u32 rate ) +{ + int retval; + + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + u32 master = hclkfreq_get() * 1000 / HCLK_DIVISOR; + u8 divisor = 1; /* No divisor */ + + DEBUG( 1, ": rate = %d master=%d\n", rate, master); + + while ( master > rate ) { + divisor++; + master /= 2; + } + if ( divisor > 8 ) divisor = 8; + + DEBUG(1,": setting divisor to %d (request=%d result=%d)\n", + divisor, rate, master ); + + retval = lh7a400_stop_clock(); + if ( retval ) + return retval; + + mmc->ClockRate = divisor; + mmc_delay(); + + mmc->ResponseTimeout = 0x0040; + mmc_delay(); + + mmc->ReadTimeout = 0xffff; + mmc_delay(); + + lh7a400_start_clock(); + g_lh7a400_data.clock = master; + g_lh7a400_data.rate = rate; + + return MMC_NO_ERROR; +} + +static int reset_mmc_controller( u32 clock_rate ) +{ + int retval; + DEBUG( 1, ": clock_rate=%d\n", clock_rate); + + retval = lh7a400_set_clock( clock_rate ); + lh7a400_start_clock(); + return retval; +} + +/* + The reset function clears _everything_ in the ASIC, + so it needs be completely reset +*/ + +static void lh7a400_reset_timeout( unsigned long nr ) +{ +// struct lh7a400_mmc_data *sd = (struct lh7a400_mmc_data *) nr; + + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG( 1, ": nr=%ul\n", (unsigned int)nr); + + /* Send 80 clocks to get things started */ + mmc->CmdDataControl = MMC_CMD_DATA_CONT_INITIALIZE; + mmc_delay(); + + mmc->InterruptMask = MMC_INT_MASK_END_COMMAND_RESPONSE; + mmc_delay(); + + START_DEBUG(2) { + u16 status = mmc->Status; + printk("%s: enabling irq mask=%04x status=0x%04x (", + __FUNCTION__, mmc->InterruptMask, status); + decode_status(status); + printk(")\n"); + } END_DEBUG; + + mod_timer( &g_lh7a400_data.irq_timer, jiffies + MMC_IRQ_TIMEOUT); + enable_irq( IRQ_MMC ); +} + +static int lh7a400_reset( struct lh7a400_mmc_data *sd ) +{ + int retval = reset_mmc_controller( MMC_CLOCK_SLOW ); + g_lh7a400_data.type = RT_NO_RESPONSE; + mod_timer( &sd->reset_timer, jiffies + (100 * HZ) / 1000 ); + g_lh7a400_mmc_statistics.mmc_reset++; + + return retval; +} + + +static void lh7a400_set_command( u16 cmd, u32 arg ) +{ + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG(2,": cmd=%d arg=0x%08x\n", cmd, arg); + + mmc->CommandArg = arg; + mmc_delay(); + + mmc->CommandNumber = cmd; + mmc_delay(); +} + +static void lh7a400_set_transfer( u16 block_len, u16 nob ) +{ + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG(2,": block_len=%d nob=%d\n", block_len, nob); + + mmc->BlockLength = block_len; + mmc_delay(); + + mmc->NumOfBLocks = nob; + mmc_delay(); +} + +static void lh7a400_transmit_data( struct mmc_request *request ) +{ + u8 *buf = request->buffer; + u16 data; + int i; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG(2,": nob=%d block_len=%d\n", request->nob, request->block_len); + + if ( request->nob <= 0 ) { + DEBUG(1,": *** nob already at 0 ***\n"); + return; + } + + for ( i = 0 ; i < request->block_len ; i+=2, buf+=2 ) { + data = *(buf+1) | (((u16) *buf) << 8); + mmc->DataFifo = data; + mmc_delay(); + } + + START_DEBUG(2) { + u16 status = mmc->Status; + printk("%s: irq_mask=%04x status=0x%04x (", + __FUNCTION__, mmc->InterruptMask, status); + decode_status(status); + printk(")\n"); + } END_DEBUG; + + START_DEBUG(3) { + u8 *b = request->buffer; + for ( i = 0 ; i < request->block_len ; i++ ) { + printk(" %02x", *b++); + if ( ((i + 1) % 16) == 0 ) + printk("\n"); + } + } END_DEBUG; + + /* Updated the request buffer to reflect the current state */ + request->buffer = (u8 *) buf; + request->nob--; + g_lh7a400_mmc_statistics.mmc_written++; +} + +static void lh7a400_receive_data( struct mmc_request *request ) +{ + u8 *buf = request->buffer; + u16 data; + int i; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG(2,": nob=%d block_len=%d buf=%p\n", + request->nob, request->block_len, buf); + + if ( request->nob <= 0 ) { + DEBUG(1,": *** nob already at 0 ***\n"); + return; + } + + for ( i = 0 ; i < request->block_len ; i+=2 ) { + data = mmc->DataFifo; + mmc_delay(); + *buf++ = data >> 8; + *buf++ = data & 0xff; + } + + START_DEBUG(3) { + u8 *b = request->buffer; + for ( i = 0 ; i < request->block_len ; i++ ) { + printk(" %02x", *b++); + if ( ((i + 1) % 16) == 0 ) + printk("\n"); + } + } END_DEBUG; + + /* Updated the request buffer to reflect the current state */ + request->buffer = (u8 *) buf; + request->nob--; + g_lh7a400_mmc_statistics.mmc_read++; +} + +#ifdef CONFIG_MMC_DEBUG +#define STATBUG(_x) \ + { u16 status = mmc->Status; \ + if ( status & ~(MMC_STATUS_FIFO_EMPTY | MMC_STATUS_CLOCK_STOPPED)) { \ + printk("..." _x " status=0x%04x ( ", status); \ + decode_status(status); \ + printk(")\n"); \ + printk_mmc_state( "... "); \ + } \ + } +#else +#define STATBUG(_x) +#endif + +static int lh7a400_exec_command( struct mmc_request *request ) +{ + int retval; + int cdc = 0; + int irq = 0; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + DEBUG(2,": request=%p status=%04x\n", request, mmc->Status ); + + /* Start the actual transfer */ + retval = lh7a400_stop_clock(); + if ( retval ) + return retval; + + STATBUG("stop_clock"); + + lh7a400_set_command( request->cmd, request->arg ); + + STATBUG("set_command"); + + switch (request->cmd) { + case MMC_READ_SINGLE_BLOCK: + case MMC_READ_MULTIPLE_BLOCK: + lh7a400_set_transfer( request->block_len, request->nob ); + cdc = MMC_CMD_DATA_CONT_READ | MMC_CMD_DATA_CONT_DATA_ENABLE; + irq = MMC_INT_MASK_BUFFER_READY | MMC_INT_MASK_DATA_TRANSFER_DONE; + g_lh7a400_data.type = RT_READ; + break; + case MMC_WRITE_BLOCK: + case MMC_WRITE_MULTIPLE_BLOCK: + lh7a400_set_transfer( request->block_len, request->nob ); + cdc = MMC_CMD_DATA_CONT_WRITE | MMC_CMD_DATA_CONT_DATA_ENABLE; + irq = MMC_INT_MASK_BUFFER_READY | MMC_INT_MASK_PROGRAM_DONE; + g_lh7a400_data.type = RT_WRITE; + break; + default: + irq = MMC_INT_MASK_END_COMMAND_RESPONSE; + g_lh7a400_data.type = RT_RESPONSE_ONLY; + break; + } + + cdc |= rinfo[request->rtype].cdc_flags; + + mmc->CmdDataControl = cdc; + DEBUG( 1, ": set CmdDataCont=0x%x\n", cdc); + mmc_delay(); + + STATBUG("cmd_data_cont"); + + /* these are the interrupts we *want* */ + mmc->InterruptMask = irq; + mmc_delay(); + + STATBUG("irq_mask"); + + lh7a400_start_clock(); + + START_DEBUG(2) { + u16 status = mmc->Status; + printk("%s: enabling irq mask=%04x status=0x%04x (", + __FUNCTION__, mmc->InterruptMask, status); + decode_status(status); + printk(")\n"); + } END_DEBUG; + + mod_timer( &g_lh7a400_data.irq_timer, jiffies + MMC_IRQ_TIMEOUT); + enable_irq( IRQ_MMC ); + g_lh7a400_mmc_statistics.mmc_command++; + return MMC_NO_ERROR; +} + +static void lh7a400_send_command( struct mmc_request *request ) +{ + int retval; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + START_DEBUG(1) { + printk("\n\n"); + } END_DEBUG; + DEBUG(1,": request=%p cmd=%d (%s) arg=%08x status=%04x\n", request, + request->cmd, get_cmd_name(request->cmd), request->arg, mmc->Status); + + /* TODO: Grab a lock???? */ + g_lh7a400_data.request = request; + request->result = MMC_NO_RESPONSE; /* Flag to indicate don't have a result yet */ + + if ( request->cmd == MMC_CIM_RESET ) { + retval = lh7a400_reset( &g_lh7a400_data ); + } + else { + retval = lh7a400_exec_command( request ); + if ( retval ) { + g_lh7a400_mmc_statistics.mmc_error++; + DEBUG(0,": ASIC not responding! Trying to reset\n"); + lh7a400_start_clock(); + + retval = reset_mmc_controller( g_lh7a400_data.clock ); + if ( retval ) { + DEBUG(0,": ASIC doesn't reset! Panic now!\n"); + } + else { + retval = lh7a400_exec_command( request ); + if ( retval ) { + DEBUG(0,": ASIC unable to exec!\n"); + } + } + } + } + + if ( retval ) { + request->result = retval; + mmc_cmd_complete( request ); + } +} + +/**************************************************************************/ +/* TODO: Need to mask interrupts?? */ + +static void lh7a400_get_response( struct mmc_request *request ) +{ + int i; + int len = rinfo[request->rtype].length; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + u8 *buf = request->response; + + /* Mark this as having a request result of some kind */ + request->result = MMC_NO_ERROR; + + if ( len <= 0 ) + return; + + for ( i = 0 ; i < len ; ) { + u16 data = mmc->ResultFifo; +#if ROTATE_RESP_FIFO /* only on older (-01) EVBs */ + buf[i++] = data >> 8; + buf[i++] = data & 0xff; +#else + buf[i++] = data & 0xff; + buf[i++] = data >> 8; +#endif + } + + START_DEBUG(2) { + printk("%s Raw byte stream: ", __FUNCTION__); + for ( i = 0 ; i < len; i++ ) + printk("%02x ", buf[i]); + printk("\n"); + } END_DEBUG; +} + +static void lh7a400_handle_int( struct lh7a400_mmc_data *sd, u16 status, int timeout ) +{ + int retval = MMC_NO_ERROR; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + START_DEBUG( 1) { + printk("%s: status=%04x intStatus=%04x type=", + __FUNCTION__, status, mmc->InterruptStatus); + switch (g_lh7a400_data.type) { + case RT_NO_RESPONSE: printk( "RT_NO_RESPONSE\n"); break; + case RT_RESPONSE_ONLY: printk( "RT_RESPONSE_ONLY\n"); break; + case RT_READ: printk( "RT_READ\n"); break; + case RT_WRITE: printk( "RT_WRITE\n"); break; + } + } END_DEBUG; + + disable_irq( IRQ_MMC ); + + if ( status & (MMC_STATUS_READ_TIMEOUT + | MMC_STATUS_RESPONSE_TIMEOUT )) { + retval = MMC_ERROR_TIMEOUT; + goto terminate_int; + } + + if ( status & ( MMC_STATUS_CRC_WRITE_ERROR + | MMC_STATUS_CRC_READ_ERROR + | MMC_STATUS_SPI_READ_ERROR + | MMC_STATUS_CRC_RESPONSE_ERROR)) { + + while( mmc->Status & MMC_STATUS_FIFO_FULL) { + u16 foo; + DEBUG(0,": CRC error: Flushing FIFO\n"); + foo = mmc->DataFifo; + } + + retval = MMC_ERROR_CRC; + goto terminate_int; + } + + if ( (status & MMC_STATUS_END_COMMAND_RESPONSE) && + sd->request->result == MMC_NO_RESPONSE ) + { + lh7a400_get_response( sd->request ); + } + + if (g_lh7a400_data.type == RT_READ && + (status & (MMC_STATUS_FIFO_FULL | + MMC_STATUS_DATA_TRANSFER_DONE)) != 0) + { + lh7a400_receive_data( sd->request ); + } + + if (g_lh7a400_data.type == RT_WRITE && + (status & MMC_STATUS_FIFO_EMPTY ) != 0 && sd->request->nob > 0 ) + { + lh7a400_transmit_data( sd->request ); + } + + switch (g_lh7a400_data.type) { + case RT_NO_RESPONSE: + break; + + case RT_RESPONSE_ONLY: + if ( sd->request->result < 0 ) { + printk(KERN_INFO + "%s: illegal interrupt - " + "command hasn't finished\n", + __FUNCTION__); + retval = MMC_ERROR_TIMEOUT; + } + break; + case RT_READ: + if ( sd->request->nob ) { + DEBUG(2,": read re-enabling IRQ status=0x%04x\n", + mmc->InterruptStatus); + mod_timer( &sd->irq_timer, jiffies + MMC_IRQ_TIMEOUT); + lh7a400_start_clock(); + enable_irq( IRQ_MMC ); + return; + } + break; + case RT_WRITE: + if ( sd->request->nob || !(status & MMC_STATUS_END_PROGRAM) ) { + DEBUG(2,": write re-enabling IRQ status=0x%04x\n", + mmc->InterruptStatus); + mod_timer( &sd->irq_timer, jiffies + MMC_IRQ_TIMEOUT); + lh7a400_start_clock(); + enable_irq( IRQ_MMC ); + return; + } + break; + } + + DEBUG(2,": terminating status=0x%04x\n", mmc->Status ); + +terminate_int: + mmc->InterruptMask = MMC_INT_MASK_END_COMMAND_RESPONSE; + mmc->EOI = 0x1f; + + del_timer_sync( &sd->irq_timer ); + sd->request->result = retval; + mmc_cmd_complete( sd->request ); +} + +static void mmc_lh7a400_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct lh7a400_mmc_data *sd = (struct lh7a400_mmc_data *) dev_id; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + u16 status = mmc->Status; + START_DEBUG(2) { + printk_mmc_state( "IRQ "); + } END_DEBUG; + + START_DEBUG(2) { + printk("%s sd=%p status=0x%04x (", + __FUNCTION__, sd, status); + decode_status(status); + printk(")\n"); + } END_DEBUG; + + lh7a400_handle_int( sd, status, 0 ); +} + +static void lh7a400_irq_timeout( unsigned long nr ) +{ + struct lh7a400_mmc_data *sd = (struct lh7a400_mmc_data *) nr; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + u16 status = mmc->Status; + + START_DEBUG(1) { + printk("%s: irq_status=0x%x irq_mask=%04x status=0x%04x (", + __FUNCTION__, + mmc->InterruptStatus, mmc->InterruptMask, status); + decode_status(status); + printk(")\nRequest info:\n"); + printk_request( sd->request, " " ); + + printk_mmc_state( "IRQ timeout: "); + } END_DEBUG; + + g_lh7a400_mmc_statistics.mmc_timeout++; + lh7a400_handle_int( sd, status, 1 ); +} + + +/**************************************************************************/ + +static void lh7a400_fix_sd_detect( unsigned long nr ) +{ + int insert = lh7a400_slot_is_empty(0) ? 0 : 1; + + DEBUG(2,": insert=%d\n", insert); + + if ( insert ) { + mmc_insert(0); + g_lh7a400_mmc_statistics.mmc_insert++; + } + else { + mmc_eject(0); + g_lh7a400_mmc_statistics.mmc_eject++; + } +} + +static void mmc_lh7a400_detect_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct lh7a400_mmc_data *sd = (struct lh7a400_mmc_data *) dev_id; + + DEBUG( 1, ": slot_is_empty=%d\n", lh7a400_slot_is_empty(0) ); + + mod_timer( &sd->sd_detect_timer, jiffies + (250 * HZ) / 1000 ); +} + +static int lh7a400_slot_is_empty( int slot ) +{ +#ifdef CONFIG_MACH_KEV7A400 + cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + + DEBUG( 1, "\n"); + + return(cpld->bootMMCstatus & MMC_DETECT ? 0 : 1); +#else + return 1; +#endif +} + + +/**************************************************************************/ + + +static void mmc_lh7a400_slot_up( void ) +{ + DEBUG( 1, "\n"); +} + +static void mmc_lh7a400_slot_down( void ) +{ + DEBUG( 1, "\n"); + disable_irq( IRQ_MMC ); +} + + +static int lh7a400_slot_init( void ) +{ + int retval; + int i; + mmcRegs_t *mmc = (mmcRegs_t *)IO_ADDRESS(MMC_PHYS); + + DEBUG(1,"\n"); + +#ifdef CONFIG_MACH_KEV7A400 +#ifdef LH7A400_EVB_01 /* only on older (-01) EVBs */ + /* Enable power to the MMC slot */ + set_ioBrdCtl_bit( CPLD_IOB_MMC_POWER_ON); + DEBUG(1," MMC slot Power On, before loop.\n"); + for( i=0; i<2500000; i++) + ; + DEBUG(1," MMC slot Power On, loop done.\n"); +#endif +#endif + + /* + * flush the fifos + */ + for( i=0; i < 16; i++) { + u16 foo; + foo = mmc->DataFifo; + foo = mmc->ResultFifo; + } + + /* Set up timers */ + g_lh7a400_data.sd_detect_timer.function = lh7a400_fix_sd_detect; + g_lh7a400_data.sd_detect_timer.data = (unsigned long) &g_lh7a400_data; + init_timer(&g_lh7a400_data.sd_detect_timer); + + g_lh7a400_data.reset_timer.function = lh7a400_reset_timeout; + g_lh7a400_data.reset_timer.data = (unsigned long) &g_lh7a400_data; + init_timer(&g_lh7a400_data.reset_timer); + + g_lh7a400_data.irq_timer.function = lh7a400_irq_timeout; + g_lh7a400_data.irq_timer.data = (unsigned long) &g_lh7a400_data; + init_timer(&g_lh7a400_data.irq_timer); + + /* Basic service interrupt */ + mmc->InterruptMask = 0; + retval = request_irq( IRQ_MMC, mmc_lh7a400_int, + SA_INTERRUPT, "MMC", &g_lh7a400_data ); + + if( retval ) { + printk(KERN_CRIT "%s: unable to grab MMC IRQ, retval=0x%x\n", + __FUNCTION__, retval); + return retval; + } + disable_irq( IRQ_MMC ); + + /* + * Enable FIFO reads via APB, enable the MMC, and set the PreDivider. + */ + mmc->PreDivider = + (MMC_PREDIV_ENABLE | MMC_PREDIV_APB_ENABLE | HCLK_DIVISOR); + + DEBUG(1,": " + "status=0x%04x ClockControl=0x%x PreDivider=0x%x\n", + mmc->Status, mmc->ClockControl, mmc->PreDivider); + + /* Disable SPI mode control functions */ + mmc->SPIModeControl = 0; + + /* Fixes the sd_detect interrupt direction */ + mmc_lh7a400_slot_up(); + + retval = request_irq(IRQ_KEV7A400_MMC_DETECT, mmc_lh7a400_detect_int, + SA_INTERRUPT, "MMC Detect", &g_lh7a400_data ); + + if( retval ) { + printk(KERN_CRIT + "%s: unable to grab MMC DETECT IRQ, retval=0x%x\n", + __FUNCTION__, retval); + mmc_lh7a400_slot_down(); + free_irq( IRQ_MMC, &g_lh7a400_data); + } + return retval; +} + +static void lh7a400_slot_cleanup( void ) +{ + DEBUG(1,"\n"); + + del_timer_sync(&g_lh7a400_data.sd_detect_timer); + del_timer_sync(&g_lh7a400_data.reset_timer); + del_timer_sync(&g_lh7a400_data.irq_timer); + + mmc_lh7a400_slot_down(); + + free_irq(IRQ_KEV7A400_MMC_DETECT, &g_lh7a400_data); + free_irq(IRQ_MMC, &g_lh7a400_data); +} + + +/***********************************************************/ + +static struct mmc_slot_driver dops = { + owner: THIS_MODULE, + name: "LH7A400 MMC", + ocr: 0x00ffc000, + flags: MMC_SDFLAG_MMC_MODE, + + init: lh7a400_slot_init, + cleanup: lh7a400_slot_cleanup, + is_empty: lh7a400_slot_is_empty, + send_cmd: lh7a400_send_command, + set_clock: lh7a400_set_clock, +}; + +#ifdef CONFIG_CPU_FREQ +/* + * HCLK clock speed change handler. + */ +static int +mmc_clkchg_notifier(struct notifier_block *nb, unsigned long val, void *data) +{ + switch (val) { + case HCLKFREQ_PRECHANGE: + DEBUG( 2,": mmc PRE CHANGE\n"); + break; + + case HCLKFREQ_POSTCHANGE: + DEBUG( 2,": mmc POST CHANGE\n"); + if( g_lh7a400_data.rate != 0) + lh7a400_set_clock( g_lh7a400_data.rate); + break; + } + return 0; +} + +static struct notifier_block mmc_hclk_nb = { + notifier_call: mmc_clkchg_notifier, +}; + +#endif /* CONFIG_CPU_FREQ */ + + +static int +__init lh7a400_mmc_init(void) +{ + int retval; + + DEBUG(1,"\n"); + + retval = mmc_register_slot_driver(&dops, 1); + if ( retval < 0 ) { + printk(KERN_INFO "%s: unable to register slot\n",__FUNCTION__); + return retval; + } +#ifdef CONFIG_CPU_FREQ + hclkfreq_register_notifier( &mmc_hclk_nb); +#endif + return 0; +} + +void __exit lh7a400_mmc_cleanup(void) +{ + DEBUG(1,"\n"); +#ifdef CONFIG_CPU_FREQ + hclkfreq_unregister_notifier( &mmc_hclk_nb); +#endif + mmc_unregister_slot_driver(&dops); +} + +module_init(lh7a400_mmc_init); +module_exit(lh7a400_mmc_cleanup); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mach-lh7a400/mmc.h linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/mmc.h --- linux-2.4.21-rmk1/arch/arm/mach-lh7a400/mmc.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mach-lh7a400/mmc.h Thu Oct 16 15:20:44 2003 @@ -0,0 +1,154 @@ +/* + * Driver interface to the MMC controller on the Sharp LH7A400 SoC. + * + * Portions Copyright (C) 2002 Embedix, Inc + * Strongly based on code for the iPAQ H3800, see below. + * + * 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 + */ + +/* +* Driver interface to the ASIC Complasion chip on the iPAQ H3800 +* +* Copyright 2001 Compaq Computer Corporation. +* +* Use consistent with the GNU GPL is permitted, +* provided that this copyright notice is +* preserved in its entirety in all copies and derived works. +* +* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, +* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS +* FITNESS FOR ANY PARTICULAR PURPOSE. +* +* Author: Andrew Christian +* +* October 2001 +* +* Restrutured June 2002 +*/ + +#ifndef MMC_H +#define MMC_H + +int lh7a400_asic_mmc_init(void); +void lh7a400_asic_mmc_cleanup(void); +int lh7a400_asic_mmc_suspend(void); +void lh7a400_asic_mmc_resume(void); + +/* + * MMC register set structure + */ +typedef struct { + volatile u32 ClockControl; /* Clock control register */ + volatile u32 Status; /* Adapter status */ + volatile u32 ClockRate; /* Clock divider */ + volatile u32 PreDivider; /* Clock pre-divider */ + volatile u32 SPIModeControl; /* SPI mode control */ + volatile u32 CmdDataControl; /* Command control */ + volatile u32 ResponseTimeout; /* Response timeout */ + volatile u32 ReadTimeout; /* Read timeout */ + volatile u32 BlockLength; /* Block length */ + volatile u32 NumOfBLocks; /* Number of blocks */ + volatile u32 InterruptStatus; /* Interrupt status */ + volatile u32 EOI; /* Interrupt clear register */ + volatile u32 rsv1; + volatile u32 InterruptMask; /* Interrupt enables */ + volatile u32 CommandNumber; /* Command number */ + volatile u32 CommandArg; /* Command argument */ + volatile u32 ResultFifo; /* Result FIFO */ + volatile u32 rsv2; + volatile u32 DataFifo; /* Data FIFO */ + volatile u32 BufferPartFull; /* Partial buffer selection */ +} mmcRegs_t; + + + +/* ClockControl register bits */ +#define MMC_STOP_CLOCK _BIT(0) +#define MMC_START_CLOCK _BIT(1) + + +/* Status register bits */ +#define MMC_STATUS_READ_TIMEOUT _BIT(0) +#define MMC_STATUS_RESPONSE_TIMEOUT _BIT(1) +#define MMC_STATUS_CRC_WRITE_ERROR _BIT(2) +#define MMC_STATUS_CRC_READ_ERROR _BIT(3) +#define MMC_STATUS_SPI_READ_ERROR _BIT(4) /* SPI data token error received */ +#define MMC_STATUS_CRC_RESPONSE_ERROR _BIT(5) +#define MMC_STATUS_FIFO_EMPTY _BIT(6) +#define MMC_STATUS_FIFO_FULL _BIT(7) +#define MMC_STATUS_CLOCK_STOPPED _BIT(8) /* MultiMediaCard clock stopped */ +#define MMC_STATUS_DATA_TRANSFER_DONE _BIT(11) /* Write operation, indicates transfer finished */ +#define MMC_STATUS_END_PROGRAM _BIT(12) /* End write and read operations */ +#define MMC_STATUS_END_COMMAND_RESPONSE _BIT(13) /* End command response */ + + +/* ClockRate register bits */ +#define MMC_CLOCK_RATE_FULL 0 +#define MMC_CLOCK_RATE_DIV_2 1 +#define MMC_CLOCK_RATE_DIV_4 2 +#define MMC_CLOCK_RATE_DIV_8 3 +#define MMC_CLOCK_RATE_DIV_16 4 +#define MMC_CLOCK_RATE_DIV_32 5 +#define MMC_CLOCK_RATE_DIV_64 6 + + +/* PreDivider register bits */ +#define MMC_PREDIV_ENABLE _BIT(4) /* Enables PCLK to the MMC */ +#define MMC_PREDIV_APB_ENABLE _BIT(5) /* Enables reading the FIFO via APB, not DMA */ + + +/* SPIModeControl register bits */ +#define MMC_SPI_REG_SPI_ENABLE _BIT(0) /* Enables SPI mode */ +#define MMC_SPI_REG_CRC_ON _BIT(1) /* 1:turn on CRC */ +#define MMC_SPI_REG_SPI_CS_ENABLE _BIT(2) /* 1:turn on SPI CS */ +#define MMC_SPI_REG_CS_ADDRESS _BIT(3) /* specifies the relative address of the card + to activate the SPI CS as 0 or 1 */ + +/* CmdDataControl register bits */ +#define MMC_CMD_DATA_CONT_FORMAT_NO_RESPONSE _SBF(0,0) /* Response format */ +#define MMC_CMD_DATA_CONT_FORMAT_R1 _SBF(0,1) +#define MMC_CMD_DATA_CONT_FORMAT_R2 _SBF(0,2) +#define MMC_CMD_DATA_CONT_FORMAT_R3 _SBF(0,3) +#define MMC_CMD_DATA_CONT_DATA_ENABLE _BIT(2) /* This command contains a data transfer */ +#define MMC_CMD_DATA_CONT_READ _SBF(3,0) /* This data transfer is a read */ +#define MMC_CMD_DATA_CONT_WRITE _SBF(3,1) /* This data transfer is a write */ +#define MMC_CMD_DATA_CONT_STREAM_BLOCK _BIT(4) /* This data transfer is in stream mode */ +#define MMC_CMD_DATA_CONT_BUSY_BIT _BIT(5) +#define MMC_CMD_DATA_CONT_INITIALIZE _BIT(6) /* Enables the 80 bits for initializing card */ + + +/* Interrupt Status and InterruptMask register bits */ +#define MMC_INT_MASK_DATA_TRANSFER_DONE _BIT(0) +#define MMC_INT_MASK_PROGRAM_DONE _BIT(1) +#define MMC_INT_MASK_END_COMMAND_RESPONSE _BIT(2) +#define MMC_INT_MASK_BUFFER_READY _BIT(3) +#define MMC_INT_MASK_ALL (0xf) + + + +/* Statistics */ +struct mmc_statistics { + u32 mmc_insert; + u32 mmc_eject; + u32 mmc_reset; /* Reset commands issued */ + u32 mmc_command; /* General commands issued */ + u32 mmc_read; /* Blocks */ + u32 mmc_written; /* Blocks */ + u32 mmc_timeout; /* Timeout interrupts */ + u32 mmc_error; /* Response errors */ +}; + +#endif /* MMC_H */ diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mm/discontig.c linux-2.4.21-rmk1-lh7a400/arch/arm/mm/discontig.c --- linux-2.4.21-rmk1/arch/arm/mm/discontig.c Fri Jun 13 10:51:29 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mm/discontig.c Thu Oct 16 14:27:01 2003 @@ -16,8 +16,11 @@ #include #if NR_NODES != 4 +#ifdef CONFIG_ARCH_LH7A400 +#else #error Fix Me Please #endif +#endif /* * Our node_data structure for discontiguous memory. @@ -30,6 +33,21 @@ { bdata: &node_bootmem_data[1] }, { bdata: &node_bootmem_data[2] }, { bdata: &node_bootmem_data[3] } +#ifdef CONFIG_ARCH_LH7A400 + , + { bdata: &node_bootmem_data[4] }, + { bdata: &node_bootmem_data[5] }, + { bdata: &node_bootmem_data[6] }, + { bdata: &node_bootmem_data[7] }, + { bdata: &node_bootmem_data[8] }, + { bdata: &node_bootmem_data[9] }, + { bdata: &node_bootmem_data[10] }, + { bdata: &node_bootmem_data[11] }, + { bdata: &node_bootmem_data[12] }, + { bdata: &node_bootmem_data[13] }, + { bdata: &node_bootmem_data[14] }, + { bdata: &node_bootmem_data[15] } +#endif }; EXPORT_SYMBOL(discontig_node_data); diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mm/init.c linux-2.4.21-rmk1-lh7a400/arch/arm/mm/init.c --- linux-2.4.21-rmk1/arch/arm/mm/init.c Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mm/init.c Thu Oct 16 14:27:37 2003 @@ -35,7 +35,11 @@ #ifndef CONFIG_DISCONTIGMEM #define NR_NODES 1 #else -#define NR_NODES 4 + #ifdef CONFIG_ARCH_LH7A400 + #define NR_NODES 16 + #else + #define NR_NODES 4 + #endif #endif #ifdef CONFIG_CPU_32 diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/mm/proc-arm922.S linux-2.4.21-rmk1-lh7a400/arch/arm/mm/proc-arm922.S --- linux-2.4.21-rmk1/arch/arm/mm/proc-arm922.S Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/mm/proc-arm922.S Thu Oct 16 17:01:04 2003 @@ -647,7 +647,11 @@ __arm922_proc_info: .long 0x41009220 .long 0xff00fff0 +#if defined(CONFIG_CPU_ARM922_WRITETHROUGH) + .long 0x00000c1a @ mmuflags +#else .long 0x00000c1e @ mmuflags +#endif b __arm922_setup .long cpu_arch_name .long cpu_elf_name diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/arch/arm/tools/mach-types linux-2.4.21-rmk1-lh7a400/arch/arm/tools/mach-types --- linux-2.4.21-rmk1/arch/arm/tools/mach-types Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/arch/arm/tools/mach-types Sat Oct 18 07:53:13 2003 @@ -363,3 +363,5 @@ ixrd425 ARCH_IXRD425 IXRD425 352 iq80315 ARCH_IQ80315 IQ80315 353 nmp7312 ARCH_NMP7312 NMP7312 354 +kev7a400 MACH_KEV7A400 KEV7A400 388 +eframe MACH_EFRAME EFRAME 398 diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/build linux-2.4.21-rmk1-lh7a400/build --- linux-2.4.21-rmk1/build Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/build Fri Feb 6 15:17:25 2004 @@ -0,0 +1,2 @@ +#make zImage && cp arch/arm/boot/zImage /tftpboot/arm +make zImage && cp arch/arm/boot/zImage /tftpboot/sharp diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/dot.config linux-2.4.21-rmk1-lh7a400/dot.config --- linux-2.4.21-rmk1/dot.config Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/dot.config Thu Oct 16 17:05:41 2003 @@ -0,0 +1,999 @@ +# +# 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=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_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_LH7A400=y +# 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 + +# +# 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 + +# +# Sharp LH7A400 Implementations +# +CONFIG_ARCH_KEV7A400=y +# 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=y +CONFIG_PLD=y +# 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_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# 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=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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_LH7A400=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# 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 is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" +CONFIG_ALIGNMENT_TRAP=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=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# 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=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# 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=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES 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=y +# 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 is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_CS89x0=y +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 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=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_AIRO is not set +CONFIG_HERMES=y + +# +# Wireless Pcmcia cards support +# +CONFIG_PCMCIA_HERMES=y +# CONFIG_AIRO_CS is not set +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=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=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +CONFIG_IRPORT_SIR=y + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD 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/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=y +# 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 is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_LH7X_KEYBOARD_DRIVER is not set +CONFIG_LH7X_BUTTON_DRIVER=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_LH7A400=y +CONFIG_SERIAL_LH7A400_CONSOLE=y +# 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_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# 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 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 + +# +# 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_LH7A400_DC2DC=y +# CONFIG_RTC is not set +# CONFIG_LH7A400_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_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=y +# 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_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 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_NFSD_TCP 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# 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 is not set +# 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_PL110=y +CONFIG_PL110_LQ39=y +# CONFIG_PL110_LM57 is not set +# CONFIG_PL110_LQ57 is not set +# CONFIG_PL110_LQ121 is not set +# CONFIG_PL110_LQ104 is not set +# 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=y +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=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# 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_LH7A400=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +# 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 + +# +# Misc devices +# +CONFIG_TOUCHSCREEN_LH7X=y +# CONFIG_EEPROM_LH7X is not set +# CONFIG_7SEGMENT_LH7X is not set +# CONFIG_LH7A400_SCI is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG 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 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=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/dot.config2 linux-2.4.21-rmk1-lh7a400/dot.config2 --- linux-2.4.21-rmk1/dot.config2 Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/dot.config2 Sun Oct 19 06:19:50 2003 @@ -0,0 +1,1008 @@ +# +# 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=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_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_LH7A400=y +# 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 + +# +# 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 + +# +# Sharp LH7A400 Implementations +# +CONFIG_MACH_KEV7A400=y +# CONFIG_MACH_EFRAME is not set + +# +# Acorn +# +# CONFIG_ARCH_ACORN is not set + +# +# Footbridge support +# +# 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=y +# 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_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# 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=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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_LH7A400=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# 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 is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" +CONFIG_ALIGNMENT_TRAP=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=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# 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=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# 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=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES 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=y +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 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=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_AIRO is not set +CONFIG_HERMES=y + +# +# Wireless Pcmcia cards support +# +CONFIG_PCMCIA_HERMES=y +# CONFIG_AIRO_CS is not set +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=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=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +CONFIG_IRPORT_SIR=y + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD 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/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=y +# 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 is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_LH7X_KEYBOARD_DRIVER is not set +CONFIG_LH7X_BUTTON_DRIVER=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_LH7A400=y +CONFIG_SERIAL_LH7A400_CONSOLE=y +# 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_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# 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 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 + +# +# 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_LH7A400_DC2DC=y +# CONFIG_RTC is not set +# CONFIG_LH7A400_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_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=y +# 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_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 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_NFSD_TCP 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# 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 is not set +# 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_PL110=y +CONFIG_PL110_LQ39=y +# CONFIG_PL110_LM57 is not set +# CONFIG_PL110_LQ57 is not set +# CONFIG_PL110_LQ121 is not set +# CONFIG_PL110_LQ104 is not set +# 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=y +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=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# 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_LH7A400=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +# 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 + +# +# Misc devices +# +CONFIG_TOUCHSCREEN_LH7X=y +# CONFIG_EEPROM_LH7X is not set +# CONFIG_7SEGMENT_LH7X is not set +# CONFIG_LH7A400_SCI is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG 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 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=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/dot.config3 linux-2.4.21-rmk1-lh7a400/dot.config3 --- linux-2.4.21-rmk1/dot.config3 Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/dot.config3 Sun Feb 8 19:04:08 2004 @@ -0,0 +1,1083 @@ +# +# 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=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_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_LH7A400=y +# 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 + +# +# 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 + +# +# Sharp LH7A400 Implementations +# +CONFIG_MACH_KEV7A400=y +# CONFIG_MACH_EFRAME is not set + +# +# Acorn +# +# CONFIG_ARCH_ACORN is not set + +# +# Footbridge support +# +# 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=y +# 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_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# 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=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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_LH7A400=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# 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 is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" +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 + +# +# 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=y +# CONFIG_MTD_SYNCFLASH_PROBE 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_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_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_KEV7A400=y +# CONFIG_MTD_KEV7A400_SYNC 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=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# 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=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# 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=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES 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=y +# 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_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 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=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_AIRO is not set +CONFIG_HERMES=y + +# +# Wireless Pcmcia cards support +# +CONFIG_PCMCIA_HERMES=y +# CONFIG_AIRO_CS is not set +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=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=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +CONFIG_IRPORT_SIR=y + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD 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/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=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 + +# +# 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=y +# 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 is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_LH7X_KEYBOARD_DRIVER is not set +CONFIG_LH7X_BUTTON_DRIVER=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_LH7A400=y +CONFIG_SERIAL_LH7A400_CONSOLE=y +# 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_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# 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 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 + +# +# 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_LH7A400_DC2DC=y +# CONFIG_RTC is not set +# CONFIG_LH7A400_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_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=y +# 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_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 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_NFSD_TCP 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# 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 is not set +# 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_PL110=y +CONFIG_PL110_LQ39=y +# CONFIG_PL110_LM57 is not set +# CONFIG_PL110_LQ57 is not set +# CONFIG_PL110_LQ121 is not set +# CONFIG_PL110_LQ104 is not set +# 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=y +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=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# 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_LH7A400=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +# 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 + +# +# Misc devices +# +CONFIG_TOUCHSCREEN_LH7X=y +# CONFIG_EEPROM_LH7X is not set +# CONFIG_7SEGMENT_LH7X is not set +# CONFIG_LH7A400_SCI is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG 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 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=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/dot.config4 linux-2.4.21-rmk1-lh7a400/dot.config4 --- linux-2.4.21-rmk1/dot.config4 Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/dot.config4 Thu Feb 19 21:22:16 2004 @@ -0,0 +1,1083 @@ +# +# 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=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_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_LH7A400=y +# 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 + +# +# 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 + +# +# Sharp LH7A400 Implementations +# +CONFIG_MACH_KEV7A400=y +# CONFIG_MACH_EFRAME is not set + +# +# Acorn +# +# CONFIG_ARCH_ACORN is not set + +# +# Footbridge support +# +# 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=y +# 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_32v3 is not set +CONFIG_CPU_32v4=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +CONFIG_ISA=y +# 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=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_PCMCIA_PROBE=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_LH7A400=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# 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 is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="" +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 + +# +# 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=y +# CONFIG_MTD_SYNCFLASH_PROBE 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_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_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_KEV7A400=y +# CONFIG_MTD_KEV7A400_SYNC 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=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# 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=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# 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=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES 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=y +# 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 is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_CS89x0=y +# CONFIG_TULIP is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 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=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_AIRO is not set +CONFIG_HERMES=y + +# +# Wireless Pcmcia cards support +# +CONFIG_PCMCIA_HERMES=y +# CONFIG_AIRO_CS is not set +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=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=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +CONFIG_IRCOMM=y +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=y +CONFIG_IRPORT_SIR=y + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD 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/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=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 + +# +# 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=y +# 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 is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_KEV7X_KEYBOARD_DRIVER is not set +CONFIG_KEV7X_BUTTON_DRIVER=y + +# +# Serial drivers +# +# CONFIG_SERIAL_ANAKIN is not set +# CONFIG_SERIAL_ANAKIN_CONSOLE is not set +# CONFIG_SERIAL_AMBA is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_LH7A400=y +CONFIG_SERIAL_LH7A400_CONSOLE=y +# 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_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# 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 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 + +# +# 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_LH7A400_DC2DC=y +# CONFIG_RTC is not set +# CONFIG_LH7A400_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_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=y +# 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_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 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_NFSD_TCP 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 + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# 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 is not set +# 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_PL110=y +CONFIG_PL110_LQ39=y +# CONFIG_PL110_LM57 is not set +# CONFIG_PL110_LQ57 is not set +# CONFIG_PL110_LQ121 is not set +# CONFIG_PL110_LQ104 is not set +# 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=y +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=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# 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_LH7A400=y +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_VIDC is not set +# CONFIG_SOUND_WAVEARTIST is not set +# 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 + +# +# Misc devices +# +CONFIG_KEV7X_TOUCHSCREEN=y +CONFIG_KEV7X_EEPROM=y +CONFIG_KEV7X_7SEGMENT=y +# CONFIG_LH7A400_SCI is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG 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 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=y +# CONFIG_DEBUG_DC21285_PORT is not set +# CONFIG_DEBUG_CLPS711X_UART2 is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/Makefile linux-2.4.21-rmk1-lh7a400/drivers/Makefile --- linux-2.4.21-rmk1/drivers/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/Makefile Thu Oct 16 15:20:44 2003 @@ -8,7 +8,7 @@ mod-subdirs := dio hil mtd sbus video macintosh usb input telephony sgi ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ - fc4 net/hamradio i2c l3 acpi bluetooth serial + fc4 net/hamradio i2c l3 acpi bluetooth serial mmc subdir-y := parport serial char block net sound misc media cdrom hotplug pld subdir-m := $(subdir-y) @@ -49,6 +49,7 @@ subdir-$(CONFIG_ACPI) += acpi subdir-$(CONFIG_BLUEZ) += bluetooth +subdir-$(CONFIG_MMC) += mmc subdir-$(CONFIG_SSI) += ssi subdir-$(CONFIG_ARCH_AT91RM9200)+= at91 diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/Config.in linux-2.4.21-rmk1-lh7a400/drivers/char/Config.in --- linux-2.4.21-rmk1/drivers/char/Config.in Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/Config.in Sun Feb 8 20:26:52 2004 @@ -137,6 +137,11 @@ tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV fi +if [ "$CONFIG_ARCH_LH7A400" = "y" -o "$CONFIG_ARCH_LH79520" = "y" ]; then + dep_tristate 'Enable KEV7A400/79520 Keyboard Driver' CONFIG_KEV7X_KEYBOARD_DRIVER $CONFIG_INPUT + dep_tristate 'Enable KEV7A400/79520 Button Driver' CONFIG_KEV7X_BUTTON_DRIVER $CONFIG_INPUT +fi + source drivers/serial/Config.in if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then @@ -271,6 +276,7 @@ fi dep_tristate 'AMD 76x native power management (Experimental)' CONFIG_AMD_PM768 $CONFIG_PCI tristate '/dev/nvram support' CONFIG_NVRAM +tristate 'LH7A400 DC to DC Support' CONFIG_LH7A400_DC2DC tristate 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_IA64" = "y" ]; then bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC @@ -287,6 +293,9 @@ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC fi +if [ "$CONFIG_ARCH_LH7A400" = "y" ]; then + tristate 'LH7A400 Real Time Clock' CONFIG_LH7A400_RTC +fi tristate 'Double Talk PC internal speech card support' CONFIG_DTLK tristate 'Siemens R3964 line discipline' CONFIG_R3964 diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/Makefile linux-2.4.21-rmk1-lh7a400/drivers/char/Makefile --- linux-2.4.21-rmk1/drivers/char/Makefile Thu Oct 16 10:10:08 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/Makefile Sun Feb 8 20:21:05 2004 @@ -135,6 +135,12 @@ ifeq ($(CONFIG_ARCH_GUIDEA07),y) KEYMAP := defkeymap.o endif + ifeq ($(CONFIG_ARCH_LH79520),y) + KEYBD += lh7x-keyb.o + endif + ifeq ($(CONFIG_ARCH_LH7A400),y) + KEYBD += lh7x-keyb.o + endif endif ifeq ($(ARCH),sh) @@ -262,11 +268,13 @@ obj-$(CONFIG_ADBMOUSE) += adbmouse.o obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_MK712_MOUSE) += mk712.o +obj-$(CONFIG_LH7A400_DC2DC) += lh7a400_dc2dc.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o +obj-$(CONFIG_LH7A400_RTC) +=lh7a400_rtc.o ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o endif diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7a400_dc2dc.c linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_dc2dc.c --- linux-2.4.21-rmk1/drivers/char/lh7a400_dc2dc.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_dc2dc.c Sat Oct 18 13:12:50 2003 @@ -0,0 +1,345 @@ +/* + * linux/drivers/char/dc2dc.c + * + * Copyright (C) 2002 Embedix. + * + * Original code write was authored by Craig Matsuura + * Parts of this code are from Sharp. + * This code falls under the license of the GPL. + * + * This modules is for controlling the DC to DC converter. + * Jumps for backlighting and audio must be set correctly on the LH7a400 + * Board for this module to work properly. See Sharp LH7a400 Documentation + * for jumper settings. + */ +#define MODULES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lh7a400_dc2dc.h" + + +dc2dcRegs_t *dc2dcregs = (dc2dcRegs_t *) IO_ADDRESS( DCDC_PHYS); +cpldRegs_t *cpldregs = (cpldRegs_t *) CPLD_BASE; + +#define TYPE(dev) (MINOR(dev) >> 4) /* high nibble */ +#define NUM(dev) (MINOR(dev) & 0xf) /* low nibble */ + +static int dc2dc_major=0; // Major Number for Driver 0 indicates dynamic assignment +static int dc2dc_debug=0; +static int dc2dc_bl=0; /* 0=Not backlight control via cpld, 1=Control Backlight */ +static int audio_freq=0x7777; +static int audio_vol=0x7777; +static int audio_duration=100000; + +#ifdef MODULES +MODULE_PARM(dc2dc_bl,"i"); +MODULE_PARM(dc2dc_major,"i"); +MODULE_PARM(dc2dc_debug,"i"); +MODULE_PARM(audio_freq,"i"); +MODULE_PARM(audio_vol,"i"); +MODULE_PARM(audio_duration,"i"); +#endif + +/*********************************************************************** + * + * Function: lcd_priv_set_bl + * + * Purpose: + * Sets the backlight intensity (variable intensity). + * + * Processing: + * The passed value must be a value between 0 and max_intens. The + * value of max_intens may be different for different panel types. + * On panel types where max_intens = 1, the value of '1' will simply + * turn the backlight on. '0' will always turn the backlight off. + * + * Parameters: + * intens: Backlight intensity value + * + * Outputs: + * None + * + * Returns: + * Nothing + * + * Notes: + * The DC-DC converter 0 is used by default for backlight intensity + * control. + * + **********************************************************************/ +static void lcd_priv_set_bl (unsigned short intens) +{ + + if (dc2dc_bl != 1) + { + if (intens == 0) + { + // Disable backlight power + cpldregs->lcd_pwr_cntl &= ~CPLD_BACKLIGHT_ON; + } + else + { + // Enable backlight power + cpldregs->lcd_pwr_cntl |= CPLD_BACKLIGHT_ON; + + // Limit value of intens to PWM value + intens = intens & 0xF; + intens = intens | (intens << 4); + + dc2dcregs->dcdcfreq = PMPFREQ_DRV0_PREHI (7) | PMPFREQ_DRV0_PRELO (7); + dc2dcregs->dcdccon = intens; + } + } + else + { + + // Limit value of intens to PWM value + intens = intens & 0xF; + intens = intens | (intens << 4); + + dc2dcregs->dcdcfreq = PMPFREQ_DRV0_PREHI (7) | PMPFREQ_DRV0_PRELO (7); + dc2dcregs->dcdccon = intens; + } +} + +/* + * Test code for speaker sounds. + */ +static void spk_priv_set_sound (unsigned short intens) +{ + dc2dcregs->dcdcfreq = audio_freq; + dc2dcregs->dcdccon = intens; /* Voule Level */ +} + + +/* + * Start Sound with values in audio_freq and audio_vol + */ +static void startSnd(void) +{ + dc2dcregs->dcdcfreq = audio_freq; + dc2dcregs->dcdccon = audio_vol; +} + +/* + * Stop sound, reset freq and vol to zero. + */ +static void stopSnd(void) +{ + dc2dcregs->dcdcfreq = 0; + dc2dcregs->dcdccon = 0; +} +/* + * Beep a freq, vol for a duration. + */ +static void beep(void) +{ + startSnd(); + udelay(audio_duration); + stopSnd(); +} + + +/**************************************************************************** + * Open Function - Open the device either the Backlight or the Audio + * /dev/bl c 254 0 is the Backlighting + * /dev/dcdc1 c 254 1 is the Audio + * Keep in mind the 254 is only an example. If you do not specify a + * major code then a dynamic one will be assigned. You will have to + * look at /proc/devices to see the major code for pwm + */ +int dc2dc_open(struct inode * inode, struct file * filp) +{ + + MOD_INC_USE_COUNT; + +// printk("<4>open pwm... dc=%d, bl_dc=%d\n",pwmregs->pwm0.dc,pwm_backlight_dcycle); + switch (NUM(inode->i_rdev)) { + case 0: // Device 0 + break; + case 1: // Device 1 + break; + default: + printk("<4>Minor device unknown %d\n",NUM(inode->i_rdev)); + break; + } + + return 0; +} + +/**************************************************************************** + * + */ +int dc2dc_release(struct inode *inode, struct file * filp) +{ + //printk("<4>release dc2dc...\n"); + switch (NUM(inode->i_rdev)) { + case 0: // Device 0 + break; + case 1: // Device 1 + break; + default: + printk("<4>Minor device unknown %d\n",NUM(inode->i_rdev)); + break; + } + + MOD_DEC_USE_COUNT; + return 0; +} + +/**************************************************************************** + * + */ +ssize_t dc2dc_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + return 0; +} + +/**************************************************************************** + * + */ +ssize_t dc2dc_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + return 0; +} + +/**************************************************************************** + * + */ +int dc2dc_ioctl(struct inode *inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + //int err = 0, size = _IOC_SIZE(cmd); + + if (dc2dc_debug) + { + printk("IOCTL called!!!\n"); + } + + + if (_IOC_TYPE(cmd) != DC2DC_IOC_MAGIC) { + return -EINVAL; + } + if (_IOC_NR(cmd) > DC2DC_IOC_MAXNR) { + return -EINVAL; + } + + /* + Should check for direction bit's see page 101 in "Linux Device Drivers Book" + size and err used here. + */ + + switch (NUM(inode->i_rdev)) { + case 0: // device 0 (backlight) + switch (cmd) { + case DC2DC_IOCRESET: + printk("Reset dc2dc\n"); + break; + case DC2DC_IOCSETBL: + // printk("Set Backlight value to %ld\n",arg); + lcd_priv_set_bl(arg); + break; + + } + break; + + case 1: // Device 1 (Audio Device) + switch (cmd) { + case DC2DC_IOCBEEP: + beep(); + break; + case DC2DC_IOCSTARTSND: + startSnd(); + break; + case DC2DC_IOCSTOPSND: + stopSnd(); + break; + case DC2DC_IOCSETSND: + printk("Set Sound value to %ld\n",arg); + spk_priv_set_sound(arg); + break; + case DC2DC_IOCSETVOL: + audio_vol = arg; + break; + case DC2DC_IOCSETFREQ: + audio_freq = arg; + break; + case DC2DC_IOCGETVOL: + __put_user(audio_vol, (int *) arg); + break; + case DC2DC_IOCGETFREQ: + __put_user(audio_freq, (int *) arg); + break; + } + break; + } + + return 0; +} + + +/**************************************************************************** + * + */ +struct file_operations dc2dc_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + read: dc2dc_read, + write: dc2dc_write, + ioctl: dc2dc_ioctl, + open: dc2dc_open, + release: dc2dc_release, +}; + + +/**************************************************************************** + * + */ +static int __init dc2dc_init_module(void) +{ + int result; + + printk("<1>Sharp LH7a400 DC2DC Driver Copyright 2002 Embedix\n"); + + result = register_chrdev(dc2dc_major,"dc2dc",&dc2dc_fops); + if (result < 0) { + printk("<4>dc2dc: can't get major number %d\n",dc2dc_major); + return result; + } + if (dc2dc_major == 0) { + dc2dc_major = result; /* Dynamic Allocation of major number */ + printk("<4>DC2DC Dynamic Major Number %d\n",dc2dc_major); + } + + return 0; +} + +/**************************************************************************** + * + */ +static void __exit dc2dc_cleanup_module(void) +{ + int result; + + printk("<1>End DC2DC Module...\n"); + result = unregister_chrdev(dc2dc_major,"dc2dc"); +} + +module_init(dc2dc_init_module); +module_exit(dc2dc_cleanup_module); diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7a400_dc2dc.h linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_dc2dc.h --- linux-2.4.21-rmk1/drivers/char/lh7a400_dc2dc.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_dc2dc.h Thu Oct 16 15:17:24 2003 @@ -0,0 +1,79 @@ +/* + * linux/drivers/char/dc2dc.h + * + * Copyright (C) 2002 Embedix. + * + * Original code write was authored by Craig Matsuura + * Parts of this code are from Sharp. + * This code falls under the license of the GPL. + * + * This modules is for controlling the DC - DC audio and backlighting. + * Jumps for backlighting and audio must be set correctly on the LH7a400 + * Board for this module to work properly. See Sharp LH7a400 Documentation + * for jumper settings. + */ +#ifndef __DC2DC_H +#define __DC2DC_H + +typedef volatile struct { + volatile unsigned int dcdccon; // Drive0 and Drive1 configuration register RW + volatile unsigned int res1[1]; // Reserved: Reading this register returns 0x00000001 RO + volatile unsigned int dcdcfreq; // Frequency configuration register RW + volatile unsigned int res2[12]; // Reserved: Reading this register returns 0x00000001 RO + volatile unsigned int res3[24]; // Reserved: Unpredictable values. RO (DO not write) + volatile unsigned int res4[22]; // Reserved: Reading this register returns 0x00000001 RO +} dc2dcRegs_t; + +extern dc2dcRegs_t *dc2dcregs; + +/********************************************************************** + * DC-DC Converter Register Bit Fields + *********************************************************************/ + +/********************************************************************** + * PMPCON Register Bit Fields + *********************************************************************/ +#define PMPCON_DRV0_DTYHI(n) _SBF(0, (_BITMASK(4) & (n))) +#define PMPCON_DRV0_DTYLO(n) _SBF(4, (_BITMASK(4) & (n))) +#define PMPCON_DRV1_DTYHI(n) _SBF(8, (_BITMASK(4) & (n))) +#define PMPCON_DRV1_DTYLO(n) _SBF(12, (_BITMASK(4) & (n))) + +/********************************************************************** + * PMPFREQ Register Bit Fields + *********************************************************************/ +#define PMPFREQ_DRV0_PREHI(n) _SBF(0, (_BITMASK(3) & (n))) +#define PMPFREQ_DRV0_PRELO(n) _SBF(4, (_BITMASK(3) & (n))) +#define PMPFREQ_DRV1_PREHI(n) _SBF(8, (_BITMASK(3) & (n))) +#define PMPFREQ_DRV1_PRELO(n) _SBF(12, (_BITMASK(3) & (n))) + +// IOCTL's +#define DC2DC_IOC_MAGIC 'd' +#define DC2DC_IOCRESET _IO(DC2DC_IOC_MAGIC, 0) +#define DC2DC_IOCSETBL _IOW(DC2DC_IOC_MAGIC, 1, int) +#define DC2DC_IOCSETSND _IOW(DC2DC_IOC_MAGIC, 2, int) +#define DC2DC_IOCBEEP _IO(DC2DC_IOC_MAGIC, 3) +#define DC2DC_IOCSETFREQ _IOW(DC2DC_IOC_MAGIC, 4, int) +#define DC2DC_IOCSETVOL _IOW(DC2DC_IOC_MAGIC, 5, int) +#define DC2DC_IOCGETFREQ _IOR(DC2DC_IOC_MAGIC, 6, int) +#define DC2DC_IOCGETVOL _IOR(DC2DC_IOC_MAGIC, 7, int) +#define DC2DC_IOCSTARTSND _IO(DC2DC_IOC_MAGIC, 8) +#define DC2DC_IOCSTOPSND _IO(DC2DC_IOC_MAGIC, 9) +#define DC2DC_IOC_MAXNR 9 +/* +#define PWM520_IOCBEEP _IO(PWM520_IOC_MAGIC, 0) +#define PWM520_IOCSTARTSND _IO(PWM520_IOC_MAGIC, 1) +#define PWM520_IOCSTOPSND _IO(PWM520_IOC_MAGIC, 2) +#define PWM520_IOCSETFREQ _IOW(PWM520_IOC_MAGIC, 3, int) +#define PWM520_IOCSETDCYCLE _IOW(PWM520_IOC_MAGIC, 4, int) +#define PWM520_IOCGETFREQ _IOR(PWM520_IOC_MAGIC, 5, int) +#define PWM520_IOCGETDCYCLE _IOR(PWM520_IOC_MAGIC, 6, int) + +#define PWM520_IOCRESET _IO(PWM520_IOC_MAGIC, 7) +#define PWM520_IOCSTOPPWM0 _IO(PWM520_IOC_MAGIC, 8) +#define PWM520_IOCINCREASEBL _IO(PWM520_IOC_MAGIC, 9) +#define PWM520_IOCDECREASEBL _IO(PWM520_IOC_MAGIC, 10) +#define PWM520_IOCSETBL _IOW(PWM520_IOC_MAGIC, 11, int) + +#define PWM520_IOC_MAXNR 11 +*/ +#endif diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7a400_rtc.c linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_rtc.c --- linux-2.4.21-rmk1/drivers/char/lh7a400_rtc.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_rtc.c Thu Oct 16 15:17:24 2003 @@ -0,0 +1,404 @@ +/* + * Real Time Clock interface for Linux on Sharp LH7a400 + * + * Copyright (c) 2002 Lineo + * + * Based on sa1100_rtc.c by Nils Faerber + * 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. + * + * 0.01 2002-07-08 Craig Matsuura (cmatsuura@lineo.com) + * - initial release + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lh7a400_rtc.h" + +#define DRIVER_VERSION "0.02" + +#define RTCR_MIE 0x00000001 /* Match Int Enable Bit */ + +/* Those are the bits from a classic RTC we want to mimic */ +#define RTC_IRQF 0x80 /* any of the following 3 is active */ +#define RTC_PF 0x40 +#define RTC_AF 0x20 +#define RTC_UF 0x10 + + +rtcRegs_t *rtcregs = (rtcRegs_t *) IO_ADDRESS(RTC_PHYS); + +static unsigned long rtc_status; +static unsigned long rtc_irq_data; +static unsigned long rtc_freq = 1024; + +static struct fasync_struct *rtc_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); + +extern spinlock_t rtc_lock; + +static const unsigned char days_in_mo[] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define is_leap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + +/* + * Converts seconds since 1970-01-01 00:00:00 to Gregorian date. + */ +#define SECS_PER_MIN 60 +#define SECS_PER_HOUR (SECS_PER_MIN * SECS_PER_MIN) +#define SECS_PER_DAY (SECS_PER_HOUR * 24) +static unsigned int epoch=1970; +static void decodetime (unsigned long t, struct rtc_time *tval) +{ + long days, month, year, rem; + + days = t / SECS_PER_DAY; + rem = t % SECS_PER_DAY; + tval->tm_hour = rem / SECS_PER_HOUR; + rem %= SECS_PER_HOUR; + tval->tm_min = rem / SECS_PER_MIN; + tval->tm_sec = rem % SECS_PER_MIN; + tval->tm_wday = (4 + days) % 7; + +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) + + year = epoch + days / 365; + days -= ((year - epoch) * 365 + + LEAPS_THRU_END_OF (year - 1) + - LEAPS_THRU_END_OF (epoch - 1)); + if (days < 0) { + year -= 1; + days += 365 + is_leap(year); + } + tval->tm_year = year - 1900; + tval->tm_yday = days + 1; + + month = 0; + if (days >= 31) { + days -= 31; + month++; + if (days >= (28 + is_leap(year))) { + days -= (28 + is_leap(year)); + month++; + while (days >= days_in_mo[month]) { + days -= days_in_mo[month]; + month++; + } + } + } + tval->tm_mon = month; + tval->tm_mday = days + 1; +} + + + +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +static inline unsigned long +encodetime (unsigned int year, unsigned int mon, + unsigned int day, unsigned int hour, + unsigned int min, unsigned int sec) +{ + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return (((( + (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec) ; /* finally seconds */ +} + + + + + +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int rtsr = rtcregs->u.stat; + + /* Clear Interrupts */ + rtcregs->u.eoi = 1; + + if (rtsr) { + rtc_irq_data |= RTC_AF; + } + rtc_irq_data += 0x100; + + /* wake up waiting process */ + wake_up_interruptible(&rtc_wait); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); +} + + +static int rtc_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit (1, &rtc_status)) + return -EBUSY; + rtc_irq_data = 0; + return 0; +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + spin_lock_irq (&rtc_lock); + rtcregs->u.eoi = 1; + spin_unlock_irq (&rtc_lock); + rtc_status = 0; + return 0; +} + +static int rtc_fasync (int fd, struct file *filp, int on) +{ + return fasync_helper (fd, filp, on, &rtc_async_queue); +} + +static unsigned int rtc_poll(struct file *file, poll_table *wait) +{ + poll_wait (file, &rtc_wait, wait); + return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM; +} + +static loff_t rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&rtc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq (&rtc_lock); + data = rtc_irq_data; + if (data != 0) { + rtc_irq_data = 0; + break; + } + spin_unlock_irq (&rtc_lock); + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + + spin_unlock_irq (&rtc_lock); + + data -= 0x100; /* the first IRQ wasn't actually missed */ + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&rtc_wait, &wait); + return retval; +} + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct rtc_time tm, tm2; + + switch (cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&rtc_lock); + rtcregs->u.stat = 0; + rtcregs->cr = ~RTCR_MIE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&rtc_lock); + rtcregs->u.stat = 0; + rtcregs->cr = RTCR_MIE; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + case RTC_UIE_OFF: + case RTC_UIE_ON: + case RTC_PIE_OFF: + case RTC_PIE_ON: + return -EINVAL; + + case RTC_ALM_READ: + decodetime (rtcregs->mr, &tm); + break; + case RTC_ALM_SET: + if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2))) + return -EFAULT; + decodetime (rtcregs->dr, &tm); + if ((unsigned)tm2.tm_hour < 24) + tm.tm_hour = tm2.tm_hour; + if ((unsigned)tm2.tm_min < 60) + tm.tm_min = tm2.tm_min; + if ((unsigned)tm2.tm_sec < 60) + tm.tm_sec = tm2.tm_sec; + rtcregs->mr = encodetime ( tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return 0; + case RTC_RD_TIME: + decodetime (rtcregs->dr, &tm); + break; + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm))) + return -EFAULT; + tm.tm_year += 1900; + if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 || + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] + + (tm.tm_mon == 1 && is_leap(tm.tm_year))) || + (unsigned)tm.tm_hour >= 24 || + (unsigned)tm.tm_min >= 60 || + (unsigned)tm.tm_sec >= 60) + return -EINVAL; + rtcregs->clr = encodetime ( tm.tm_year, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return 0; + case RTC_IRQP_READ: + case RTC_IRQP_SET: + return -EINVAL; + case RTC_EPOCH_READ: + return put_user (epoch, (unsigned long *)arg); + default: + return -EINVAL; + } + return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0; +} + +static struct file_operations rtc_fops = { + owner: THIS_MODULE, + llseek: rtc_llseek, + read: rtc_read, + poll: rtc_poll, + ioctl: rtc_ioctl, + open: rtc_open, + release: rtc_release, + fasync: rtc_fasync, +}; + +static struct miscdevice lh7a400rtc_miscdev = { + RTC_MINOR, + "lh7a400rtc", + &rtc_fops +}; + +static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + char *p = page; + int len; + struct rtc_time tm; + + decodetime (rtcregs->dr, &tm); + p += sprintf(p, "dr\t\t: %d\n" + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04d\n", + rtcregs->dr, + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + decodetime (rtcregs->mr, &tm); + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n" + "alrm_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + p += sprintf(p, "update_IRQ\t: %s\n", (rtcregs->u.stat) ? "yes" : "no"); + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + +static int __init rtc_init(void) +{ + int ret; + + misc_register (&lh7a400rtc_miscdev); + create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL); + ret = request_irq (IRQ_RTC, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL); + if (ret) { + printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC); + goto IRQ_RTC_failed; + } + + printk (KERN_INFO "LH7A400 Real Time Clock driver v" DRIVER_VERSION "\n"); + + + /* Clear Interrupts */ + rtcregs->u.eoi = 1; + + + return 0; + +IRQ_RTC_failed: + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&lh7a400rtc_miscdev); + return ret; +} + +static void __exit rtc_exit(void) +{ + free_irq (IRQ_RTC, NULL); + remove_proc_entry ("driver/rtc", NULL); + misc_deregister (&lh7a400rtc_miscdev); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +MODULE_AUTHOR("Craig Matsuura "); +MODULE_DESCRIPTION("Sharp LH7A400 Realtime Clock Driver (RTC)"); +EXPORT_NO_SYMBOLS; diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7a400_rtc.h linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_rtc.h --- linux-2.4.21-rmk1/drivers/char/lh7a400_rtc.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7a400_rtc.h Thu Oct 16 15:17:24 2003 @@ -0,0 +1,61 @@ +/* + * linux/drivers/char/dc2dc.h + * + * Copyright (C) 2002 Embedix. + * + * Original code write was authored by Craig Matsuura + * Parts of this code are from Sharp. + * This code falls under the license of the GPL. + * + * This modules is for the RTC. + */ +#ifndef __LH7A400_RTC_H +#define __LH7A400_RTC_H + +/********************************************************************** + * Real Time Clock Module Register Structure + *********************************************************************/ +typedef volatile struct { + volatile unsigned int dr; /* Data */ + volatile unsigned int clr; /* Counter Load */ + volatile unsigned int mr; /* Match */ + volatile unsigned int reserved; + volatile union { + volatile unsigned int stat; /* Interrupt Status */ + volatile unsigned int eoi; /* Interrupt Clear */ + } u; + volatile unsigned int cr; /* Control */ +} rtcRegs_t; + +//extern rtcRegs_t *rtcregs; + + +/******************************************************************** + * Global Macros + *******************************************************************/ + +/* _BIT(n) sets the bit at position "n" + * _BIT(n) is intended to be used in "OR" and "AND" expressions: + * e.g., "(_BIT(3) | _BIT(7))". + */ +#undef _BIT +#define _BIT(n) (((unsigned int)(1)) << (n)) + +/********************************************************************** + * Real Time Clock Register Bit Fields + *********************************************************************/ + +/********************************************************************** + * RTC Status Register (rtcstat) Bit Fields + *********************************************************************/ +#define RTC_STAT_RTCINTR _BIT(0) + +/********************************************************************** + * RTC Control Register (cr) Bit Fields + *********************************************************************/ +#define RTC_CR_MIE _BIT(0) + +// IOCTL's +// See linux/rtc.h + +#endif diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7x-keyb.c linux-2.4.21-rmk1-lh7a400/drivers/char/lh7x-keyb.c --- linux-2.4.21-rmk1/drivers/char/lh7x-keyb.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7x-keyb.c Sun Feb 8 20:24:19 2004 @@ -0,0 +1,779 @@ +/* vi: set sw=4 ts=4 ai: */ + +/********************************************************************** +* drivers/char/lh7x-keyb.c +* +* Sharp LH7x EVB keyboard/button driver +* +* Based very loosely on: +* IDR keyboard/button driver, (C) 2002 Ross Wille +* Based on: +* Shannon IR keyboard driver, (C) 2001 Russ Dill +* +* Copyright (C) 2002 Lineo, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) 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 "lh7x-keyb.h" + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "lh7x-keyb" +#define LONG_DRVNAME "Sharp LH7x EVB Keyboard/Button driver" + +#include +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif /* MODULE */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PRESSED 1 +#define RELEASED 0 + +/********************************************************************** +**********************************************************************/ + +static cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; +static gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); + +/********************************************************************** +**********************************************************************/ + + +/* +* WARNING: I recommend leaving IRQ_TRIGGERED_READS undefined. +* Not all of the Buttons cause dependable interrupts. +* On my board, buttons 10-14 worked good, but the others did not. +*/ +#undef IRQ_TRIGGERED_READS + +#define DEBOUNCE_BUTTONS +#define DEBOUNCE_BUTTON_USEC 3 + +#undef DEBOUNCE_KEYS +#define DEBOUNCE_KEY_USEC 3 + +typedef struct lh7x_btn_and_key_context lh7x_btn_and_key_context; +struct lh7x_btn_and_key_context { +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + uint16_t pbSwitchState; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + uint16_t keyRow[N_KEY_COLUMNS]; +#endif /* CONFIG_KEV7X_KEYBOARD_DRIVER */ +}; + +typedef struct lh7x_kbd_context lh7x_kbd_context; +struct lh7x_kbd_context { + struct input_dev dev; + char name[128]; + int irq; + int open, open_failed; + spinlock_t hardware_lock; + int cleanup_flag; + unsigned int last_scan; + unsigned int last_scan_was_bogus; +#if defined(IRQ_TRIGGERED_READS) + int read_btns_and_keys; +#endif /* IRQ_TRIGGERED_READS */ + lh7x_btn_and_key_context bk_context; + lh7x_btn_and_key_context bk_context_last; +}; +static lh7x_kbd_context *global_kbd_context = NULL; + +/********************************************************************** +**********************************************************************/ + +static void lh7x_timer_irq_handler(void *data); +static DECLARE_WAIT_QUEUE_HEAD(cleanup_wait_queue); + +#if defined(IRQ_TRIGGERED_READS) +static void lh7x_btn_and_key_irq_handler(int irq, void *_kbd_context, + struct pt_regs *regs); +static int lh7x_init_irq(struct lh7x_kbd_context *kbd_context); +#endif /* IRQ_TRIGGERED_READS */ + +/********************************************************************** +**********************************************************************/ + +//static unsigned int last_btn_state = 0; + +static struct tq_struct lh7x_btn_task = { + routine: lh7x_timer_irq_handler, + data: NULL +}; + +#ifdef DEBUG +//static char btn_chars[] = "x^VP+-RpfrM"; +#endif /* DEBUG */ + +#define SCAN_BREAK 0xf0 + +/********************************************************************** +**********************************************************************/ + +#ifdef CONFIG_MAGIC_SYSRQ +static unsigned char lh7x_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +/* +* Translation of escaped scancodes to keycodes. +* This is now user-settable. +* The keycodes 1-88,96-111,119 are fairly standard, and +* should probably not be changed - changing might confuse X. +* X also interprets scancode 0x5d (KEY_Begin). +* +* For 1-88 keycode equals scancode. +*/ + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 + +#define E1_PAUSE 119 + +/* +* New microsoft keyboard is rumoured to have +* e0 5b (left window button), e0 5c (right window button), +* e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] +* [or: Windows_L, Windows_R, TaskMan] +*/ +#define E0_MSLW 125 + +static unsigned char e0_keys[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, 0, E0_RCTRL, 0, 0, /* 0x18-0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, 0, 0, E0_PRSCR, /* 0x30-0x37 */ + E0_RALT, 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f */ + 0, 0, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ + E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, 0, E0_END, /* 0x48-0x4f */ + E0_DOWN, E0_PGDN, 0, 0, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, E0_MSLW, 0, 0, 0, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +#define vdprintk if (0) printk +#define dprintk if (0) printk + +static int lh7x_setkeycode(unsigned int scancode, unsigned int keycode) +{ + int sts = 0; + + vdprintk("ENTER: lh7x_setkeycode(s=0x%02X,k=0x%02X)\n", scancode, keycode); + if (scancode > 255 || keycode > 127) { + sts = -EINVAL; + } else { + e0_keys[scancode - 128] = keycode; + } + + return(sts); +} + +static int lh7x_getkeycode(unsigned int scancode) +{ + int keycode; + + vdprintk("ENTER: lh7x_getkeycode(s=0x%02X)\n", scancode); + keycode = scancode > 255 ? -EINVAL : e0_keys[scancode - 128]; + + return(keycode); +} + +/* #define KBD_REPORT_UNKN */ +static int lh7x_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + static int prev_scancode; + + vdprintk("ENTER: lh7x_translate(s=0x%02X,r=%d)\n", scancode, raw_mode); + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + + if (prev_scancode) { + /* + * usually it will be 0xe0, but a Pause key generates + * e1 1d 45 e1 9d c5 when pressed, and nothing when released + */ + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } else if (prev_scancode == 0x100 && scancode == 0x45) { + *keycode = E1_PAUSE; + prev_scancode = 0; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); +#endif + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + + if (e0_keys[scancode]) { + *keycode = e0_keys[scancode]; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) { + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); + } +#endif + return 0; + } + } + } else { + *keycode = scancode; + } + vdprintk("LEAVE: lh7x_translate(k=0x%02X)\n", *keycode); + + return 1; +} + +static char lh7x_unexpected_up(unsigned char keycode) +{ + vdprintk("ENTER: lh7x_unexpected_up(k=0x%02X)\n", keycode); + return(0200); +} + +/********************************************************************** +* Function: lh7x_read_btn_and_key_hardware() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static void lh7x_read_btn_and_key_hardware(lh7x_btn_and_key_context *bk_context) +{ +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + uint16_t button_state_1; +#if defined(DEBOUNCE_BUTTONS) + uint16_t button_state_2; +#endif /* DEBOUNCE_BUTTONS */ +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + int col; + uint16_t key_state_1; +#if defined(DEBOUNCE_KEYS) + uint16_t key_state_2; +#endif /* DEBOUNCE_KEYS */ +#endif /* LH7X_KEYBARD_DRIVER */ + +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + /* Read the buttons */ + /* while doing a little switch debounce dance */ + /* NOTE: Buttons are considered active with a value of 1 */ + button_state_1 = cpld->pbSwitchState & LH7X_BUTTON_MASK; +#if defined(DEBOUNCE_BUTTONS) + do { + button_state_2 = button_state_1; + udelay(DEBOUNCE_BUTTON_USEC); + button_state_1 = cpld->pbSwitchState & LH7X_BUTTON_MASK; + } while (button_state_1 != button_state_2); +#endif /* DEBOUNCE_BUTTONS */ + bk_context->pbSwitchState = button_state_1; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + /* Read the keyboard */ + for (col = 0; col < N_KEY_COLUMNS; col++) { + /* Enable the col we want to read */ + gpio->kscan = 1 << col; + /* Read the col we just setup for (row values) */ + /* while doing a little switch debounce dance */ + /* NOTE: Keys are considered active with a value of 0 */ + /* SO - we invert the values */ + // JMG - key_state_1 = (~(cpld->u2.kpdRowSense)) & LH7X_KEY_MASK; + key_state_1 = cpld->u2.kpdRowSense & LH7X_KEY_MASK; +#if defined(DEBOUNCE_KEYS) + do { + key_state_2 = key_state_1; + udelay(DEBOUNCE_KEY_USEC); + // JMG - key_state_1 = (~(cpld->u2.kpdRowSense)) & LH7X_KEY_MASK; + key_state_1 = cpld->u2.kpdRowSense & LH7X_KEY_MASK; + } while (key_state_1 != key_state_2); +#endif /* DEBOUNCE_KEYS */ + bk_context->keyRow[col] = key_state_1; + } +#endif /* LH7X_KEYBARD_DRIVER */ + + return; +} /* lh7x_read_btn_and_key_hardware() */ + +#if defined(IRQ_TRIGGERED_READS) +/********************************************************************** +* Function: enable_lh7x_btn_and_key_irq() +**********************************************************************/ +static void enable_lh7x_btn_and_key_irq(void) +{ +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + /* Enable the button IRQ causing events */ + cpld->u2.pbIntMask = LH7X_BUTTON_MASK; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + /* Enable the keyboard IRQ causing events */ + /* ? HOW ? */ +#endif /* CONFIG_KEV7X_KEYBOARD_DRIVER */ + + return; +} /* enable_lh7x_btn_and_key_irq() */ +#endif /* IRQ_TRIGGERED_READS */ + +#if defined(IRQ_TRIGGERED_READS) +/********************************************************************** +* Function: disable_lh7x_btn_and_key_irq() +**********************************************************************/ +static void disable_lh7x_btn_and_key_irq(void) +{ +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + /* Disable the button IRQ causing events */ + cpld->u2.pbIntMask = 0; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + /* Disable the keyboard IRQ causing events */ + /* ? HOW ? */ +#endif /* CONFIG_KEV7X_KEYBOARD_DRIVER */ + + return; +} /* enable_lh7x_btn_and_key_irq() */ +#endif /* IRQ_TRIGGERED_READS */ + +#if defined(IRQ_TRIGGERED_READS) +/********************************************************************** +* Function: lh7x_btn_and_key_irq_handler() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static void lh7x_btn_and_key_irq_handler(int irq, void *_kbd_context, + struct pt_regs *regs) +{ + lh7x_kbd_context *kbd_context = (struct lh7x_kbd_context *)_kbd_context; + + // Too noisy --- vdprintk("ENTER: lh7x_btn_and_key_irq_handler()\n"); + + /* + * NOTE: Processing of keys and buttons will be started when the + * "read_btns_and_keys" variable goes to non-zero. It will be + * halted when it goes to zero. + */ + /* Check if this is a button generated interrupt */ + if (cpld->pbSwitchState & LH7X_BUTTON_MASK) { + disable_lh7x_btn_and_key_irq(); + kbd_context->read_btns_and_keys = 1; + } + + // Too noisy --- vdprintk("LEAVE: lh7x_btn_and_key_irq_handler()\n"); + + return; +} /* lh7x_btn_and_key_irq_handler() */ +#endif /* IRQ_TRIGGERED_READS */ + +/********************************************************************** +* Function: lh7x_timer_irq_handler() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static void lh7x_timer_irq_handler(void *data) +{ + struct lh7x_kbd_context *kbd_context = (struct lh7x_kbd_context *)data; +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) || defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + int lst, cur; + int lst_b, cur_b; + int bit; + int bit_index; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER || CONFIG_KEV7X_KEYBOARD_DRIVER */ +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + int col; +#endif /* LH7X_KEYBARD_DRIVER */ + + // Too noisy // vdprintk("ENTER: lh7x_timer_irq_handler()\n"); + +#if defined(IRQ_TRIGGERED_READS) + if ( ! kbd_context->read_btns_and_keys) { + goto exit_timer_irq_handler; + } +#endif /* IRQ_TRIGGERED_READS */ + + /* Read the keys and buttons */ + /* NOTE: This function attempts to do debouncing */ + lh7x_read_btn_and_key_hardware(&kbd_context->bk_context); + +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + lst = kbd_context->bk_context_last.pbSwitchState; + cur = kbd_context->bk_context.pbSwitchState; + if (((cur != 0) || (lst != 0)) && (cur != lst)) { + vdprintk("BTN: LST:0x%04X, CUR:0x%04X\n", lst, cur); + /* We have detected button activity */ + /* Determine down/up actions */ + /* by walking through all the buttons individually */ + bit_index = 0; + for (bit = 1; bit & LH7X_BUTTON_MASK; bit <<= 1) { + uint16_t btn; + btn = lh7x_button_table[bit_index]; + bit_index++; + if (btn != KEY_RESERVED) { + lst_b = lst & bit; + cur_b = cur & bit; + if (lst_b != cur_b) { + if (lst_b) { + /* Button was released */ + dprintk("BTN: RELEASED: 0x%02X\n", bit); + input_report_key(&kbd_context->dev, btn, RELEASED); + } else { + /* Button was pressed */ + dprintk("BTN: PRESSED: 0x%02X\n", bit); + input_report_key(&kbd_context->dev, btn, PRESSED); + } + } + } + } + kbd_context->bk_context_last.pbSwitchState = cur; + } +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + for (col = 0; col < N_KEY_COLUMNS; col++) { + lst = kbd_context->bk_context_last.keyRow[col]; + cur = kbd_context->bk_context.keyRow[col]; + if (((cur != 0) || (lst != 0)) && (cur != lst)) { + vdprintk("KEY: col:%d, LST:0x%04X, CUR:0x%04X\n", col, lst, cur); + /* We have detected keyboard activity */ + /* Determine down/up actions */ + /* by walking through all the keys individually */ + bit_index = 0; + for (bit = 1; bit & LH7X_KEY_MASK; bit <<= 1) { + uint16_t key; + key = lh7x_key_table[col][bit_index]; + bit_index++; + if (key != KEY_RESERVED) { + lst_b = lst & bit; + cur_b = cur & bit; + if (lst_b != cur_b) { + if (lst_b) { + /* Key was released */ + dprintk("KEY: RELEASED: %d:0x%04X\n", col, bit); + input_report_key(&kbd_context->dev, key, RELEASED); + } else { + /* Key was pressed */ + dprintk("KEY: PRESSED: %d:0x%04X\n", col, bit); + input_report_key(&kbd_context->dev, key, PRESSED); + } + } + } + } + kbd_context->bk_context_last.keyRow[col] = cur; + } + } +#endif /* LH7X_KEYBARD_DRIVER */ + +#if defined(IRQ_TRIGGERED_READS) + /* + * NOTE: Processing of keys and buttons will be halted when the + * "read_btns_and_keys" variable goes to zero. It will be + * restarted when a button or key event (interrupt) occurs. + */ + kbd_context->read_btns_and_keys = 0; +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + kbd_context->read_btns_and_keys += + kbd_context->bk_context_last.pbSwitchState + + kbd_context->bk_context.pbSwitchState; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + for (col = 0; col < N_KEY_COLUMNS; col++) { + kbd_context->read_btns_and_keys += + kbd_context->bk_context_last.keyRow[col] + + kbd_context->bk_context.keyRow[col]; + } +#endif /* LH7X_KEYBARD_DRIVER */ + + if ( ! kbd_context->read_btns_and_keys) { + enable_lh7x_btn_and_key_irq(); + } +#endif /* IRQ_TRIGGERED_READS */ + +exit_timer_irq_handler: + + // If cleanup wants us to die + if (kbd_context->cleanup_flag) { + wake_up(&cleanup_wait_queue); // now cleanup_module can return + } + else { + queue_task(&lh7x_btn_task, &tq_timer); // put us back in the task queue + } + + // too noisy // vdprintk("LEAVE: lh7x_timer_irq_handler()\n"); + + return; +} /* lh7x_timer_irq_handler() */ + +#if defined(IRQ_TRIGGERED_READS) +/********************************************************************** +* Function: lh7x_init_irq() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static int lh7x_init_irq(struct lh7x_kbd_context *kbd_context) +{ + int retval = 0; + + vdprintk("ENTER: lh7x_init_irq()\n"); + + kbd_context->irq = IRQ_CPLD; + retval = request_irq(kbd_context->irq, lh7x_btn_and_key_irq_handler, + SA_SHIRQ | SA_SAMPLE_RANDOM, DRVNAME, kbd_context); + if (retval < 0) { + printk(KERN_ERR "IRQ %d already in use.\n", kbd_context->irq); + return retval; + } + +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + /* Enable the button IRQ causing events */ + enable_lh7x_btn_and_key_irq(); +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + + vdprintk("LEAVE: lh7x_init_irq()\n"); + + return 0; +} /* lh7x_init_irq() */ +#endif /* IRQ_TRIGGERED_READS */ + +/********************************************************************** +* Function: lh7x_kbd_open() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static int lh7x_kbd_open(struct input_dev *dev) +{ + struct lh7x_kbd_context *kbd_context = dev->private; + + vdprintk("ENTER: lh7x_kbd_open()\n"); + + if (kbd_context->open++) return 0; + +#if defined(IRQ_TRIGGERED_READS) + { + int retval; + + retval = lh7x_init_irq(kbd_context); + if (retval < 0) { + kbd_context->open_failed = 1; + return retval; + } + + enable_irq(kbd_context->irq); + } +#endif /* IRQ_TRIGGERED_READS */ + + lh7x_btn_task.data = kbd_context; + queue_task(&lh7x_btn_task, &tq_timer); + + vdprintk("LEAVE: lh7x_kbd_open()\n"); + + return 0; +} /* lh7x_kbd_open() */ + +/********************************************************************** +* Function: lh7x_kbd_close() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static void lh7x_kbd_close(struct input_dev *dev) +{ + struct lh7x_kbd_context *kbd_context = dev->private; + int flags; + + vdprintk("ENTER: lh7x_kbd_close()\n"); + + if ( ! --kbd_context->open && ! kbd_context->open_failed ) { + spin_lock_irqsave(&kbd_context->hardware_lock, flags); + + disable_irq(kbd_context->irq); + free_irq(kbd_context->irq, kbd_context); + + spin_unlock_irqrestore(&kbd_context->hardware_lock, flags); + + kbd_context->cleanup_flag = 1; + sleep_on(&cleanup_wait_queue); + } + + vdprintk("LEAVE: lh7x_kbd_close()\n"); + + return; +} /* lh7x_kbd_close() */ + +/********************************************************************** +* Function: lh7x_kbd_init() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static int __init lh7x_kbd_init(void) +{ + struct lh7x_kbd_context *kbd_context; +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) || defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + int row; +#endif /* CONFIG_KEV7X_BUTTON_DRIVER || CONFIG_KEV7X_KEYBOARD_DRIVER */ +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + int col; +#endif /* LH7X_KEYBARD_DRIVER */ + + vdprintk("ENTER: lh7x_kbd_init()\n"); + + global_kbd_context = kmalloc(sizeof(struct lh7x_kbd_context), GFP_KERNEL); + kbd_context = global_kbd_context; + if ( ! kbd_context) return -ENOMEM; + + /* Initialize the keyboard and button/key context structure(s) */ + memset(kbd_context, 0, sizeof(struct lh7x_kbd_context)); + + // kbd_context->cleanup_flag = 0; // Done above + kbd_context->hardware_lock = SPIN_LOCK_UNLOCKED; + strcpy(kbd_context->name, LONG_DRVNAME); + kbd_context->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + kbd_context->dev.private = kbd_context; + kbd_context->dev.open = lh7x_kbd_open; + kbd_context->dev.close = lh7x_kbd_close; + kbd_context->dev.name = kbd_context->name; + kbd_context->dev.idbus = BUS_RS232; /* JMG --- ??? */ + + k_setkeycode = lh7x_setkeycode; + k_getkeycode = lh7x_getkeycode; + k_translate = lh7x_translate; + k_unexpected_up = lh7x_unexpected_up; +#ifdef CONFIG_MAGIC_SYSRQ + k_sysrq_key = 0x54; + k_sysrq_xlate = lh7x_sysrq_xlate; +#endif /* CONFIG_MAGIC_SYSRQ */ + + input_register_device(&kbd_context->dev); + +#if defined(CONFIG_KEV7X_BUTTON_DRIVER) + /* Make the buttons we are dealing with active in the kernel */ + for (row = 0; row < N_BUTTON_ROWS; row++) { + if (lh7x_button_table[row] != KEY_RESERVED) { + set_bit(lh7x_button_table[row], kbd_context->dev.keybit); + } + } +#endif /* CONFIG_KEV7X_BUTTON_DRIVER */ + +#if defined(CONFIG_KEV7X_KEYBOARD_DRIVER) + /* Make the keys we are dealing with active in the kernel */ + for (col = 0; col < N_KEY_COLUMNS; col++) { + for (row = 0; row < N_KEY_ROWS; row++) { + if (lh7x_key_table[col][row] != KEY_RESERVED) { + set_bit(lh7x_key_table[col][row], kbd_context->dev.keybit); + } + } + } +#endif /* LH7X_KEYBARD_DRIVER */ + + printk(KERN_INFO "%s installed\n", LONG_DRVNAME); + + vdprintk("LEAVE: lh7x_kbd_init()\n"); + + return 0; +} /* lh7x_kbd_init() */ + +/********************************************************************** +* Function: lh7x_kbd_exit() +* +* Purpose: +* FUNCTION_DESCRIPTION +**********************************************************************/ +static void __exit lh7x_kbd_exit(void) +{ + vdprintk("ENTER: lh7x_kbd_exit()\n"); + + global_kbd_context->cleanup_flag = 1; + + sleep_on(&cleanup_wait_queue); + + input_unregister_device(&global_kbd_context->dev); + + kfree(global_kbd_context); + + printk(KERN_INFO "%s unloaded\n", LONG_DRVNAME); + + vdprintk("LEAVE: lh7x_kbd_exit()\n"); + + return; +} /* lh7x_kbd_exit() */ + +module_init(lh7x_kbd_init); +module_exit(lh7x_kbd_exit); + +MODULE_AUTHOR("Jim Gleason / Lineo, Inc."); +MODULE_DESCRIPTION(LONG_DRVNAME); +MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/char/lh7x-keyb.h linux-2.4.21-rmk1-lh7a400/drivers/char/lh7x-keyb.h --- linux-2.4.21-rmk1/drivers/char/lh7x-keyb.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/char/lh7x-keyb.h Thu Oct 16 15:14:45 2003 @@ -0,0 +1,375 @@ +/* vi: set sw=4 ts=4 ai: */ + +/********************************************************************** +* drivers/char/lh7x-keyb.h +* +* Sharp LH7x EVB keyboard/buttons driver +* +* Copyright (C) 2002 Lineo, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) version 2 +* as published by the Free Software Foundation. +* +* Based on LH7A400_evb_keyboard_driver.h +* COPYRIGHT (C) 2002 SHARP MICROELECTRONICS OF THE AMERICAS, INC. +* CAMAS, WA +* +**********************************************************************/ + +#ifndef LH7X_KEYB_H +#define LH7X_KEYB_H + + +#define LH7X_BTN_10 _BIT(0) +#define LH7X_BTN_11 _BIT(1) +#define LH7X_BTN_12 _BIT(2) +#define LH7X_BTN_13 _BIT(3) +#define LH7X_BTN_14 _BIT(4) +#define LH7X_BTN_15 _BIT(5) +#define LH7X_BTN_16 _BIT(6) +#define LH7X_BTN_17 _BIT(7) + +#define N_BUTTON_ROWS 8 +#define LH7X_BUTTON_MASK 0xFF + +static uint16_t lh7x_button_table[N_BUTTON_ROWS] = +{ + KEY_F1, /* bit 0 --- LH7X_BTN_10 */ + KEY_F2, /* bit 1 --- LH7X_BTN_11 */ + KEY_F3, /* bit 2 --- LH7X_BTN_12 */ + KEY_F4, /* bit 3 --- LH7X_BTN_13 */ + KEY_F5, /* bit 4 --- LH7X_BTN_14 */ + KEY_F6, /* bit 5 --- LH7X_BTN_15 */ + KEY_F7, /* bit 6 --- LH7X_BTN_16 */ + KEY_F8 /* bit 7 --- LH7X_BTN_17 */ +}; + + +#define N_KEY_ROWS 16 +#define LH7X_KEY_MASK 0xFFFF + +/*****************************/ +/* control key row positions */ +/*****************************/ + +/* column 0 */ +#define KB_ALT_KEY _BIT(0) +#define KB_CTRL_KEY _BIT(3) +#define KB_FN_KEY _BIT(4) + +/* column 1 */ +#define KB_LEFT_SHIFT_KEY _BIT(2) +#define KB_RIGHT_SHIFT_KEY _BIT(12) + +/*********************/ +/* key row positions */ +/*********************/ + +/* column 0 */ +#define KB_GRAVE_KEY _BIT(1) +#define KB_ESC_KEY _BIT(5) +#define KB_ONE_KEY _BIT(6) +#define KB_TWO_KEY _BIT(7) +#define KB_NINE_KEY _BIT(8) +#define KB_ZERO_KEY _BIT(9) +#define KB_MINUS_KEY _BIT(10) +#define KB_EQUALS_KEY _BIT(11) +#define KB_BACKSPACE_KEY _BIT(13) + +/* Account for column 0 control key row positions also */ +static uint16_t lh7x_key_row_0[N_KEY_ROWS] = +{ + KEY_LEFTALT, /* bit 0 --- KB_ALT_KEY */ + KEY_GRAVE, /* bit 1 --- KB_GRAVE_KEY */ + KEY_RESERVED, /* bit 2 --- */ + KEY_LEFTCTRL, /* bit 3 --- KB_CTRL_KEY */ + KEY_LEFTMETA, /* bit 4 --- KB_FN_KEY */ /* JMG ? */ + KEY_ESC, /* bit 5 --- KB_ESC_KEY */ + KEY_1, /* bit 6 --- KB_ONE_KEY */ + KEY_2, /* bit 7 --- KB_TWO_KEY */ + KEY_9, /* bit 8 --- KB_NINE_KEY */ + KEY_0, /* bit 9 --- KB_ZERO_KEY */ + KEY_MINUS, /* bit 10 -- KB_MINUS_KEY */ + KEY_EQUAL, /* bit 11 -- KB_EQUALS_KEY */ + KEY_RESERVED, /* bit 12 -- */ + KEY_BACKSPACE, /* bit 13 -- KB_BACKSPACE_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/* column 1 */ +#define KB_BACKSLASH_KEY _BIT(1) +#define KB_DEL_KEY _BIT(5) +#define KB_T_KEY _BIT(7) +#define KB_Y_KEY _BIT(8) +#define KB_U_KEY _BIT(9) +#define KB_I_KEY _BIT(10) +#define KB_ENTER_KEY _BIT(11) +#define KB_DOWN_KEY _BIT(13) + +/* Account for column 1 control key row positions also */ +static uint16_t lh7x_key_row_1[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_BACKSLASH, /* bit 1 --- KB_BACKSLASH_KEY */ + KEY_LEFTSHIFT, /* bit 2 --- KB_LEFT_SHIFT_KEY */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_DELETE, /* bit 5 --- KB_DEL_KEY */ + KEY_RESERVED, /* bit 6 --- */ + KEY_T, /* bit 7 --- KB_T_KEY */ + KEY_Y, /* bit 8 --- KB_Y_KEY */ + KEY_U, /* bit 9 --- KB_U_KEY */ + KEY_I, /* bit 10 -- KB_I_KEY */ + KEY_ENTER, /* bit 11 -- KB_ENTER_KEY */ + KEY_RIGHTSHIFT, /* bit 12 -- KB_RIGHT_SHIFT_KEY */ + KEY_DOWN, /* bit 13 -- KB_DOWN_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/* column 2 */ +#define KB_TAB_KEY _BIT(1) +#define KB_Q_KEY _BIT(5) +#define KB_W_KEY _BIT(6) +#define KB_E_KEY _BIT(7) +#define KB_R_KEY _BIT(8) +#define KB_O_KEY _BIT(9) +#define KB_P_KEY _BIT(10) +#define KB_LBRACKET_KEY _BIT(11) +#define KB_RBRACKET_KEY _BIT(13) + +static uint16_t lh7x_key_row_2[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_TAB, /* bit 1 --- KB_TAB_KEY */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_Q, /* bit 5 --- KB_Q_KEY */ + KEY_W, /* bit 6 --- KB_W_KEY */ + KEY_E, /* bit 7 --- KB_E_KEY */ + KEY_R, /* bit 8 --- KB_R_KEY */ + KEY_O, /* bit 9 --- KB_O_KEY */ + KEY_P, /* bit 10 -- KB_P_KEY */ + KEY_LEFTBRACE, /* bit 11 -- KB_LBRACKET_KEY */ /* JMG ? */ + KEY_RESERVED, /* bit 12 -- */ + KEY_RIGHTBRACE, /* bit 13 -- KB_RBRACKET_KEY */ /* JMG ? */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/*column 3 */ +#define KB_Z_KEY _BIT(1) +#define KB_CAPS_LOCK_KEY _BIT(5) +#define KB_K_KEY _BIT(8) +#define KB_L_KEY _BIT(9) +#define KB_SEMICOLON_KEY _BIT(10) +#define KB_APOSTROPHE_KEY _BIT(11) +#define KB_UP_KEY _BIT(13) + +static uint16_t lh7x_key_row_3[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_Z, /* bit 1 --- KB_Z_KEY */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_CAPSLOCK, /* bit 5 --- KB_CAPS_LOCK_KEY */ + KEY_RESERVED, /* bit 6 --- */ + KEY_RESERVED, /* bit 7 --- */ + KEY_K, /* bit 8 --- KB_K_KEY */ + KEY_L, /* bit 9 --- KB_L_KEY */ + KEY_SEMICOLON, /* bit 10 -- KB_SEMICOLON_KEY */ + KEY_APOSTROPHE, /* bit 11 -- KB_APOSTROPHE_KEY */ + KEY_RESERVED, /* bit 12 -- */ + KEY_UP, /* bit 13 -- KB_UP_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/* column 4 */ +#define KB_A_KEY _BIT(1) +#define KB_S_KEY _BIT(5) +#define KB_D_KEY _BIT(6) +#define KB_F_KEY _BIT(7) +#define KB_G_KEY _BIT(8) +#define KB_H_KEY _BIT(9) +#define KB_J_KEY _BIT(10) +#define KB_SLASH_KEY _BIT(11) +#define KB_LEFT_KEY _BIT(13) + +static uint16_t lh7x_key_row_4[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_A, /* bit 1 --- KB_A_KEY */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_S, /* bit 5 --- KB_S_KEY */ + KEY_D, /* bit 6 --- KB_D_KEY */ + KEY_F, /* bit 7 --- KB_F_KEY */ + KEY_G, /* bit 8 --- KB_G_KEY */ + KEY_H, /* bit 9 --- KB_H_KEY */ + KEY_J, /* bit 10 -- KB_J_KEY */ + KEY_SLASH, /* bit 11 -- KB_SLASH_KEY */ + KEY_RESERVED, /* bit 12 -- */ + KEY_LEFT, /* bit 13 -- KB_LEFT_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/* column 5 */ +#define KB_X_KEY _BIT(1) +#define KB_C_KEY _BIT(5) +#define KB_V_KEY _BIT(6) +#define KB_B_KEY _BIT(7) +#define KB_N_KEY _BIT(8) +#define KB_M_KEY _BIT(9) +#define KB_COMMA_KEY _BIT(10) +#define KB_PERIOD_KEY _BIT(11) +#define KB_SPACE_KEY _BIT(13) + +static uint16_t lh7x_key_row_5[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_X, /* bit 1 --- KB_X_KEY */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_C, /* bit 5 --- KB_C_KEY */ + KEY_V, /* bit 6 --- KB_V_KEY */ + KEY_B, /* bit 7 --- KB_B_KEY */ + KEY_N, /* bit 8 --- KB_N_KEY */ + KEY_M, /* bit 9 --- KB_M_KEY */ + KEY_COMMA, /* bit 10 -- KB_COMMA_KEY */ + KEY_DOT, /* bit 11 -- KB_PERIOD_KEY */ + KEY_RESERVED, /* bit 12 -- */ + KEY_SPACE, /* bit 13 -- KB_SPACE_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +/* column 6 */ +#define KB_THREE_KEY _BIT(5) +#define KB_FOUR_KEY _BIT(6) +#define KB_FIVE_KEY _BIT(7) +#define KB_SIX_KEY _BIT(8) +#define KB_SEVEN_KEY _BIT(9) +#define KB_EIGHT_KEY _BIT(10) +#define KB_PROG_KEY _BIT(11) +#define KB_RIGHT_KEY _BIT(13) + +static uint16_t lh7x_key_row_6[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_RESERVED, /* bit 1 --- */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_3, /* bit 5 --- KB_THREE_KEY */ + KEY_4, /* bit 6 --- KB_FOUR_KEY */ + KEY_5, /* bit 7 --- KB_FIVE_KEY */ + KEY_6, /* bit 8 --- KB_SIX_KEY */ + KEY_7, /* bit 9 --- KB_SEVEN_KEY */ + KEY_8, /* bit 10 -- KB_EIGHT_KEY */ + KEY_PROG1, /* bit 11 -- KB_PROG_KEY */ + KEY_RESERVED, /* bit 12 -- */ + KEY_RIGHT, /* bit 13 -- KB_RIGHT_KEY */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +static uint16_t lh7x_key_row_7[N_KEY_ROWS] = +{ + KEY_RESERVED, /* bit 0 --- */ + KEY_RESERVED, /* bit 1 --- */ + KEY_RESERVED, /* bit 2 --- */ + KEY_RESERVED, /* bit 3 --- */ + KEY_RESERVED, /* bit 4 --- */ + KEY_RESERVED, /* bit 5 --- */ + KEY_RESERVED, /* bit 6 --- */ + KEY_RESERVED, /* bit 7 --- */ + KEY_RESERVED, /* bit 8 --- */ + KEY_RESERVED, /* bit 9 --- */ + KEY_RESERVED, /* bit 10 -- */ + KEY_RESERVED, /* bit 11 -- */ + KEY_RESERVED, /* bit 12 -- */ + KEY_RESERVED, /* bit 13 -- */ + KEY_RESERVED, /* bit 14 -- */ + KEY_RESERVED /* bit 15 -- */ +}; + +#define N_KEY_COLUMNS 8 +static uint16_t *lh7x_key_table[N_KEY_COLUMNS] = +{ + lh7x_key_row_0, /* Column 0 */ + lh7x_key_row_1, /* Column 1 */ + lh7x_key_row_2, /* Column 2 */ + lh7x_key_row_3, /* Column 3 */ + lh7x_key_row_4, /* Column 4 */ + lh7x_key_row_5, /* Column 5 */ + lh7x_key_row_6, /* Column 6 */ + lh7x_key_row_7 /* Column 7 */ +}; + +#endif /* LH7X_KEYB_H */ + + + +#ifdef SHARP_STUFF_NOT_IN_USE + +/* key values (ASCII) */ +#define KB_TAB '\t' +#define KB_ESC '\x1b' +#define KB_BREAK '\x03' /* control-C */ +#define KB_BACKSPACE '\x08' +#define KB_DEL '\x7f' +#define KB_SCRLK '\x11' /* x-on */ +#define KB_ENTER '\x0d' + +/* key values (arbitrary) */ +#define KB_NUMLOCK '\x80' +#define KB_BACKTAB '\x81' +#define KB_PAUSE '\x82' +#define KB_CAPSLOCK '\x83' +#define KB_PRTSCR '\x84' +#define KB_DOWN '\x85' +#define KB_UP '\x86' +#define KB_INS '\x87' +#define KB_PAGE_UP '\x88' +#define KB_PAGE_DOWN '\x89' +#define KB_LEFT '\x8a' +#define KB_HOME '\x8b' +#define KB_RIGHT '\x8c' +#define KB_END '\x8d' +#define KB_PROG '\x8e' +#define KB_SYSREQ '\x8f' +#define KB_PF1 '\x90' +#define KB_PF2 '\x91' +#define KB_PF3 '\x92' +#define KB_PF4 '\x93' +#define KB_PF5 '\x94' +#define KB_PF6 '\x95' +#define KB_PF7 '\x96' +#define KB_PF8 '\x97' +#define KB_PF9 '\x98' +#define KB_PF10 '\x99' + +typedef union +{ + struct + { + UNS_32 c:8; + UNS_32 fn:1; + UNS_32 left_shift:1; + UNS_32 right_shift:1; + UNS_32 ctrl:1; + UNS_32 alt:1; + } decoded; + UNS_32 raw; +} KEYVAL; + +#endif /* SHARP_STUFF_NOT_IN_USE */ + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/ide/ide-disk.c linux-2.4.21-rmk1-lh7a400/drivers/ide/ide-disk.c --- linux-2.4.21-rmk1/drivers/ide/ide-disk.c Fri Jun 13 10:51:33 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/ide/ide-disk.c Sun Feb 8 17:33:59 2004 @@ -734,6 +734,9 @@ if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0) drive->wcache = 1; } +/*XXXbrad@heeltoe.com*/ +printk("idedisk_open() wcache %d\n", drive->wcache); +drive->wcache = 0; return 0; } @@ -741,6 +744,7 @@ static int ide_cacheflush_p(ide_drive_t *drive) { +printk("ide_cacheflush_p() wcache %d\n", drive->wcache); if(drive->wcache) { if (do_idedisk_flushcache(drive)) diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/ide/legacy/ide-cs.c linux-2.4.21-rmk1-lh7a400/drivers/ide/legacy/ide-cs.c --- linux-2.4.21-rmk1/drivers/ide/legacy/ide-cs.c Fri Jun 13 10:51:33 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/ide/legacy/ide-cs.c Fri Feb 6 16:27:35 2004 @@ -100,7 +100,8 @@ static int ide_event(event_t event, int priority, event_callback_args_t *args); -static dev_info_t dev_info = "ide-cs"; +//static dev_info_t dev_info = "ide-cs"; +static dev_info_t dev_info = "ide_cs"; static dev_link_t *ide_attach(void); static void ide_detach(dev_link_t *); diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/Config.in linux-2.4.21-rmk1-lh7a400/drivers/misc/Config.in --- linux-2.4.21-rmk1/drivers/misc/Config.in Thu Oct 16 10:10:09 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/Config.in Sun Feb 8 20:25:17 2004 @@ -15,3 +15,18 @@ dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200 endmenu +mainmenu_option next_comment + +comment 'Misc devices' + +if [ "$CONFIG_ARCH_LH79520" = "y" -o "$CONFIG_ARCH_LH7A400" = "y" ]; then + tristate 'Sharp LH7A400/LH79520 touchscreen support' CONFIG_KEV7X_TOUCHSCREEN + tristate 'Sharp LH7A400/LH79520 serial eeprom support' CONFIG_KEV7X_EEPROM + tristate 'Sharp LH7A400/LH70520 7-segment support' CONFIG_KEV7X_7SEGMENT +fi + +if [ "$CONFIG_ARCH_LH7A400" = "y" ]; then + tristate 'LH7A400 Smart Card Interface' CONFIG_LH7A400_SCI +fi + +endmenu diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/Makefile linux-2.4.21-rmk1-lh7a400/drivers/misc/Makefile --- linux-2.4.21-rmk1/drivers/misc/Makefile Thu Oct 16 10:10:09 2003 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/Makefile Sun Feb 8 20:25:43 2004 @@ -18,6 +18,10 @@ 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_KEV7X_TOUCHSCREEN) += ads784x.o ssp-lh7a400.o +obj-$(CONFIG_KEV7X_EEPROM) += eeprom-lh7a400.o +obj-$(CONFIG_KEV7X_7SEGMENT) += led-lh7a400.o +obj-$(CONFIG_LH7A400_SCI) += sci-lh7a400.o include $(TOPDIR)/Rules.make diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/ads784x.c linux-2.4.21-rmk1-lh7a400/drivers/misc/ads784x.c --- linux-2.4.21-rmk1/drivers/misc/ads784x.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/ads784x.c Thu Oct 16 17:15:59 2003 @@ -0,0 +1,967 @@ +/* vi: set sw=4 ts=4 ai: */ + +// #define MODULE + +#define TS_DATA_LH7X + +/********************************************************************** +* linux/drivers/misc/ads784x.c +* +* Provide ADS_784x (touchscreen) functionality for LH7x EVB boards +* +* Copyright (C) 2002 Lineo, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) version 2 +* as published by the Free Software Foundation. +* +**********************************************************************/ + +/********************************************************************** +* Algorithm: +* +* The driver sleeps when there is no pen on the screen. When a pen_down +* interrupt occurs, the pen_down interrupt handler wakes the polling thread. +* The polling thread polls the ADS chip SAMPLES_PER_SECOND. When the polling +* thread polls the ADS chip and the pen is no longer down, the polling +* thread goes to sleep and the pen_down interrupt handler is enabled. +* +* The ADS device sleeps between conversions to save power. +* +* The driver stores pen coordinates in a queue. An application can access +* the coordinate queue by opening and reading the associated device file +* (char major=10 minor=20). An application can poll the queue to see if +* it contains coordinates. If it does, the application can read a coordinate +* structure back. The coordinate queue is flushed when the application +* opens the device file. +* +**********************************************************************/ + +#include +#include +#include +#include +#include +//#include +//#include +#include +//#include +//#include +#include +#include +#include +#include + +// #define DEBUG +// #define VERBOSE +#define DRVNAME "ads_784x" + +#include +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif /* MODULE */ + +#include "ssp.h" + +#if defined(CONFIG_ADS7846) && defined(CONFIG_PROC_FS) +# define PROC_TEMPERATURE +# define PROC_BATTERY +#endif + +#ifdef PROC_BATTERY +static struct proc_dir_entry *ads_784x_proc_battery; +#endif +#ifdef PROC_TEMPERATURE +static struct proc_dir_entry *ads_784x_proc_temperature; +#endif + +/********************************************************************* +* A couple of macros we use here... +*********************************************************************/ +#ifndef _BIT +#define _BIT(n) (1 << (n)) +#endif +#ifndef _SBF +#define _SBF(f,v) ((v) << (f)) +#endif +#ifndef _BITMASK +#define _BITMASK(field_width) ( _BIT(field_width) - 1) +#endif + +/********************************************************************** +* Define ADS 784x Control byte +**********************************************************************/ + +#define CTRL_S _BIT(7) /* Start bit (REQUIRED) */ + +// #define CTRL_ADDR(n) _SBF(4,(n&0x7)) +#define CTRL_X _SBF(4,0x5) /* Read X value */ +#define CTRL_Y _SBF(4,0x1) /* Read Y value */ +#define CTRL_P1 _SBF(4,0x3) /* Read P1 value */ +#define CTRL_P2 _SBF(4,0x4) /* Read P2 value */ +#define CTRL_BATTERY _SBF(4,0x2) /* Read BATTERY value */ +#define CTRL_TEMP0 _SBF(4,0x0) /* Read Temperature-0 value */ +#define CTRL_TEMP1 _SBF(4,0x7) /* Read Temperature-1 value */ + +// #define CTRL_MODE(n) _SBF(3,(n&0x1)) +#define CTRL_12BIT _SBF(3,0x0) /* 12-Bit conversions */ +#define CTRL_8BIT _SBF(3,0x1) /* 8-Bit conversions */ + +// #define CTRL_SER_DFR(n) _SBF(2,(n&0x1)) +#define CTRL_SER _SBF(2,0x1) /* Single-Ended reference */ +#define CTRL_DFR _SBF(2,0x0) /* Differential reference */ + +// #define CTRL_PD(n) (n&0x3) +#define CTRL_PD_ZERO (0x0) /* PenIRQ enabled - PowerDown after */ +#define CTRL_PD_ONE (0x1) /* PenIRQ disabled - PowerDown after */ +#define CTRL_PD_TWO (0x2) /* PenIRQ disabled - RESERVED */ +#define CTRL_PD_THREE (0x3) /* PenIRQ disabled - Powered ON */ + +/********************************************************************** +* Define Simplified ADS 784x Control Codes +**********************************************************************/ + +//#define ADS_784x_PD 0 /* Power Down Settings */ +//#define ADS_784x_PD_INIT 0 /* Init setting reference and ADC Off */ + +#define ADS_784x_INIT \ + ( CTRL_S | CTRL_BATTERY | CTRL_12BIT | CTRL_SER | CTRL_PD_ZERO) +#define ADS_784x_READ_X \ + ( CTRL_S | CTRL_X | CTRL_12BIT | CTRL_DFR | CTRL_PD_ZERO) +#define ADS_784x_READ_Y \ + ( CTRL_S | CTRL_Y | CTRL_12BIT | CTRL_DFR | CTRL_PD_ZERO) +#define ADS_784x_READ_P1 \ + ( CTRL_S | CTRL_P1 | CTRL_12BIT | CTRL_DFR | CTRL_PD_ZERO) +#define ADS_784x_READ_P2 \ + ( CTRL_S | CTRL_P2 | CTRL_12BIT | CTRL_DFR | CTRL_PD_ZERO) +#define ADS_784x_READ_BATTERY \ + ( CTRL_S | CTRL_BATTERY | CTRL_12BIT | CTRL_SER | CTRL_PD_ZERO) +#define ADS_784x_READ_TEMP0 \ + ( CTRL_S | CTRL_TEMP0 | CTRL_12BIT | CTRL_SER | CTRL_PD_ZERO) +#define ADS_784x_READ_TEMP1 \ + ( CTRL_S | CTRL_TEMP1 | CTRL_12BIT | CTRL_SER | CTRL_PD_ZERO) + +/********************************************************************** +* Define our touchscreen data type +* +* This structure is nonsense - millisecs is not very useful +* since the field size is too small. Also, we SHOULD NOT +* be exposing jiffies to user space directly. +**********************************************************************/ +typedef struct tsData_t tsData_t; + +#ifdef TS_DATA_COLLIE +#define TS_DATA_STRUCT +#define PROVIDE_TS_MILLISECS +struct tsData_t { + long x; + long y; + long pressure; + long long millisecs; +}; +#endif + +#ifdef TS_DATA_IPAQ +#define TS_DATA_STRUCT +struct tsData_t { + unsigned short pressure; + unsigned short x; + unsigned short y; + unsigned short pad; +}; +#endif + +#ifdef TS_DATA_LH7X +#define TS_DATA_STRUCT +struct tsData_t { + uint16_t pressure; + uint16_t y; /* Will be read as X */ + uint16_t x; /* Will be read as Y */ + uint16_t pad; +}; +#endif + +#ifndef TS_DATA_STRUCT +#define TS_DATA_DEFAULT +#define PROVIDE_TS_TIMESTAMP +struct tsData_t { + uint16_t pressure; + uint16_t x; + uint16_t y; + uint16_t pad; + struct timeval stamp; +}; +#endif + +#define MAX_TS_DATA 16 + +#define X_DELTA_MAX 20 +#define Y_DELTA_MAX 30 + +/* Define the readings we are to take per second (default to 50) */ +#define SAMPLES_PER_SECOND 50 + +/* +* Define the pen down debounce we are to take. +* (default of 20 == 1/20 of a second) +*/ +#define DEBOUNCE_FRACTION_OF_A_SECOND 50 + +/********************************************************************** +* Define our ADS context structure +**********************************************************************/ +typedef struct adsContext_t adsContext_t; +struct adsContext_t { + + void *sspContext; + void (*write) (void *sspContext, unsigned int data); + unsigned int (*read) (void *sspContext); + int (*enable_pen_down_irq)(void *sspContext); + int (*disable_pen_down_irq)(void *sspContext); + int (*is_pen_down)(void *sspContext); + int (*lock)(void *sspContext, int device); + int (*unlock)(void *sspContext, int device); + + struct fasync_struct *fasync; + struct completion complete; + struct task_struct *rtask; + + wait_queue_head_t read_wait; + wait_queue_head_t irq_wait; + + int tsDataHead; + int tsDataTail; + tsData_t tsData[MAX_TS_DATA]; +}; +static adsContext_t adsContext_l; + +/********************************************************************** +* Macro: ads_784x_tsData_pending +**********************************************************************/ +#define ads_784x_tsData_pending(adsContext) \ + ((adsContext)->tsDataHead != (adsContext)->tsDataTail) + +/********************************************************************** +* Macro: ads_784x_tsData_get +**********************************************************************/ +#define ads_784x_tsData_get(adsContext) \ + ((adsContext)->tsData + (adsContext)->tsDataTail) + +/********************************************************************** +* Macro: ads_784x_tsData_pull +**********************************************************************/ +#define ads_784x_tsData_pull(adsContext) \ + ((adsContext)->tsDataTail = \ + ((adsContext)->tsDataTail + 1) & (MAX_TS_DATA - 1)) + +/********************************************************************** +* Macro: ads_784x_tsData_flush +**********************************************************************/ +#define ads_784x_tsData_flush(adsContext) \ + ((adsContext)->tsDataTail = (adsContext)->tsDataHead) + +#define vdprintk if (0) printk +#define dprintk if (0) printk + +/********************************************************************** +* Function: ads_784x_tsData_add +**********************************************************************/ +static inline void ads_784x_tsData_add( + adsContext_t *adsContext, + unsigned int pressure, + unsigned int x, + unsigned int y) +{ + int next_head; + + vdprintk("ENTER: ads_784x_tsData_add()\n"); + next_head = (adsContext->tsDataHead + 1) & (MAX_TS_DATA - 1); + if (next_head != adsContext->tsDataTail) { + adsContext->tsData[adsContext->tsDataHead].pressure = pressure; + adsContext->tsData[adsContext->tsDataHead].x = x; + adsContext->tsData[adsContext->tsDataHead].y = y; +#ifdef PROVIDE_TS_TIMESTAMP + get_fast_time(&adsContext->tsData[adsContext->tsDataHead].stamp); +#endif + adsContext->tsDataHead = next_head; + if (adsContext->fasync) + kill_fasync(&adsContext->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&adsContext->read_wait); + } + vdprintk("LEAVE: ads_784x_tsData_add()\n"); + return; +} + +/********************************************************************** +* Function: ads_784x_Read_tsData +**********************************************************************/ +static int ads_784x_Read_tsData(adsContext_t *adsContext) +{ + void *sspContext = adsContext->sspContext; + int x=0, x_1=0, x_2=0; + int y=0, y_1=0, y_2=0; + int pen_down = 0; + int p = 0; +#ifdef CONFIG_ADS7846 + int p1=0, p1_1=0, p1_2=0; + int p2=0, p2_1=0, p2_2=0; +#endif + + vdprintk("ENTER: ads_784x_Read_tsData()\n"); + + /* + * Filtering is policy. Policy belongs in user space. We + * therefore leave it to user space to do any filtering + * they please. + * + * We do however, read twice and check against maximum x & y deltas + * to reduce the amount of garbage returned. + * + * Note: There will be one reading with p=0 given when the pen is raised. + */ + + /* Read the pen_down data first as it jitters after the other reads */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + pen_down = adsContext->is_pen_down(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + + do { + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + /* + * Read the pressure, X position, and Y position. + * Interleave them for better performance + */ +#ifdef CONFIG_ADS7846 + adsContext->write(sspContext, ADS_784x_READ_P1); + adsContext->write(sspContext, ADS_784x_READ_P2); + p1_1 = adsContext->read(sspContext); + p2_1 = adsContext->read(sspContext); +#endif + adsContext->write(sspContext, ADS_784x_READ_X); + adsContext->write(sspContext, ADS_784x_READ_Y); + x_1 = adsContext->read(sspContext); + y_1 = adsContext->read(sspContext); + + /* + * ... AGAIN ... + * Read the pressure, X position, and Y position. + * Interleave them for better performance + */ +#ifdef CONFIG_ADS7846 + adsContext->write(sspContext, ADS_784x_READ_P1); + adsContext->write(sspContext, ADS_784x_READ_P2); + p1_2 = adsContext->read(sspContext); + p2_2 = adsContext->read(sspContext); +#endif + adsContext->write(sspContext, ADS_784x_READ_X); + adsContext->write(sspContext, ADS_784x_READ_Y); + x_2 = adsContext->read(sspContext); + y_2 = adsContext->read(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + } while ((x_1 > (x_2+X_DELTA_MAX)) || (x_2 > (x_1+X_DELTA_MAX)) + || (y_1 > (y_2+Y_DELTA_MAX)) || (y_2 > (y_1+Y_DELTA_MAX))); + + +#ifdef CONFIG_ADS7846 + p1 = (p1_1 + p1_2) / 2; + p2 = (p2_1 + p2_2) / 2; + p = p2 - p1; +#else + p = pen_down; +#endif + x = (x_1 + x_2) / 2; + y = (y_1 + y_2) / 2; + + ads_784x_tsData_add(adsContext, p, x, y); + + dprintk("LEAVE: ads_784x_Read_tsData(p=0x%03x, x=0x%03x, y=0x%03x)\n", + p, x, y); + + return(pen_down); +} + +/********************************************************************** +* Function: ads_784x_thread +* +* This is a RT kernel thread that handles the ADC accesses +* (mainly so we can use semaphores to serialise accesses to the ADC). +**********************************************************************/ +static int ads_784x_thread(void *_adsContext) +{ + adsContext_t *adsContext = _adsContext; + void *sspContext = adsContext->sspContext; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + int pen_down = 0; + + vdprintk("ENTER: ads_784x_thread()\n"); + adsContext->rtask = tsk; + + daemonize(); + tsk->tty = NULL; + strcpy(tsk->comm, "ktsd"); + + /* 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(&adsContext->irq_wait, &wait); + + complete(&adsContext->complete); + + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + pen_down = adsContext->is_pen_down(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + for (;;) { + signed long interval; + + /* + * Set to interrupt mode and wait a settling time. + */ + set_task_state(tsk, TASK_INTERRUPTIBLE); + if (sspContext == NULL) { + interval = HZ; /* Check for change once per second */ + } else if (pen_down) { + /* If pen is down then periodically read pen position */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->disable_pen_down_irq(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + interval = HZ/SAMPLES_PER_SECOND; + } else { + /* If pen is not down then sleep until pen down interrupt */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->enable_pen_down_irq(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + interval = MAX_SCHEDULE_TIMEOUT; + } + schedule_timeout(interval); + if (signal_pending(tsk)) { + break; + } + if (pen_down == 0) { + /* + * On pen down there is some bounce. + * Wait a debounce period and read it again. + */ + schedule_timeout(HZ/DEBOUNCE_FRACTION_OF_A_SECOND); + if (signal_pending(tsk)) { + break; + } + /* + * If the pen is not down after the debounce period, + * ignore the pen down signal. + */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + pen_down = adsContext->is_pen_down(sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + if (pen_down == 0) + continue; + } + adsContext->disable_pen_down_irq(sspContext); + /* + * We got an IRQ, which works us up. Process the touchscreen. + */ + pen_down = ads_784x_Read_tsData(adsContext); + } + + remove_wait_queue(&adsContext->irq_wait, &wait); + adsContext->rtask = NULL; + vdprintk("LEAVE: ads_784x_thread()\n"); + + return(0); +} + +/********************************************************************** +* Function: ads_784x_read +* +* *********************************** +* *** User space driver interface *** +* *********************************** +**********************************************************************/ +static ssize_t ads_784x_read(struct file *filp, char *buffer, size_t _count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + adsContext_t *adsContext = filp->private_data; + char *ptr = buffer; + int err = 0; + int count = (int)_count; /* Force a sigened value to be used */ + + vdprintk("ENTER: ads_784x_read()\n"); + add_wait_queue(&adsContext->read_wait, &wait); + while (count >= sizeof(tsData_t)) { + err = -ERESTARTSYS; + if (signal_pending(current)) + break; + + if (ads_784x_tsData_pending(adsContext)) { + tsData_t *tsData = ads_784x_tsData_get(adsContext); + + err = copy_to_user(ptr, tsData, sizeof(tsData_t)); + ads_784x_tsData_pull(adsContext); + + if (err) + break; + + ptr += sizeof(tsData_t); + count -= sizeof(tsData_t); + continue; + } + + set_current_state(TASK_INTERRUPTIBLE); + err = -EAGAIN; + if (filp->f_flags & O_NONBLOCK) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&adsContext->read_wait, &wait); + vdprintk("LEAVE: ads_784x_read()\n"); + + return(ptr == buffer ? err : ptr - buffer); +} + +/********************************************************************** +* Function: ads_784x_poll +* +* *********************************** +* *** User space driver interface *** +* *********************************** +**********************************************************************/ +static unsigned int ads_784x_poll(struct file *filp, poll_table *wait) +{ + adsContext_t *adsContext = filp->private_data; + int ret = 0; + + vdprintk("ENTER: ads_784x_poll()\n"); + poll_wait(filp, &adsContext->read_wait, wait); + if (ads_784x_tsData_pending(adsContext)) + ret = POLLIN | POLLRDNORM; + vdprintk("LEAVE: ads_784x_poll()\n"); + + return(ret); +} + +/********************************************************************** +* Function: ads_784x_open +* +* *********************************** +* *** User space driver interface *** +* *********************************** +**********************************************************************/ +static int ads_784x_open(struct inode *inode, struct file *filp) +{ + adsContext_t *adsContext = &adsContext_l; + int ret = 0; + + vdprintk("ENTER: ads_784x_open()\n"); + + filp->private_data = adsContext; + + /* Flush the ts data queue here */ + ads_784x_tsData_flush(adsContext); + + vdprintk("LEAVE: ads_784x_open()\n"); + return(ret); +} + +/********************************************************************** +* Function: ads_784x_fasync +* +* *********************************** +* *** User space driver interface *** +* *********************************** +**********************************************************************/ +static int ads_784x_fasync(int fd, struct file *filp, int on) +{ + int sts; + adsContext_t *adsContext = filp->private_data; + + vdprintk("ENTER: ads_784x_fasync()\n"); + sts = fasync_helper(fd, filp, on, &adsContext->fasync); + vdprintk("LEAVE: ads_784x_fasync()\n"); + + return(sts); +} + +/********************************************************************** +* Function: ads_784x_release +* +* *********************************** +* *** User space driver interface *** +* *********************************** +* +* Release touchscreen resources. Disable IRQs. +**********************************************************************/ +static int ads_784x_release(struct inode *inode, struct file *filp) +{ + // adsContext_t *adsContext = filp->private_data; + + vdprintk("ENTER: ads_784x_release()\n"); + lock_kernel(); + ads_784x_fasync(-1, filp, 0); + unlock_kernel(); + vdprintk("LEAVE: ads_784x_release()\n"); + + return(0); +} + +/********************************************************************** +* Define (fill in) the user space file operations for this driver +* and initialize the ADS touchscreen driver as a "miscdevice": +* Character device +* Major(10) --- Non-serial mice, misc features +* Minor(20) --- /dev/touchscreen/ads_784x +**********************************************************************/ +static struct file_operations ads_784x_fops = { + owner: THIS_MODULE, + read: ads_784x_read, + poll: ads_784x_poll, + open: ads_784x_open, + fasync: ads_784x_fasync, + release: ads_784x_release, +}; + +static struct miscdevice ads_784x_dev = { + minor: 20, + name: "touchscreen/ads_784x", + fops: &ads_784x_fops, +}; + +#ifdef PROC_BATTERY +/********************************************************************** +* ads_784x_proc_battery_read +**********************************************************************/ +static int ads_784x_proc_battery_read(char *buf, char **start, off_t offset, + int len, int *eof, void *unused) +{ + adsContext_t *adsContext = &adsContext_l; + ads784x_sspContext_t *ads784x_sspContext = adsContext->ads784x_sspContext; + int milliVolts; + int volts; + int hundredthsVolts; + int sample; + int size; + int count; + int last_irq_state; + + vdprintk("ENTER: ads_784x_proc_battery_read(len=%d)\n", len); + /* + * Reading the ADS784X takes the part out of pen down interrupt mode + * causing spurious pen down interrupts. So we must disable + * pen down interrupts while reading battery voltage. + */ + last_irq_state = adsContext->disable_pen_down_irq(ads784x_sspContext); + + /* Do a dummy read to turn on the internal reference voltage */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_BATTERY); + sample = adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + udelay(100); /* wait until the reference voltage settle */ + + sample = 0; + for (count = 0; count < 3; count++) { + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_BATTERY); + sample += adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + } + sample /= count; + milliVolts = (sample * 1000 * 10) / 4096; + volts = milliVolts / 1000; + hundredthsVolts = (milliVolts - (volts * 1000)) / 10; + size = sprintf(buf, "battery: %i.%02iV\n", volts, hundredthsVolts); + + /* Do a dummy read to turn off the internal reference voltage */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_X); + sample = adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + + /* Restore the interrupt enable state */ + if (last_irq_state) { + udelay(100); /* Wait until the pen down interrupt settles */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->enable_pen_down_irq(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + } + vdprintk("LEAVE: ads_784x_proc_battery_read(len=%d)\n", len); + + return(size); +} +#endif + +#ifdef PROC_TEMPERATURE +/********************************************************************** +* ads_784x_proc_temperature_read +**********************************************************************/ +static int ads_784x_proc_temperature_read(char *buf, char **start, + off_t offset, int len, int *eof, void *unused) +{ + adsContext_t *adsContext = &adsContext_l; + ads784x_sspContext_t *ads784x_sspContext = adsContext->ads784x_sspContext; + int size; + int count; + int C10, F10; + int sample1; + int sample91; + int last_irq_state; + + vdprintk("ENTER: ads_784x_proc_temperature_read(len=%d)\n", len); + /* + * Reading the ADS784X takes the part out of pen down interrupt mode + * causing spurious pen down interrupts. So we must disable + * pen down interrupts while reading temperature. + */ + last_irq_state = adsContext->disable_pen_down_irq(ads784x_sspContext); + + /* do a dummy read to turn on the internal reference voltage */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP0); + sample1 = adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + udelay(100); /* wait until the reference voltage settle */ + + sample1 = 0; + sample91 = 0; + /* read the temperature values */ + for (count = 0; count < 3; count++) { + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP0); + adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP1); + sample1 += adsContext->read(ads784x_sspContext); + sample91 += adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + } + /* average values */ + sample1 /= count; + sample91 /= count; + + C10 = (((sample91 - sample1) * (25 * 2573)) / 4095) - 2730; + F10 = (C10*9)/5 + 320; + + size = sprintf(buf, "Temperature: %iC, %iF\n", (C10+5)/10, (F10+5)/10); + + /* do a dummy read to turn off the internal reference voltage */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(ads784x_sspContext, ADS_784x_READ_X); + sample1 = adsContext->read(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + + /* restore the interrupt enable state */ + if (last_irq_state) { + udelay(100); /* wait until the pen down interrupt settles */ + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->enable_pen_down_irq(ads784x_sspContext); + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + } + vdprintk("LEAVE: ads_784x_proc_temperature_read(len=%d)\n", len); + + return(size); +} +#endif + +/********************************************************************** +* Function: ads_784x_make_ssp_association +* +* Purpose: +* Make the association between the eeprom driver and the ssp driver +**********************************************************************/ +static int ads_784x__make_ssp_association(adsContext_t *adsContext) +{ + int sts = 0; + void *vp; + +/* NOTE: -EOPNOTSUPP == Operation not supported on transport endpoint */ +#define ASSOCIATION_ERROR -EOPNOTSUPP + + dprintk("ENTER: ads_784x_make_ssp_association()\n"); + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "sspContext"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->sspContext = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "write"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->write = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "read"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->read = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "enable_pen_down_irq"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->enable_pen_down_irq = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "disable_pen_down_irq"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->disable_pen_down_irq = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "is_pen_down"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->is_pen_down = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "lock"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->lock = vp; + + vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "unlock"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + adsContext->unlock = vp; + + /* Note: The following need reset to NULL when we are finished */ + + vp = ssp_provide_pointer(SSP_DEV_TOUCHSCREEN, "irq_wait_ptr", + &(adsContext->irq_wait)); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + + dprintk("LEAVE: ads_784x_make_ssp_association(%d)\n", sts); + + return(sts); +} + +/********************************************************************** +* Function: ads_784x_init +* +* Purpose: +* Register & Initialize the module +**********************************************************************/ +static int __init ads_784x_init(void) +{ + adsContext_t *adsContext = &adsContext_l; + int sts = -ENODEV; + + vdprintk("ENTER: ads_784x_init()\n"); + init_waitqueue_head(&adsContext->read_wait); + /* Retrieve the service information from the SSP driver */ + sts = ads_784x__make_ssp_association(adsContext); + if (sts == 0) { + void *sspContext = adsContext->sspContext; + + /* Start the ADS polling thread */ + lock_kernel(); + if (adsContext->rtask == NULL) { + init_completion(&adsContext->complete); + init_waitqueue_head(&adsContext->irq_wait); + sts = kernel_thread(ads_784x_thread, adsContext, + CLONE_FS | CLONE_FILES); + if (sts >= 0) { + sts = 0; + /* Only do this is the tread started correctly */ + wait_for_completion(&adsContext->complete); + } + } + unlock_kernel(); + + /* MUST lock the SSP before accessing it */ + adsContext->lock(sspContext, SSP_DEV_TOUCHSCREEN); + adsContext->write(sspContext, ADS_784x_INIT); + adsContext->read(sspContext); /* dummy read */ + /* MUST unlock the SSP after it has been locked */ + adsContext->unlock(sspContext, SSP_DEV_TOUCHSCREEN); + + sts = misc_register(&ads_784x_dev); + +#ifdef PROC_BATTERY + ads_784x_proc_battery = create_proc_entry("battery", 0, 0); + if (ads_784x_proc_battery) { + ads_784x_proc_battery->read_proc = ads_784x_proc_battery_read; + } else { + printk(KERN_ERR "%s: unable to register /proc/battery\n", DRVNAME); + } +#endif +#ifdef PROC_TEMPERATURE + ads_784x_proc_temperature = create_proc_entry("temperature", 0, 0); + if (ads_784x_proc_temperature) { + ads_784x_proc_temperature->read_proc = ads_784x_proc_temperature_read; + } else { + printk(KERN_ERR "%s: unable to register /proc/temperature\n", DRVNAME); + } +#endif + } + + vdprintk("LEAVE: ads_784x_init()\n"); + return(sts); +} + +/********************************************************************** +* Function: ads_784x_exit +* +* Purpose: +* Un-Register & Cleanup the module +**********************************************************************/ +static void ads_784x_exit(void) +{ + adsContext_t *adsContext = &adsContext_l; + + vdprintk("ENTER: ads_784x_exit()\n"); + + if (adsContext->rtask) { + send_sig(SIGKILL, adsContext->rtask, 1); + schedule(); + } + + vdprintk("ads_784x_exit(): misc_deregister()\n"); + misc_deregister(&ads_784x_dev); + + /* Back out the pointer(s) we gave to the SSP driver */ + (void) ssp_provide_pointer(SSP_DEV_TOUCHSCREEN, "irq_wait_ptr", NULL); + +#ifdef PROC_BATTERY + remove_proc_entry("battery", NULL); +#endif +#ifdef PROC_TEMPERATURE + remove_proc_entry("temperature", NULL); +#endif + + vdprintk("LEAVE: ads_784x_exit()\n"); + + return; +} + +module_init(ads_784x_init); +module_exit(ads_784x_exit); + +MODULE_AUTHOR("Jim Gleason"); +MODULE_DESCRIPTION("ADS 784x Driver for Sharp LH7x EVB"); +MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/eeprom-lh7a400.c linux-2.4.21-rmk1-lh7a400/drivers/misc/eeprom-lh7a400.c --- linux-2.4.21-rmk1/drivers/misc/eeprom-lh7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/eeprom-lh7a400.c Sun Feb 8 20:32:52 2004 @@ -0,0 +1,749 @@ +/* vi: set sw=4 ts=4 ai: */ + +// #define MODULE + +#define READ_AFTER_WRITE + +/********************************************************************** +* linux/drivers/misc/eeprom-lh7x.c +* +* Provide Microchip 93LC46B 64 x 16 EEPROM access for LH7x EVB boards +* +* Copyright (C) 2002 Lineo, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) version 2 +* as published by the Free Software Foundation. +* +* References: +* SHARP_EVB_DISPLAY_BOARD_REV2.pdf +* 93LC46.pdf (Microchip 1K Microwire(R) EEPROM chip spec) +* +**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "eeprom-lh7x" +//#include +#define vdprintk(...) +#define dprintk(...) + +#include +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif /* MODULE */ + +#include + +#include "ssp.h" + +#define SIXmsJIFFIES (((HZ*6)/1000)+2) + +/********************************************************************** +* Define EEPROM Control macros for "Microchip 93LC46B Microwire Serial EEPROM" +**********************************************************************/ + +/* Erase one 16 bit word at addr */ +#define EEPROM_ERASE(addr) (0x01C0 | (addr & 0x3F)) +/* Erase entire eeprom */ +#define EEPROM_ERAL() (0x0120) +/* Erase/Write disable */ +#define EEPROM_EWDS() (0x0100) +/* Erase/Write enable */ +#define EEPROM_EWEN() (0x0130) +/* Read one 16 bit word at addr */ +#define EEPROM_READ(addr) (0x0180 | (addr & 0x3F)) +/* (Erase and) Write one 16 bit word at addr */ +#define EEPROM_WRITE(addr) (0x0140 | (addr & 0x3F)) +/* Write one 16 bit value throught entire eeprom */ +#define EEPROM_WRAL() (0x0110) + +/********************************************************************** +* Define our eeprom context structure +**********************************************************************/ + +#define EEPROM_SIZE_16BIT 64 +#define EEPROM_SIZE_8BIT 128 + +typedef struct eepromContext_t eepromContext_t; +struct eepromContext_t { + union { + uint16_t w[EEPROM_SIZE_16BIT]; /* Actual device size */ + u_char c[EEPROM_SIZE_8BIT]; + } cache; + union { + uint16_t w[EEPROM_SIZE_16BIT]; /* Actual device size */ + u_char c[EEPROM_SIZE_8BIT]; + } state; + wait_queue_head_t read_and_write_wait; + + void *sspContext; + void (*write) (void *sspContext, unsigned int data); + unsigned int (*read) (void *sspContext); + int (*lock)(void *sspContext, int device); + int (*unlock)(void *sspContext, int device); +#if defined(CONFIG_ARCH_LH79520) + void (*ssp_chipselect_automatic)(void); + void (*ssp_chipselect_manual)(void); + void (*ssp_chipselect_enable)(void); + void (*ssp_chipselect_disable)(void); +#elif defined(CONFIG_ARCH_LH7A400) + int (*ssp_eeprom_busy_poll)(void *sspContext, int timeout_ms); +#endif + void (*ssp_flush_tx_fifo)(void *sspContext); + void (*ssp_flush_rx_fifo)(void *sspContext); + void (*ssp_busy_wait)(void); +}; +static eepromContext_t eepromContext_l; + +#define CACHE_STATE_VALID_8 0x01 +#define CACHE_STATE_MODIFIED_8 0x02 + +#define CACHE_STATE_VALID_16 0x0101 +#define CACHE_STATE_MODIFIED_16 0x0202 + +/********************************************************************** +* Function: eeprom_lh7x_erase_write_enable +* Function: eeprom_lh7x_erase_write_disable +**********************************************************************/ +static void +eeprom_lh7x_erase_write_enable(eepromContext_t *eepromContext) +{ + void *sspContext = eepromContext->sspContext; + + /* Lock the SSP before accessing it */ + eepromContext->lock(sspContext, SSP_DEV_EEPROM); + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* EEPROM Writes must be done using manual control of the ChipSelect */ + eepromContext->ssp_chipselect_manual(); + eepromContext->ssp_chipselect_enable(); +#endif + + eepromContext->write(sspContext, EEPROM_EWEN()); /* Enable Erase/Write */ + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* Reset back to automatic control of the EEPROM ChipSelect */ + eepromContext->ssp_chipselect_disable(); + eepromContext->ssp_chipselect_automatic(); +#endif + + /* Unlock the SSP after it has been locked */ + eepromContext->unlock(sspContext, SSP_DEV_EEPROM); + + return; +} + +static void +eeprom_lh7x_erase_write_disable(eepromContext_t *eepromContext) +{ + void *sspContext = eepromContext->sspContext; + + /* Lock the SSP before accessing it */ + eepromContext->lock(sspContext, SSP_DEV_EEPROM); + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* EEPROM Writes must be done using manual control of the ChipSelect */ + eepromContext->ssp_chipselect_manual(); + eepromContext->ssp_chipselect_enable(); +#endif + + eepromContext->write(sspContext, EEPROM_EWDS()); /* Disable Erase/Write */ + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* Reset back to automatic control of the EEPROM ChipSelect */ + eepromContext->ssp_chipselect_disable(); + eepromContext->ssp_chipselect_automatic(); +#endif + + /* Unlock the SSP after it has been locked */ + eepromContext->unlock(sspContext, SSP_DEV_EEPROM); + + return; +} + +/********************************************************************** +* Function: eeprom_lh7x_read_device_word +**********************************************************************/ +static void +eeprom_lh7x_read_device_word(eepromContext_t *eepromContext, int offset_w) +{ + void *sspContext = eepromContext->sspContext; + uint16_t word = 0; + + /* Lock the SSP before accessing it */ + eepromContext->lock(sspContext, SSP_DEV_EEPROM); + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* EEPROM Reads must be done using manual control of the ChipSelect */ + eepromContext->ssp_chipselect_manual(); + eepromContext->ssp_chipselect_enable(); +#endif + + /* Read eeprom into cache */ + /* Note: We shift to take care of the "dummy 0" the eeprom sends */ + eepromContext->write(sspContext, (EEPROM_READ(offset_w))<<1); + /* Following is a Dummy/Invalid command to allow the eeprom to be read */ + eepromContext->write(sspContext, 0); + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + word = eepromContext->read(sspContext); /* Dummy Word */ + word = eepromContext->read(sspContext); /* Real Word */ + +#if defined(CONFIG_ARCH_LH79520) + /* Reset back to automatic control of the EEPROM ChipSelect */ + eepromContext->ssp_chipselect_disable(); + eepromContext->ssp_chipselect_automatic(); +#endif + + /* Unlock the SSP after it has been locked */ + eepromContext->unlock(sspContext, SSP_DEV_EEPROM); + + /* Modify the state of the cache data */ + eepromContext->cache.w[offset_w] = word; + eepromContext->state.w[offset_w] |= CACHE_STATE_VALID_16; + + schedule(); /* Give the rest of the system a chance to work */ + + return; +} + +/********************************************************************** +* Function: eeprom_lh7x_write_device_word +**********************************************************************/ +static void +eeprom_lh7x_write_device_word(eepromContext_t *eepromContext, int offset_w) +{ + void *sspContext = eepromContext->sspContext; + uint16_t word; + long timeoutJiffies; + + vdprintk("ENTER: eeprom_lh7x_write_device_word(,%d)\n", offset_w); + + /* Get the modified cache data to write to the eeprom */ + word = eepromContext->cache.w[offset_w]; + + /* Lock the SSP before accessing it */ + eepromContext->lock(sspContext, SSP_DEV_EEPROM); + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + +#if defined(CONFIG_ARCH_LH79520) + /* EEPROM Writes must be done using manual control of the ChipSelect */ + eepromContext->ssp_chipselect_manual(); + eepromContext->ssp_chipselect_enable(); +#endif + + /* Write modified cache data to the eeprom */ + eepromContext->write(sspContext, EEPROM_WRITE(offset_w)); + eepromContext->write(sspContext, word); + +#if defined(CONFIG_ARCH_LH79520) + /* Reset back to automatic control of the EEPROM ChipSelect */ + eepromContext->ssp_chipselect_disable(); + eepromContext->ssp_chipselect_automatic(); +#elif defined(CONFIG_ARCH_LH7A400) + (void) eepromContext->ssp_eeprom_busy_poll(sspContext, 7); /* Min of 6 */ +#endif + + eepromContext->ssp_busy_wait(); /* Wait for the SSP to not be busy */ + eepromContext->ssp_flush_rx_fifo(sspContext); + + /* Unlock the SSP after it has been locked */ + eepromContext->unlock(sspContext, SSP_DEV_EEPROM); + + /* Modify the state of the cache data */ + eepromContext->state.w[offset_w] &= ~CACHE_STATE_MODIFIED_16; + +#ifdef READ_AFTER_WRITE + /* Force the modified cache data to be reread from the eeprom */ + eepromContext->state.w[offset_w] &= ~CACHE_STATE_VALID_16; +#endif /* READ_AFTER_WRITE */ + + /* Cause ~ 6ms delay (actually does 10 on the Sharp LH79520) */ + timeoutJiffies = SIXmsJIFFIES; + while (timeoutJiffies > 0) { + __set_current_state(TASK_UNINTERRUPTIBLE); + timeoutJiffies = schedule_timeout(timeoutJiffies); + } + // __set_current_state(TASK_RUNNING); + + schedule(); /* Give the rest of the system a chance to work */ + + vdprintk("LEAVE: eeprom_lh7x_write_device_word()\n"); + + return; +} + +/********************************************************************** +* Function: eeprom_lh7x_read_device +**********************************************************************/ +static void +eeprom_lh7x_read_device(eepromContext_t *eepromContext) +{ + uint16_t *scwp; + int offset_w; + + scwp = eepromContext->state.w; + for (offset_w = 0; offset_w < EEPROM_SIZE_16BIT; offset_w++) { + if ((*scwp & CACHE_STATE_VALID_16) != CACHE_STATE_VALID_16) { + eeprom_lh7x_read_device_word(eepromContext, offset_w); + } + scwp++; + } + + return; +} + +/********************************************************************** +* Function: eeprom_lh7x_write_device +**********************************************************************/ +static void +eeprom_lh7x_write_device(eepromContext_t *eepromContext) +{ + uint16_t *scwp; + int offset_w; + int timeoutJiffies; + + vdprintk("ENTER: eeprom_lh7x_write_device()\n"); + + /* Enable erase/write of the eeprom */ + eeprom_lh7x_erase_write_enable(eepromContext); + + /* Just to get the timeouts in a desirable sequence */ + /* and so we don't get a "partial" timeout we do the following... */ + /* Cause ~ 6ms delay (actually does 10 on the Sharp LH79520) */ + timeoutJiffies = SIXmsJIFFIES; + while (timeoutJiffies > 0) { + __set_current_state(TASK_UNINTERRUPTIBLE); + timeoutJiffies = schedule_timeout(timeoutJiffies); + } + // __set_current_state(TASK_RUNNING); + + scwp = eepromContext->state.w; + for (offset_w = 0; offset_w < EEPROM_SIZE_16BIT; offset_w++) { + if (*scwp & CACHE_STATE_MODIFIED_16) { + eeprom_lh7x_write_device_word(eepromContext, offset_w); + } + scwp++; + } + + /* Disable erase/write of the eeprom */ + eeprom_lh7x_erase_write_disable(eepromContext); + +#ifdef READ_AFTER_WRITE + /* + * NOW ... Update the eeprom cache. + * ( Read the actual contents of the eeprom that were + * modified instead of relying on what we wrote. ) + */ + eeprom_lh7x_read_device(eepromContext); +#endif /* READ_AFTER_WRITE */ + + vdprintk("LEAVE: eeprom_lh7x_write_device()\n"); + + return; +} + +/********************************************************************** +* ***************************************************** +* *** User space "file operation" driver interfaces *** +* ***************************************************** +* Function: lh7x_eeprom_llseek +* Function: lh7x_eeprom_read +* Function: lh7x_eeprom_write +* Function: lh7x_eeprom_poll ( NOT USED --- YET ) +* Function: lh7x_eeprom_ioctl ( NOT USED --- YET ) +* Function: lh7x_eeprom_open +* Function: lh7x_eeprom_flush ( NOT USED --- YET ) +* Function: lh7x_eeprom_release ( NOT USED --- YET ) +* Function: lh7x_eeprom_fsync ( NOT USED --- YET ) +* Function: lh7x_eeprom_fasync ( NOT USED --- YET ) +* Function: lh7x_eeprom_lock ( NOT USED --- YET ) +**********************************************************************/ + +static loff_t +lh7x_eeprom_llseek(struct file *filp, loff_t offset, int origin) +{ + // eepromContext_t *eepromContext = filp->private_data; + loff_t new_offset = -EINVAL; + + switch (origin) { + case 0: /* SEEK_SET == 0, Offset from the start */ + new_offset = offset; + break; + case 1: /* SEEK_CUR == 1, Offset from the current position */ + new_offset = filp->f_pos + offset; + break; + case 2: /* SEEK_END == 2, Offset from the end */ + new_offset = EEPROM_SIZE_8BIT - offset; + break; + } + if ((new_offset < 0) || (new_offset > EEPROM_SIZE_8BIT)) { + new_offset = -EINVAL; + } else { + filp->f_pos = new_offset; + } + + return(new_offset); +} + +static ssize_t +lh7x_eeprom_read(struct file *filp, char *buffer, + size_t count, loff_t *offsetp) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + int err; + + vdprintk("ENTER: lh7x_eeprom_read(%d:%d)\n", *offsetp, count); + /* Ensure we still have data to read (relative to the offset we are at) */ + if (*offsetp < EEPROM_SIZE_8BIT) { + /* Adjust the size to be read if necessary */ + if ((*offsetp + count) > EEPROM_SIZE_8BIT) { + count = EEPROM_SIZE_8BIT - *offsetp; + } + /* Ensure the eeprom cache is valid */ + eeprom_lh7x_read_device(eepromContext); + /* Return the contents of the eeprom cache */ + err = copy_to_user(buffer, &eepromContext->cache.c[*offsetp], count); + if ( ! err) { + *offsetp += count; + sts = count; + } else { + sts = -EFAULT; + } + } + vdprintk("LEAVE: lh7x_eeprom_read(%d)\n", sts); + + return(sts); +} + +static ssize_t +lh7x_eeprom_write(struct file *filp, const char *buffer, + size_t count, loff_t *offsetp) +{ + eepromContext_t *eepromContext = filp->private_data; + u_char newcache_c[EEPROM_SIZE_8BIT]; + int sts = 0; + int err; + + vdprintk("ENTER: lh7x_eeprom_write(%d:%d)\n", *offsetp, count); + /* Ensure we still have room to write (relative to the offset we are at) */ + if (*offsetp < EEPROM_SIZE_8BIT) { + /* Adjust the size to be written if necessary */ + if ((*offsetp + count) > EEPROM_SIZE_8BIT) { + count = EEPROM_SIZE_8BIT - *offsetp; + } + /* Ensure the eeprom cache is valid to start with */ + eeprom_lh7x_read_device(eepromContext); + /* Get the new contents of the eeprom cache */ + err = copy_from_user(&newcache_c[*offsetp], buffer, count); + if ( ! err) { + u_char *ccp, *nccp, *sccp; + int i; + /* + * Transfer the new cache contents into the cache + * marking what has changed. + */ + ccp = &eepromContext->cache.c[*offsetp]; + nccp = &newcache_c[*offsetp]; + sccp = &eepromContext->state.c[*offsetp]; + for (i = 0; i < count; i++) { + if (*ccp != *nccp) { + *ccp = *nccp; + *sccp |= CACHE_STATE_MODIFIED_8; + } + ccp++; + nccp++; + sccp++; + } + /* Write the modified cache into the eeprom */ + eeprom_lh7x_write_device(eepromContext); + *offsetp += count; + sts = count; + } else { + sts = -EFAULT; + } + } + vdprintk("LEAVE: lh7x_eeprom_write(%d)\n", sts); + + return(sts); +} + +#if (0) /* NOT USED --- YET */ +static unsigned int +lh7x_eeprom_poll(struct file *filp, struct poll_table_struct *wait) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_ioctl(struct inode *, struct file *filp, unsigned int cmd, unsigned long arg) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +static int +lh7x_eeprom_open(struct inode *inode, struct file *filp) +{ + eepromContext_t *eepromContext = &eepromContext_l; + int sts = 0; + + filp->private_data = eepromContext; + + return(sts); +} + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_flush(struct file *filp) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_release(struct inode *inode, struct file *filp) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_fsync(struct file *filp, struct dentry *dentry, int datasync) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_fasync(int fd, struct file *filp, int on) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +#if (0) /* NOT USED --- YET */ +static int +lh7x_eeprom_lock(struct file *filp, int XXX, struct file_lock *file_lock) +{ + eepromContext_t *eepromContext = filp->private_data; + int sts = 0; + + return(sts); +} +#endif /* NOT USED --- YET */ + +/********************************************************************** +* Define (fill in) the user space file operations for this driver +* and initialize the eeprom driver as a "miscdevice": +* Character device +* Major(10) --- Non-serial mice, misc features +* Minor(22) --- /dev/eeprom ( Microchip 93LC46B 64 x 16 EEPROM ) +**********************************************************************/ +static struct file_operations lh7x_eeprom_fops = { + owner: THIS_MODULE, + llseek: lh7x_eeprom_llseek, + read: lh7x_eeprom_read, + write: lh7x_eeprom_write, +// poll: lh7x_eeprom_poll, +// ioctl: lh7x_eeprom_ioctl, + open: lh7x_eeprom_open, +// flush: lh7x_eeprom_flush, +// release: lh7x_eeprom_release, +// fsync: lh7x_eeprom_fsync, +// fasync: lh7x_eeprom_fasync, +// lock: lh7x_eeprom_lock, +}; + +static struct miscdevice lh7x_eeprom_dev = { +minor: 22, +name: "eeprom", +fops: &lh7x_eeprom_fops, +}; + +/********************************************************************** +* Function: lh7x_eeprom_make_ssp_association +* +* Purpose: +* Make the association between the eeprom driver and the ssp driver +**********************************************************************/ +static int lh7x_eeprom_make_ssp_association(eepromContext_t *eepromContext) +{ + int sts = 0; + void *vp; + +/* NOTE: -EOPNOTSUPP == Operation not supported on transport endpoint */ +#define ASSOCIATION_ERROR -EOPNOTSUPP + + dprintk("ENTER: lh7x_eeprom_make_ssp_association()\n"); + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "sspContext"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->sspContext = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "write"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->write = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "read"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->read = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "lock"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->lock = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "unlock"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->unlock = vp; + +#if defined(CONFIG_ARCH_LH79520) + vp = ssp_request_pointer(SSP_DEV_EEPROM, "chipselect_enable"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_chipselect_enable = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "chipselect_disable"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_chipselect_disable = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "chipselect_manual"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_chipselect_manual = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "chipselect_automatic"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_chipselect_automatic = vp; +#elif defined(CONFIG_ARCH_LH7A400) + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "eeprom_busy_poll"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_eeprom_busy_poll = vp; +#endif + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "flush_tx_fifo"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_flush_tx_fifo = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "flush_rx_fifo"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_flush_rx_fifo = vp; + + vp = ssp_request_pointer(SSP_DEV_EEPROM, "ssp_busy_wait"); + if ( ! vp ) + sts = ASSOCIATION_ERROR; + eepromContext->ssp_busy_wait = vp; + + dprintk("LEAVE: lh7x_eeprom_make_ssp_association(%d)\n", sts); + + return(sts); +} + +/********************************************************************** +* Function: lh7x_eeprom_init +* +* Purpose: +* Register & Initialize the module +**********************************************************************/ +static int lh7x_eeprom_init(void) +{ + eepromContext_t *eepromContext = &eepromContext_l; + int sts = 0; + dprintk("ENTER: lh7x_eeprom_init()\n"); + init_waitqueue_head(&eepromContext->read_and_write_wait); + /* Retrieve the service information from the SSP driver */ + sts = lh7x_eeprom_make_ssp_association(eepromContext); + if (sts == 0) { + /* Ensure the eeprom cache is valid */ + eeprom_lh7x_read_device(eepromContext); + sts = misc_register(&lh7x_eeprom_dev); + } + dprintk("LEAVE: lh7x_eeprom_init(%d)\n", sts); + return(sts); +} + +/********************************************************************** +* Function: lh7x_eeprom_exit +* +* Purpose: +* Un-Register & Cleanup the module +**********************************************************************/ +static void lh7x_eeprom_exit(void) +{ + dprintk("ENTER: lh7x_eeprom_exit()\n"); + misc_deregister(&lh7x_eeprom_dev); + dprintk("LEAVE: lh7x_eeprom_exit()\n"); + return; +} + +module_init(lh7x_eeprom_init); +module_exit(lh7x_eeprom_exit); + +MODULE_AUTHOR("Jim Gleason / Lineo, Inc."); +MODULE_DESCRIPTION("Microchip 93LC46B 64 x 16 EEPROM access for LH7x EVB"); +MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/led-lh7a400.c linux-2.4.21-rmk1-lh7a400/drivers/misc/led-lh7a400.c --- linux-2.4.21-rmk1/drivers/misc/led-lh7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/led-lh7a400.c Sun Feb 8 20:35:44 2004 @@ -0,0 +1,651 @@ +/* vi: set sw=4 ts=4 ai: */ + +//#define MODULE + +/********************************************************************** +* linux/drivers/misc/lh7x-7seg.c +* +* Provide ADS_784x 7-Segment access for LH7x EVB boards +* +* Copyright (C) 2002 Lineo, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) version 2 +* as published by the Free Software Foundation. +* +**********************************************************************/ + +/********************************************************************** +* To light up the 7-segment display, write a 16-bit value to +* +* cpld->seven_seg. +* +* The high-order byte is the most significant 7-segment digit, +* and the low-order byte is the lsb. +* +* NOTE: The 7-segment display bars are bit-mapped. +* NOTE: The 7-segment display bars are ACTIVE LOW. +* +* _ == a +* | | == f b +* - == g +* | | == e c +* -. == d dot +* +* a 0x01 +* b 0x02 +* c 0x04 +* d 0x08 +* e 0x10 +* f 0x20 +* g 0x40 +* dot 0x80 (also known as dp) +* +* The data to write looks like this: +* +* static u_char lednum[] = +* { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, // 0-7 +* 0x80, 0x98, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, // 8-F +* 0xBF, // hyphen +* 0xFF, // (blank) +* }; +* +* SO - to make "7F" show up, do this: +* +* cpld->seven_seg = 0xf88e; +* +* NOTE: When read, the 7-segment display does not return valid data. +* +**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "lh7x-7seg" +//#include +#define vdprintk(...) +#define dprintk(...) + +#include +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif /* MODULE */ + +#include +#include +#include + +static cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; + +/********************************************************************** +* Define our Seven Segment context structure +**********************************************************************/ +typedef struct sevenSegmentContext_t sevenSegmentContext_t; +struct sevenSegmentContext_t { + struct fasync_struct *fasync; + wait_queue_head_t read_and_write_wait; + + int inEscape; /* 1 == We are in an escape sequence, 0 == NOT */ + int accessMode; /* See ACCESSMODE_xxx definitions below */ + int rawData; /* Raw == 1, Cooked == 0 */ + uint16_t currentRawVal; +}; +static sevenSegmentContext_t sevenSegmentContext_l; + +#define ESCAPE 27 + +#define ACCESSMODE_SHIFT 0 +#define ACCESSMODE_LSB 1 +#define ACCESSMODE_MSB 2 +#define ACCESSMODE_DAFAULT ACCESSMODE_SHIFT + +/********************************************************************** +* Define our Seven Segment Data +**********************************************************************/ + +typedef struct sevenSegmentData_t sevenSegmentData_t; +struct sevenSegmentData_t { + int val; + u_char raw_val; +}; + +#define SSD_BLANK ((u_char)~(0x00)) + +static sevenSegmentData_t sevenSegmentData[] = { + {'0', (u_char)~(SSD_A | SSD_B | SSD_C | SSD_D | SSD_E | SSD_F) }, + {'1', (u_char)~(SSD_B | SSD_C) }, + {'2', (u_char)~(SSD_A | SSD_B | SSD_G | SSD_E | SSD_D) }, + {'3', (u_char)~(SSD_A | SSD_B | SSD_G | SSD_C | SSD_D) }, + {'4', (u_char)~(SSD_F | SSD_G | SSD_B | SSD_C) }, + {'5', (u_char)~(SSD_A | SSD_F | SSD_G | SSD_C | SSD_D) }, + {'6', (u_char)~(SSD_A | SSD_F | SSD_E | SSD_D | SSD_C | SSD_G) }, + {'7', (u_char)~(SSD_A | SSD_B | SSD_C) }, + {'8', (u_char)~(SSD_A | SSD_B | SSD_C | SSD_D | SSD_E | SSD_F | SSD_G) }, + {'9', (u_char)~(SSD_G | SSD_F | SSD_A | SSD_B | SSD_C) }, + {'A', (u_char)~(SSD_E | SSD_F | SSD_A | SSD_B | SSD_C | SSD_G) }, + {'a', (u_char)~(SSD_E | SSD_F | SSD_A | SSD_B | SSD_C | SSD_G) }, + {'B', (u_char)~(SSD_F | SSD_E | SSD_D | SSD_C | SSD_G) }, + {'b', (u_char)~(SSD_F | SSD_E | SSD_D | SSD_C | SSD_G) }, + {'C', (u_char)~(SSD_A | SSD_F | SSD_E | SSD_D) }, + {'c', (u_char)~(SSD_A | SSD_F | SSD_E | SSD_D) }, + {'D', (u_char)~(SSD_B | SSD_C | SSD_D | SSD_E | SSD_G) }, + {'d', (u_char)~(SSD_B | SSD_C | SSD_D | SSD_E | SSD_G) }, + {'E', (u_char)~(SSD_A | SSD_F | SSD_G | SSD_E | SSD_D) }, + {'e', (u_char)~(SSD_A | SSD_F | SSD_G | SSD_E | SSD_D) }, + {'F', (u_char)~(SSD_A | SSD_F | SSD_G | SSD_E) }, + {'f', (u_char)~(SSD_A | SSD_F | SSD_G | SSD_E) }, + {'H', (u_char)~(SSD_F | SSD_E | SSD_G | SSD_B | SSD_C) }, + {'h', (u_char)~(SSD_F | SSD_E | SSD_G | SSD_B | SSD_C) }, + {'I', (u_char)~(SSD_F | SSD_E) }, + {'i', (u_char)~(SSD_F | SSD_E) }, + {'Y', (u_char)~(SSD_F | SSD_G | SSD_B | SSD_C | SSD_D) }, + {'y', (u_char)~(SSD_F | SSD_G | SSD_B | SSD_C | SSD_D) }, + {'-', (u_char)~(SSD_G) }, + {'_', (u_char)~(SSD_D) }, + {'.', (u_char)~(SSD_DOT) }, + {' ', SSD_BLANK }, + {0x00, SSD_BLANK }, + { -1, (u_char)~(0x00) } /* End Of Data --- Must Be Last */ +}; + +/********************************************************************** +* Function: val_to_raw_val +**********************************************************************/ +static u_char val_to_raw_val(u_char val) +{ + sevenSegmentData_t *data; + u_char raw_val = 0xFF; /* Assume a blank if not found */ + for (data = sevenSegmentData; data->val != -1; data++) { + if (val == data->val) { + raw_val = data->raw_val; + break; + } + } + return(raw_val); +} + +/********************************************************************** +* Function: raw_val_to_val +**********************************************************************/ +static u_char raw_val_to_val(u_char raw_val) +{ + sevenSegmentData_t *data; + u_char val = ' '; /* Assume a blank if not found */ + for (data = sevenSegmentData; data->val != -1; data++) { + if (raw_val == data->raw_val) { + val = data->val; + break; + } + } + return(val); +} + +/********************************************************************** +* Function: lh7x_7seg_read_raw_display +* Function: lh7x_7seg_read_raw_display_lsb +* Function: lh7x_7seg_read_raw_display_msb +**********************************************************************/ +uint16_t lh7x_7seg_read_raw_display(void) +{ + sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; + uint16_t raw_val; + + /* + * NOTE: The device does not read so we have to remember... + */ + raw_val = sevenSegmentContext->currentRawVal; + vdprintk("lh7x_7seg_read_raw_display(0x%04X)\n", raw_val); + + return(raw_val); +} + +u_char lh7x_7seg_read_raw_display_lsb(void) +{ + uint16_t raw_val; + u_char raw_lsb; + + raw_val = lh7x_7seg_read_raw_display(); + raw_lsb = (u_char)(raw_val & 0xFF); + + return(raw_lsb); +} + +u_char lh7x_7seg_read_raw_display_msb(void) +{ + uint16_t raw_val; + u_char raw_msb; + + raw_val = lh7x_7seg_read_raw_display(); + raw_msb = (u_char)((raw_val >> 8) & 0xFF); + + return(raw_msb); +} + +/********************************************************************** +* Function: lh7x_7seg_read_display +* Function: lh7x_7seg_read_display_lsb +* Function: lh7x_7seg_read_display_msb +**********************************************************************/ +uint16_t lh7x_7seg_read_display(void) +{ + uint16_t raw_val, val; + u_char raw_lsb, lsb; + u_char raw_msb, msb; + + raw_val = lh7x_7seg_read_raw_display(); + raw_lsb = (u_char)( raw_val & 0xFF); + raw_msb = (u_char)((raw_val >> 8) & 0xFF); + lsb = raw_val_to_val(raw_lsb); + msb = raw_val_to_val(raw_msb); + val = (uint16_t)((msb << 8) | lsb); + + return(val); +} + +u_char lh7x_7seg_read_display_lsb(void) +{ + u_char raw_lsb, lsb; + + raw_lsb = lh7x_7seg_read_raw_display_lsb(); + lsb = raw_val_to_val(raw_lsb); + + return(lsb); +} + +u_char lh7x_7seg_read_display_msb(void) +{ + u_char raw_msb, msb; + + raw_msb = lh7x_7seg_read_raw_display_msb(); + msb = raw_val_to_val(raw_msb); + + return(msb); +} + +/********************************************************************** +* Function: lh7x_7seg_write_raw_display +* Function: lh7x_7seg_write_raw_display_lsb +* Function: lh7x_7seg_write_raw_display_msb +**********************************************************************/ +void lh7x_7seg_write_raw_display(uint16_t raw_val) +{ + sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; + + vdprintk("lh7x_7seg_write_raw_display(0x%04X)\n", raw_val); + /* + * NOTE: The device does not read so we have to remember... + */ + sevenSegmentContext->currentRawVal = raw_val; + cpld->seven_seg = raw_val; + + return; +} + +void lh7x_7seg_write_raw_display_lsb(u_char raw_lsb) +{ + uint16_t raw_val; + + raw_val = lh7x_7seg_read_raw_display(); + raw_val &= 0xFF00; + raw_val &= ((uint16_t)raw_lsb) & 0x00FF; + lh7x_7seg_write_raw_display(raw_val); + + return; +} + +void lh7x_7seg_write_raw_display_msb(u_char raw_msb) +{ + uint16_t raw_val; + + raw_val = lh7x_7seg_read_raw_display(); + raw_val &= 0x00FF; + raw_val &= (((uint16_t)raw_msb) << 8) & 0xFF00; + lh7x_7seg_write_raw_display(raw_val); + + return; +} + +/********************************************************************** +* Function: lh7x_7seg_write_display +* Function: lh7x_7seg_write_display_lsb +* Function: lh7x_7seg_write_display_msb +* Function: lh7x_7seg_write_display_str +**********************************************************************/ +void lh7x_7seg_write_display(uint16_t val) +{ + u_char raw_lsb, lsb; + u_char raw_msb, msb; + uint16_t raw_val; + + lsb = (u_char)( val & 0xFF); + msb = (u_char)((val >> 8) & 0xFF); + raw_lsb = val_to_raw_val(lsb); + raw_msb = val_to_raw_val(msb); + raw_val = (uint16_t)((raw_msb << 8) | raw_lsb); + lh7x_7seg_write_raw_display(raw_val); + + return; +} + +void lh7x_7seg_write_display_lsb(u_char lsb) +{ + u_char raw_lsb; + + raw_lsb = val_to_raw_val(lsb); + lh7x_7seg_write_raw_display_lsb(raw_lsb); + + return; +} + +void lh7x_7seg_write_display_msb(u_char msb) +{ + u_char raw_msb; + + raw_msb = val_to_raw_val(msb); + lh7x_7seg_write_raw_display_msb(raw_msb); + + return; +} + +void lh7x_7seg_write_display_str(u_char *str) +{ + uint16_t val; + uint16_t c16; + u_char c; + + if (str) { + /* This is basically a read, shift, write lsb loop */ + for ( ; *str; str++) { + c = *str; + if (c == '\n') continue; + if (c == '\r') continue; + val = lh7x_7seg_read_display(); + val <<= 8; + val &= 0xFF00; + c16 = c & 0x00FF; + val |= c16; + lh7x_7seg_write_display(val); + } + } + return; +} + +/********************************************************************** +* Function: sevenSegment_read +* Function: sevenSegment_poll +* Function: sevenSegment_open +* Function: sevenSegment_fasync +* Function: sevenSegment_release +* ************************************ +* *** User space driver interfaces *** +* ************************************ +**********************************************************************/ + +/* +* NOTE: The read algorithm is wide open for interpretation. +* I am not sure what the behaviour ought to be here. +*/ +static ssize_t sevenSegment_read(struct file *filp, char *buffer, + size_t _count, loff_t *ppos) +{ + sevenSegmentContext_t *sevenSegmentContext = filp->private_data; + DECLARE_WAITQUEUE(wait, current); + ssize_t sizeRead = 0; + char *ptr = buffer; + int err = 0; + int count = (int)_count; + uint16_t c16; + u_char c; + int dataSize; + int dataByteCount; + + switch (sevenSegmentContext->accessMode) { + case ACCESSMODE_LSB: + case ACCESSMODE_MSB: + dataSize = 8; + break; + case ACCESSMODE_SHIFT: + default: + dataSize = 16; + break; + } + dataByteCount = dataSize / 8; + + add_wait_queue(&sevenSegmentContext->read_and_write_wait, &wait); + while (count >= dataByteCount) { + err = -ERESTARTSYS; + if (signal_pending(current)) + break; + /* NOTE: We always have data */ + switch (sevenSegmentContext->accessMode) { + case ACCESSMODE_LSB: + c = lh7x_7seg_read_display_lsb(); + break; + case ACCESSMODE_MSB: + c = lh7x_7seg_read_display_msb(); + break; + case ACCESSMODE_SHIFT: + default: + c16 = lh7x_7seg_read_display(); + /* Flip the bytes so they get returned in the correct order */ + c = (u_char)(c16 >> 8); + c16 = ((c16 << 8) & 0xFF00) | ((uint16_t)c); + break; + } + if (dataSize == 8) { + err = copy_to_user(ptr, &c, sizeof(c)); + if (err) + break; + ptr += sizeof(c); + count -= sizeof(c); + } else /* (dataSize == 16) */ { + err = copy_to_user(ptr, &c16, sizeof(c16)); + if (err) + break; + ptr += sizeof(c16); + count -= sizeof(c16); + } + } + remove_wait_queue(&sevenSegmentContext->read_and_write_wait, &wait); + sizeRead = (ptr == buffer ? err : ptr - buffer); + return(sizeRead); +} + +static ssize_t sevenSegment_write(struct file *filp, const char *buffer, + size_t _count, loff_t *ppos) +{ + sevenSegmentContext_t *sevenSegmentContext = filp->private_data; + ssize_t sizeWritten = 0; + const char *ptr = buffer; + int count; + u_char c; + uint16_t c16; + uint16_t val; + int err = 0; + + for (count = (int)_count; count > 0; count--) { + /* NOTE: We always have room for the data */ + get_user(c, ptr++); + /* Ignore new_line or carriage_return characters */ + if (c == '\n') continue; + if (c == '\r') continue; + vdprintk("JMG: (e:%d, r:%d, a:%d) Attempting to write (%c) == (0x%02X)\n", + sevenSegmentContext->inEscape, + sevenSegmentContext->rawData, + sevenSegmentContext->accessMode, + c, c); + if (sevenSegmentContext->inEscape) { + sevenSegmentContext->inEscape = 0; + if ( c != ESCAPE ) { + switch (c) { + case 'r': /* Raw Data */ + case 'R': /* Raw Data */ + sevenSegmentContext->rawData = 1; + break; + case 'c': /* Coooked Data */ + case 'C': /* Coooked Data */ + sevenSegmentContext->rawData = 0; + break; + case 'l': /* LSB */ + case 'L': /* LSB */ + sevenSegmentContext->accessMode = ACCESSMODE_LSB; + break; + case 'm': /* MSB */ + case 'M': /* MSB */ + sevenSegmentContext->accessMode = ACCESSMODE_MSB; + break; + case 's': /* Shift */ + case 'S': /* Shift */ + case 'n': /* Normal */ + case 'N': /* Normal */ + default: + sevenSegmentContext->accessMode = ACCESSMODE_SHIFT; + } + continue; + } + } else if ( c == ESCAPE ) { + sevenSegmentContext->inEscape = 1; + continue; + } + if (sevenSegmentContext->rawData) { + val = lh7x_7seg_read_raw_display(); + } else { + val = lh7x_7seg_read_display(); + } + switch (sevenSegmentContext->accessMode) { + case ACCESSMODE_LSB: + val &= 0xFF00; + c16 = c & 0x00FF; + val |= c16; + break; + case ACCESSMODE_MSB: + val &= 0x00FF; + c16 = ((uint16_t)c << 8) & 0xFF00; + val |= c16; + break; + case ACCESSMODE_SHIFT: + default: + val <<= 8; + val &= 0xFF00; + c16 = c & 0x00FF; + val |= c16; + break; + } + vdprintk("JMG: Writing (0x%04X)\n", val); + if (sevenSegmentContext->rawData) { + lh7x_7seg_write_raw_display(val); + } else { + lh7x_7seg_write_display(val); + } + } + filp->f_dentry->d_inode->i_mtime = CURRENT_TIME; + sizeWritten = (ptr == buffer ? err : ptr - buffer); + return(sizeWritten); +} + +static unsigned int sevenSegment_poll(struct file *filp, poll_table *wait) +{ + sevenSegmentContext_t *sevenSegmentContext = filp->private_data; + /* We ALWAYS have data waiting ;) */ + int sts = POLLIN | POLLRDNORM; + poll_wait(filp, &sevenSegmentContext->read_and_write_wait, wait); + return(sts); +} + +static int sevenSegment_open(struct inode *inode, struct file *filp) +{ + sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; + int sts = 0; + filp->private_data = sevenSegmentContext; + return(sts); +} + +static int sevenSegment_fasync(int fd, struct file *filp, int on) +{ + sevenSegmentContext_t *sevenSegmentContext = filp->private_data; + int sts; + sts = fasync_helper(fd, filp, on, &sevenSegmentContext->fasync); + return(sts); +} + +static int sevenSegment_release(struct inode *inode, struct file *filp) +{ + lock_kernel(); + sevenSegment_fasync(-1, filp, 0); + unlock_kernel(); + return(0); +} + +/********************************************************************** +* Define (fill in) the user space file operations for this driver +* and initialize the Seven Segment driver as a "miscdevice": +* Character device +* Major(10) --- Non-serial mice, misc features +* Minor(21) --- /dev/7seg (7-segment display) +**********************************************************************/ +static struct file_operations sevenSegment_fops = { +owner: THIS_MODULE, +read: sevenSegment_read, +write: sevenSegment_write, +poll: sevenSegment_poll, +open: sevenSegment_open, +fasync: sevenSegment_fasync, +release: sevenSegment_release, +}; + +static struct miscdevice sevenSegment_dev = { +minor: 21, +name: "7seg", +fops: &sevenSegment_fops, +}; + +/********************************************************************** +* Function: lh7x_7seg_init +* +* Purpose: +* Register & Initialize the module +**********************************************************************/ +static int lh7x_7seg_init(void) +{ + sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; + int sts = 0; + dprintk("ENTER: lh7x_7seg_init()\n"); + init_waitqueue_head(&sevenSegmentContext->read_and_write_wait); + sts = misc_register(&sevenSegment_dev); + lh7x_7seg_write_display_str((u_char *)"HI"); + dprintk("LEAVE: lh7x_7seg_init(%d)\n", sts); + return(sts); +} + +/********************************************************************** +* Function: lh7x_7seg_exit +* +* Purpose: +* Un-Register & Cleanup the module +**********************************************************************/ +static void lh7x_7seg_exit(void) +{ + dprintk("ENTER: lh7x_7seg_exit()\n"); + misc_deregister(&sevenSegment_dev); + lh7x_7seg_write_display_str((u_char *)"BY"); + dprintk("LEAVE: lh7x_7seg_exit()\n"); + return; +} + +module_init(lh7x_7seg_init); +module_exit(lh7x_7seg_exit); + +MODULE_AUTHOR("Jim Gleason / Lineo, Inc."); +MODULE_DESCRIPTION("Seven Segment Display Driver for Sharp LH7x EVB"); +MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/sci-lh7a400.c linux-2.4.21-rmk1-lh7a400/drivers/misc/sci-lh7a400.c --- linux-2.4.21-rmk1/drivers/misc/sci-lh7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/sci-lh7a400.c Thu Oct 16 16:59:38 2003 @@ -0,0 +1,1476 @@ +/* +* linux/drivers/misc/sci-lh7a4500.c +* +* Provide SCI (Smart Card Interface) access/control for the LH7A400 +* +* Copyright (C) 2002 Embedix, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License (GPL) version 2 +* as published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "LH7A400 SCI" +#include + +static sciRegs_t *sci = (sciRegs_t *)IO_ADDRESS(SCI_PHYS); +static clkscRegs_t *clksc = (clkscRegs_t *)IO_ADDRESS(CLKSC_PHYS); + +extern uint32_t hclkfreq_get(void); + +#define DRIVER_VERSION "0.01" +#define LH7A400_SCI_MINOR 24 + + +static struct fasync_struct *sci_async_queue; +static DECLARE_WAIT_QUEUE_HEAD(sci_wait); + +extern spinlock_t sci_lock; + +/***************************************************************************** +* Initialization Values +*****************************************************************************/ +#define SCI_CLOCK_FREQUENCY 1000000 /* SCI Clock Frequency */ +#define SCI_BAUD_RATE 2400 +#define CARD_DEBOUNCE 7 /* Approx 136mSec (1/ .136) */ +#define CR0_INIT 0 +#define CR1_INIT (SCI_CR1_ATRDEN | SCI_CR1_CLKZ1) +#define CR2_INIT 0 +#define IER_INIT 0 +#define DSTAT_INIT 0 +// #define ETU_INIT 9600 /* Initial ETU should be 104uSec */ +// #define CYCLES_INIT 10 /* Start with a setting of 10 */ +#define DTIME_MAX 3415 /* (1 / 0.8mSec) / 3 */ +#define ATIME_INIT 42000 /* Must be between 40000 & 45000 */ +#define ATRS_INIT 40000 /* Max of 40000 */ +#define ATRD_INIT 19200 /* Measured in ETU's */ +#define CHTIME_MAX 9600 /* Measured in ETU's */ +#define DIRECT_MODE 0x3B /* Normal non-inverted data mode */ +#define INVERSE_MODE 0x3F /* Inverted backwards data mode */ + +/***************************************************************************** +* Useful Macros +*****************************************************************************/ +#define SCI_CLKDIV(n) (n & 0xFF) +#define SCI_STABLE(n) (n & 0xFF) +#define SCI_ATRDTIME(n) (n & 0xFFFF) +#define SCI_ATRSTIME(n) (n & 0xFFFF) +#define SCI_CHTIME(n) (n & 0xFFFF) +#define SCI_RXTIME(n) (n & 0xFFFF) +#define SCI_TXRETRY(n) (n & 0x7) +#define SCI_RXRETRY(n) ((n & 0x7) << 3) +#define SCI_TXCOUNTCLR 1 /* Actually any value woll do */ +#define SCI_RXCOUNTCLR 1 /* Actually any value woll do */ +#define SCI_BLKTIME(n) (n & 0xFF) +#define SCI_CHGUARD(n) (n & 0xFF) +#define SCI_BLKGUARD(n) (n & 0xFF) +#define SCI_BAUD(n) (n & 0xFFFF) +#define SCI_VALUE(n) (n & 0xFF) + +static uint32_t lh7a400_sci_atr_chars; +static uint8_t lh7a400_sci_data_from_card[32]; + +/***************************************************************************** +* lh7a400_sci_init_state = 0: NOT initialized +* lh7a400_sci_init_state = 2: Driver initialized +* lh7a400_sci_init_state = 4: Card inserted, ATR sequence initiated +* lh7a400_sci_init_state = 6: Received TS char (Async mode) +* lh7a400_sci_init_state = 8: Received T0 char (Async mode) +* lh7a400_sci_init_state = 10: Received all optional chars (Async mode) +* lh7a400_sci_init_state = 12: ATR complete, card is ready (Async mode) +*****************************************************************************/ +static uint32_t lh7a400_sci_init_state = 0; +#define SCI_INIT_STATE_NOT_INITIALIZED 0 +#define SCI_INIT_STATE_INITIALIZED 2 +#define SCI_INIT_STATE_CARD_INSERTED 4 +#define SCI_INIT_STATE_RECEIVED_TS 6 +#define SCI_INIT_STATE_RECEIVED_T0 8 +#define SCI_INIT_STATE_RECEIVED_ALL 10 +#define SCI_INIT_STATE_ATR_COMPLETE 12 + +/***************************************************************************** +* Map of "Smart Card Interface Memory Map" to sciRegs_t structure +*****************************************************************************/ +#define SCIDATA sci->Data +#define SCICR0 sci->Ctrl0 +#define SCICR1 sci->Ctrl1 +#define SCICR2 sci->Ctrl2 +#define SCIIIER sci->InterruptEnable +#define SCIRETRY sci->Retry +#define SCITIDE sci->TideMark +#define SCITXCOUNT sci->TxCount +#define SCIRXCOUNT sci->RxCount +#define SCIFR sci->FifoStatus +#define SCIRXTIME sci->RxTimeout +#define SCIISTAT sci->Status +#define SCISTABLE sci->Stable +#define SCIATIME sci->ActivationTime +#define SCIDTIME sci->DeactivationTime +#define SCIATRSTIME sci->ATRStartTimeout +#define SCIATRDTIME sci->ATRDurationTimeout +#define SCIBLKTIME sci->BlockTimeout +#define SCICHTIME sci->CharTimeout +#define SCICLKICC sci->ClockICC +#define SCIBAUD sci->Baud +#define SCIVALUE sci->Value +#define SCICHGUARD sci->CharGuardTime +#define SCIBLKGUARD sci->BlockGuardTime +#define SCISYNCCR sci->SyncCR +#define SCISYNCDATA sci->SyncData +#define SCIRAWSTAT sci->RawStatus +#define SCIIIR sci->IrqID_Clear +#define SCIICR sci->IrqID_Clear +#define SCI_CONTROL sci->Control + +static struct +{ + uint8_t char_T0; + uint8_t char_TA[4]; + uint8_t char_TB[4]; + uint8_t char_TC[4]; + uint8_t char_TD[4]; + uint8_t char_HC[15]; +} SCI_CARD_PARAMS; + +/***************************************************************************** +* Function Pre-Declarations +*****************************************************************************/ +static int lh7a400_sci_irq_bit_to_index(uint32_t bit); +static int lh7a400_sci_install_int_handler + (uint32_t bit, int priority, void (*handler(void))); +static void lh7a400_sci_interrupt + (int irq, void *dev_id, struct pt_regs *regs); +static int lh7a400_sci_open + (struct inode *inode, struct file *file); +static int lh7a400_sci_release + (struct inode *inode, struct file *file); +static int lh7a400_sci_fasync + (int fd, struct file *filp, int on); +static unsigned int lh7a400_sci_poll + (struct file *file, poll_table *wait); +static loff_t lh7a400_sci_llseek + (struct file *file, loff_t offset, int origin); +static ssize_t lh7a400_sci_read + (struct file *file, char *buf, size_t count, loff_t *ppos); +static int lh7a400_sci_ioctl + (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int lh7a400_sci_read_proc + (char *page, char **start, off_t off, int count, int *eof, void *data); +static void lh7a400_sci_activate(void); +static void lh7a400_sci_deactivate(void); +static void lh7a400_sci_card_up(void); +static void lh7a400_sci_atr_timeout(void); +static void lh7a400_sci_atr_start_to(void); +static void lh7a400_sci_read_atr_ts(void); +static void lh7a400_sci_read_atr_t0(void); +static void lh7a400_sci_read_atr_op(void); +static void lh7a400_sci_read_atr_hc(void); +static void lh7a400_sci_read_data(void); +static void lh7a400_sci_rx_to(void); +static int lh7a400_sci_init(void); +static void lh7a400_sci_exit(void); + +/***************************************************************************** +* FUNC: vdprintk_status +* NOTE: DEBUG Only +*****************************************************************************/ +#if defined(VERBOSE) && defined(DEBUG) +static void +vdprintk_status(const uint32_t status) +{ + printk("\t\tstatus:"); + if (status & SCI_STATUS_CARDPRESENT) printk(" cardPresent"); + if (status & SCI_STATUS_nSCIDATA_EN) printk(" nDATAEN"); + if (status & SCI_STATUS_nSCIDATAOUT_EN) printk(" nDATAOUTEN"); + if (status & SCI_STATUS_SCICLOCK_OUT) printk(" CLKOUT"); + if (status & SCI_STATUS_nSCICLOCK_EN) printk(" nCLKEN"); + if (status & SCI_STATUS_nSCICLOCKOUT_EN)printk(" nCLKOUTEN"); + if (status & SCI_STATUS_DATA_EN) printk(" DATAEN"); + if (status & SCI_STATUS_CLK_EN) printk(" CLKEN"); + if (status & SCI_STATUS_CRESET) printk(" CRESET"); + if (status & SCI_STATUS_POWER) printk(" POWER"); + printk("\n"); + + return; +} +#else /* defined(VERBOSE) && defined(DEBUG) */ +#define vdprintk_status(status) +#endif /* defined(VERBOSE) && defined(DEBUG) */ + +/***************************************************************************** +* FUNC: vdprintk_fifostatus +* NOTE: DEBUG Only +*****************************************************************************/ +#if defined(VERBOSE) && defined(DEBUG) +static void +vdprintk_fifostatus(const uint32_t status) +{ + printk("\t\tfifoStatus:"); + if (status & SCI_FIFOSTAT_RXFE) printk(" RX-empty"); + if (status & SCI_FIFOSTAT_RXFF) printk(" RX-full"); + if (status & SCI_FIFOSTAT_TXFE) printk(" TX-empty"); + if (status & SCI_FIFOSTAT_TXFF) printk(" TX-full"); + printk("\n"); + + return; +} +#else /* defined(VERBOSE) && defined(DEBUG) */ +#define vdprintk_fifostatus(status) +#endif /* defined(VERBOSE) && defined(DEBUG) */ + +/***************************************************************************** +* FUNC: dprintk_regs +* NOTE: DEBUG Only +*****************************************************************************/ +#if defined(DEBUG) +static void +dprintk_regs(const char *prefix) +{ + sciRegs_t *sci = (sciRegs_t *)IO_ADDRESS(SCI_PHYS); + uint32_t status = sci->Status; + + dprintk("regs(%s):\n", prefix); + printk("\tStatus=%08x\n", status); +#if defined(VERBOSE) + vdprintk_status(status); +#endif /* VERBOSE */ + printk("\tData=%08x\n", sci->Data); + printk("\tCR0=%08x\n", sci->Ctrl0); + printk("\tCR1=%08x\n", sci->Ctrl1); + printk("\tCR2=%08x\n", sci->Ctrl2); + printk("\tInterruptEnable=%08x\n", sci->InterruptEnable); + printk("\tRetry=%08x\n", sci->Retry); + printk("\tTideMark=%08x\n", sci->TideMark); + printk("\tTxCount=%08x\n", sci->TxCount); + printk("\tRxCount=%08x\n", sci->RxCount); + printk("\tFifoStatus=%08x\n", sci->FifoStatus); +#if defined(VERBOSE) + vdprintk_fifostatus(sci->FifoStatus); +#endif /* VERBOSE */ + printk("\tRxTimeout=%08x\n", sci->RxTimeout); + printk("\tStatus=%08x\n", sci->Status); + printk("\tStable=%08x\n", sci->Stable); + printk("\tActivationTime=%08x\n", sci->ActivationTime); + printk("\tDeactivationTime=%08x\n", sci->DeactivationTime); + printk("\tATRStartTimeout=%08x\n", sci->ATRStartTimeout); + printk("\tATRDurationTimeout=%08x\n", sci->ATRDurationTimeout); + printk("\tBlockTimeout=%08x\n", sci->BlockTimeout); + printk("\tCharTimeout=%08x\n", sci->CharTimeout); + printk("\tClockICC=%08x\n", sci->ClockICC); + printk("\tBaud=%08x\n", sci->Baud); + printk("\tValue=%08x\n", sci->Value); + printk("\tCharGuardTime=%08x\n", sci->CharGuardTime); + printk("\tBlockGuardTime=%08x\n", sci->BlockGuardTime); + printk("\tSyncCR=%08x\n", sci->SyncCR); + printk("\tSyncData=%08x\n", sci->SyncData); + printk("\tRawStatus=%08x\n", sci->RawStatus); + // IrqID_Clear (SCIICR) == (SCIIIR) */ + printk("\tIrqID_Clear=%08x\n", sci->IrqID_Clear); + printk("\tControl=%08x\n", sci->Control); + + return; +} +#else /* DEBUG */ +#define dprintk_regs(prefix) +#endif /* DEBUG */ + +/***************************************************************************** +* FUNC: dprintk_irq +* NOTE: DEBUG Only +*****************************************************************************/ +#if defined(DEBUG) +static void +dprintk_irq(uint32_t id) +{ + if (id & SCI_IRQ_TX_TIDE) printk(" tx-tide"); + if (id & SCI_IRQ_RX_TIDE) printk(" rx-tide"); + if (id & SCI_IRQ_RX_TIMEOUT) printk(" rx-timeout"); + if (id & SCI_IRQ_CHAR_TIMEOUT) printk(" char-timeout"); + if (id & SCI_IRQ_BLK_TIMEOUT) printk(" blk-timeout"); + if (id & SCI_IRQ_ATRD_TIMEOUT) printk(" atrd-timeout"); + if (id & SCI_IRQ_ATRS_TIMEOUT) printk(" atrs-timeout"); + if (id & SCI_IRQ_TX_ERROR) printk(" tx-error"); + if (id & SCI_IRQ_POWER_DOWN) printk(" power-down"); + if (id & SCI_IRQ_POWER_UP) printk(" power-up"); + if (id & SCI_IRQ_CARD_OUT) printk(" card-out"); + if (id & SCI_IRQ_CARD_IN) printk(" card-in"); + printk("\n"); + + return; +} +#else /* DEBUG */ +#define dprintk_irq(id) +#endif /* DEBUG */ + +/***************************************************************************** +* Type definitions for the IRQ code... +*****************************************************************************/ +typedef struct +{ + uint32_t bit; + void (*handler)(void); + int priority; +#ifdef DEBUG + char *description; +#endif /* DEBUG */ +} SCI_IRQ; + +#define MAX_SCI_IRQ 11 +static struct { + SCI_IRQ irq[MAX_SCI_IRQ + 1]; + int priority_index[MAX_SCI_IRQ + 1]; +} sci_irq_context; +static int sci_irq_context_initialized; + +#ifdef DEBUG +/***************************************************************************** +* FUNC: sci_irq_index_to_description +*****************************************************************************/ +static char * +sci_irq_index_to_description(int bit_index) +{ + static char *description[MAX_SCI_IRQ + 1] = + { + "INVALID", + "CARD_IN", + "CARD_OUT", + "POWER_UP", + "POWER_DOWN", + "TX_ERROR", + "ATRS_TIMEOUT", + "ATRD_TIMEOUT", + "BLK_TIMEOUT", + "CHAR_TIMEOUT", + "RX_TIMEOUT", + "RX_TIDE", + "TX_TIDE" + }; + + if ((bit_index < 0) || (bit_index > MAX_SCI_IRQ)) { + bit_index = -1; + } + bit_index++; /* Offset by one to account for "INVALID" */ + + return(description[bit_index]); +} +#else +#define sci_irq_index_to_description(n) "" +#endif /* DEBUG */ + +/***************************************************************************** +* FUNC: lh7a400_sci_irq_bit_to_index +*****************************************************************************/ +static int +lh7a400_sci_irq_bit_to_index(uint32_t bit) +{ + int bit_index = -1; + + vdprintk("ENTER: lh7a400_sci_irq_bit_to_index(0x%04X)\n", bit); + switch (bit) { + case SCI_IRQ_CARD_IN: bit_index = 0; break; + case SCI_IRQ_CARD_OUT: bit_index = 1; break; + case SCI_IRQ_POWER_UP: bit_index = 2; break; + case SCI_IRQ_POWER_DOWN: bit_index = 3; break; + case SCI_IRQ_TX_ERROR: bit_index = 4; break; + case SCI_IRQ_ATRS_TIMEOUT: bit_index = 5; break; + case SCI_IRQ_ATRD_TIMEOUT: bit_index = 6; break; + case SCI_IRQ_BLK_TIMEOUT: bit_index = 7; break; + case SCI_IRQ_CHAR_TIMEOUT: bit_index = 8; break; + case SCI_IRQ_RX_TIMEOUT: bit_index = 9; break; + case SCI_IRQ_RX_TIDE: bit_index = 10; break; + case SCI_IRQ_TX_TIDE: bit_index = 11; break; + } + vdprintk("LEAVE: lh7a400_sci_irq_bit_to_index(%d)\n", bit_index); + + return(bit_index); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_install_int_handler +*****************************************************************************/ +static int +lh7a400_sci_install_int_handler (uint32_t bit, int priority, + void (*handler(void))) +{ + int sts = -1; + int bit_index; + int i; +#ifdef DEBUG + char *description; +#endif /* DEBUG */ + + /* Initialize hander information for all available interrupts */ + if (sci_irq_context_initialized == 0) { + sci_irq_context_initialized++; + vdprintk("INIT: lh7a400_sci_install_int_handler()\n"); + for (bit_index = 0; bit_index <= MAX_SCI_IRQ; bit_index++) { + sci_irq_context.irq[bit_index].bit = (1 << bit_index); + sci_irq_context.irq[bit_index].handler = NULL; + sci_irq_context.irq[bit_index].priority = 99999; + sci_irq_context.priority_index[bit_index] = bit_index; + } + } + + /* Install the specified handler information */ + bit_index = lh7a400_sci_irq_bit_to_index(bit); +#ifdef DEBUG + description = sci_irq_index_to_description(bit_index); + vdprintk("ENTER: lh7a400_sci_install_int_handler(b:0x%04X, bi:%d, p:%d, h:0x%08X, d:%s)\n", bit, bit_index, priority, handler, description); +#endif /* DEBUG */ + if ((bit_index >= 0) && (bit_index <= MAX_SCI_IRQ)) { + sci_irq_context.irq[bit_index].handler = handler; + sci_irq_context.irq[bit_index].priority = priority; + sts = 0; + } + /* + * Sort the handler priority list (a list of indexes to the handlers) + * NOTE: Because we always keep this list in order, we can optimize a + * bubble sort by only going UP the list once and DOWN the list once... + */ + for (i = 0; i < MAX_SCI_IRQ; i++) { + int ii = i + 1; + if (sci_irq_context.irq[sci_irq_context.priority_index[i]].priority + > sci_irq_context.irq[sci_irq_context.priority_index[ii]].priority) + { + /* Switch the priority_index(es) */ + int tmp_priority_index = sci_irq_context.priority_index[i]; + sci_irq_context.priority_index[i] = + sci_irq_context.priority_index[ii]; + sci_irq_context.priority_index[ii] = tmp_priority_index; + } + } + for (i = MAX_SCI_IRQ; i > 0; i--) { + int ii = i - 1; + if (sci_irq_context.irq[sci_irq_context.priority_index[i]].priority + < sci_irq_context.irq[sci_irq_context.priority_index[ii]].priority) + { + /* Switch the priority_index(es) */ + int tmp_priority_index = sci_irq_context.priority_index[i]; + sci_irq_context.priority_index[i] = + sci_irq_context.priority_index[ii]; + sci_irq_context.priority_index[ii] = tmp_priority_index; + } + } +#if (0) + dprintk("priority_index: "); + for (i = 0; i <= MAX_SCI_IRQ; i++) { + printk(" <%d:%d>", + sci_irq_context.priority_index[i], + sci_irq_context.irq[sci_irq_context.priority_index[i]].priority); + } + printk("\n"); +#endif /* (0) */ + vdprintk("LEAVE: lh7a400_sci_install_int_handler()\n"); + + return(sts); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_interrupt +* +* *************************************** +* ***** IRQ Bit, Priority, Function ***** +* *************************************** +* +*****************************************************************************/ +static void +lh7a400_sci_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + uint32_t irq_bits = sci->IrqID_Clear; + int priority_index; + int bit_index; + uint32_t bit; + void (*handler)(void); + // int priority; +#ifdef DEBUG + char *description; +#endif /* DEBUG */ + +#ifdef VERBOSE + vdprintk("ENTER: lh7a400_sci_interrupt(0x%04X)", irq_bits); + dprintk_irq(irq_bits); +#if (0) + dprintk_regs("irq"); +#endif +#endif /* VERBOSE */ + + /* Make sure we have initialized */ + if (sci_irq_context_initialized == 0) { + lh7a400_sci_install_int_handler(-1, -1, NULL); + } + + for (priority_index = 0; priority_index <= MAX_SCI_IRQ; priority_index++) { + bit_index = sci_irq_context.priority_index[priority_index]; + bit = sci_irq_context.irq[bit_index].bit; + handler = sci_irq_context.irq[bit_index].handler; + // priority = sci_irq_context.irq[bit_index].priority; + if ((irq_bits & bit) && (handler)) { +#ifdef DEBUG + description = sci_irq_index_to_description(bit_index); + dprintk("IRQ: %s\n", description); +#endif /* DEBUG */ + handler(); + } + } + vdprintk("LEAVE: lh7a400_sci_interrupt()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_open +*****************************************************************************/ +static int +lh7a400_sci_open(struct inode *inode, struct file *file) +{ + dprintk("ENTER: lh7a400_sci_open()\n"); +#if NEVER + if (test_and_set_bit(1, &sci_status)) + return -EBUSY; + sci_irq_data = 0; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_open()\n"); + + return 0; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_release +*****************************************************************************/ +static int +lh7a400_sci_release(struct inode *inode, struct file *file) +{ + dprintk("ENTER: lh7a400_sci_release()\n"); +#if NEVER + spin_lock_irq(&sci_lock); + rtcregs->u.eoi = 1; + spin_unlock_irq(&sci_lock); + sci_status = 0; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_release()\n"); + + return 0; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_fasync +*****************************************************************************/ +static int +lh7a400_sci_fasync(int fd, struct file *filp, int on) +{ + dprintk("ENTER: lh7a400_sci_fasync()\n"); + dprintk("LEAVE: lh7a400_sci_fasync()\n"); + return fasync_helper(fd, filp, on, &sci_async_queue); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_poll +*****************************************************************************/ +static unsigned int +lh7a400_sci_poll(struct file *file, poll_table *wait) +{ + unsigned int retval = 0; + + dprintk("ENTER: lh7a400_sci_poll()\n"); +#if NEVER + poll_wait(file, &sci_wait, wait); + retval = (sci_irq_data) ? 0 : POLLIN | POLLRDNORM; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_poll()\n"); + + return(retval); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_llseek +*****************************************************************************/ +static loff_t +lh7a400_sci_llseek(struct file *file, loff_t offset, int origin) +{ + dprintk("ENTER: lh7a400_sci_llseek()\n"); + dprintk("LEAVE: lh7a400_sci_llseek()\n"); + return -ESPIPE; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read +*****************************************************************************/ +static ssize_t +lh7a400_sci_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + ssize_t retval; + + dprintk("ENTER: lh7a400_sci_read(file=0x%p, buf=0x%p, count=%d, ppos=0x%p)\n", file, buf, count, ppos); + +#if NEVER + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&sci_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + for (;;) { + spin_lock_irq(&sci_lock); + data = sci_irq_data; + if (data != 0) { + sci_irq_data = 0; + break; + } + spin_unlock_irq(&sci_lock); + + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + + schedule(); + } + + spin_unlock_irq(&sci_lock); + + data -= 0x100; /* the first IRQ wasn't actually missed */ + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + +out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&sci_wait, &wait); +#else + retval = 0; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_read()\n"); + return(retval); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_ioctl +*****************************************************************************/ +static int +lh7a400_sci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int retval; + + dprintk("ENTER: lh7a400_sci_ioctl()\n"); +#if NEVER + struct sci_time tm, tm2; + + switch (cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&sci_lock); + rtcregs->u.stat = 0; + rtcregs->cr = ~RTCR_MIE; + sci_irq_data = 0; + spin_unlock_irq(&sci_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&sci_lock); + rtcregs->u.stat = 0; + rtcregs->cr = RTCR_MIE; + sci_irq_data = 0; + spin_unlock_irq(&sci_lock); + return 0; + case RTC_UIE_OFF: + case RTC_UIE_ON: + case RTC_PIE_OFF: + case RTC_PIE_ON: + return -EINVAL; + + case RTC_ALM_READ: + decodetime(rtcregs->mr, &tm); + break; + case RTC_ALM_SET: + if (copy_from_user(&tm2, (struct sci_time*)arg, sizeof(tm2))) + return -EFAULT; + decodetime(rtcregs->dr, &tm); + if ((unsigned)tm2.tm_hour < 24) + tm.tm_hour = tm2.tm_hour; + if ((unsigned)tm2.tm_min < 60) + tm.tm_min = tm2.tm_min; + if ((unsigned)tm2.tm_sec < 60) + tm.tm_sec = tm2.tm_sec; + rtcregs->mr = encodetime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return 0; + case RTC_RD_TIME: + decodetime(rtcregs->dr, &tm); + break; + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + if (copy_from_user(&tm, (struct sci_time*)arg, sizeof (tm))) + return -EFAULT; + tm.tm_year += 1900; + if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 || + tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] + + (tm.tm_mon == 1 && is_leap(tm.tm_year))) || + (unsigned)tm.tm_hour >= 24 || + (unsigned)tm.tm_min >= 60 || + (unsigned)tm.tm_sec >= 60) + return -EINVAL; + rtcregs->clr = encodetime(tm.tm_year, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return 0; + case RTC_IRQP_READ: + case RTC_IRQP_SET: + return -EINVAL; + case RTC_EPOCH_READ: + return put_user(epoch, (unsigned long *)arg); + default: + return -EINVAL; + } + retval = copy_to_user((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0; +#else + retval = 0; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_ioctl()\n"); + return(retval); +} + +/***************************************************************************** +* DATA: lh7a400_sci_fops +*****************************************************************************/ +static struct file_operations lh7a400_sci_fops = { + owner: THIS_MODULE, + llseek: lh7a400_sci_llseek, + read: lh7a400_sci_read, + poll: lh7a400_sci_poll, + ioctl: lh7a400_sci_ioctl, + open: lh7a400_sci_open, + release: lh7a400_sci_release, + fasync: lh7a400_sci_fasync, +}; + +/***************************************************************************** +* DATA: lh7a400_sci_miscdev +*****************************************************************************/ +static struct miscdevice lh7a400_sci_miscdev = { + LH7A400_SCI_MINOR, + "SmartCard(sci)", + &lh7a400_sci_fops +}; + +/***************************************************************************** +* FUNC: lh7a400_sci_read_proc +*****************************************************************************/ +static int +lh7a400_sci_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int retval; +#if NEVER + char *p = page; + int len; + struct sci_time tm; +#endif // NEVER + + dprintk("ENTER: lh7a400_sci_read_proc(page=0x%p, start=0x%p, " + "off=%d, count=%d, ...)\n", page, start, (int)off, count); + +#if NEVER + decodetime(rtcregs->dr, &tm); + p += sprintf(p, "dr\t\t: %d\n" + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04d\n", + rtcregs->dr, + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); + decodetime(rtcregs->mr, &tm); + p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n" + "alrm_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + p += sprintf(p, "update_IRQ\t: %s\n", (rtcregs->u.stat) ? "yes" : "no"); + p += sprintf(p, "periodic_freq\t: %ld\n", sci_freq); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + retval = len; +#else + retval = 0; +#endif // NEVER + dprintk("LEAVE: lh7a400_sci_read_proc()\n"); + return(retval); +} + +/***************************************************************************** +* FUNC: sci_session_if_config +* +* Purpose: Reconfigures the SCI for normal communication based on +* parameter returned during ATR sequence. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: Need to finish this function!!! +*****************************************************************************/ +static void +sci_session_if_config(void) +{ + vdprintk("ENTER: sci_session_if_config()\n"); + sci->TideMark = SCI_TIDE_RX(7); + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 2, lh7a400_sci_read_data); + sci->InterruptEnable &= ~(SCI_IRQ_ATRS_TIMEOUT | SCI_IRQ_ATRD_TIMEOUT); + vdprintk("LEAVE: sci_session_if_config()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_activate +* +* Purpose: To activate the SCI interface when a Smart card is inserted. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: None +*****************************************************************************/ +static void +lh7a400_sci_activate(void) +{ + vdprintk("ENTER: lh7a400_sci_activate()\n"); + /* Disable SCI_IRQ_CARD_IN, and Enable SCI_IRQ_CARD_OUT */ + sci->InterruptEnable &= ~SCI_IRQ_CARD_IN; + sci->InterruptEnable |= SCI_IRQ_CARD_OUT; + /* + * Clear SCI_IRQ_CARD_IN. + * SCI_IRQ_CARD_IN doesn't clear by just doing + * "sci->IrqID_Clear = SCI_IRQ_CARD_IN;" + * it also needs the card "activated". + */ + sci->IrqID_Clear = SCI_IRQ_CARD_IN; + /* Clear direction mode (enable RECEIVE) */ + sci->Ctrl1 &= ~SCI_CR1_MODE_TX; + sci->Ctrl2 = SCI_CR2_STARTUP; + sci->TideMark = (SCI_TIDE_TX(0) | SCI_TIDE_RX(0)); + sci->InterruptEnable |= SCI_IRQ_RX_TIDE; + lh7a400_sci_init_state = SCI_INIT_STATE_CARD_INSERTED; + vdprintk("LEAVE: lh7a400_sci_activate()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_deactivate +* +* Purpose: When the SCI card removed interrupt goes active, or when a +* user requests that the card be deactivated, initiate the +* deactivation sequence, and disable the card removed +* interrupt. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: The deactivation sequence must complete within one millisecond +* of card removal detection, or damage to the card may result. +*****************************************************************************/ +static void +lh7a400_sci_deactivate(void) +{ + vdprintk("ENTER: lh7a400_sci_deactivate()\n"); + /* Disable SCI_IRQ_CARD_OUT, and Enable SCI_IRQ_CARD_IN */ + sci->InterruptEnable &= ~SCI_IRQ_CARD_OUT; + sci->InterruptEnable |= SCI_IRQ_CARD_IN; + /* + * Clear SCI_IRQ_CARD_OUT. + * SCI_IRQ_CARD_OUT doesn't clear by just doing + * "sci->IrqID_Clear = SCI_IRQ_CARD_OUT;" + * it also needs the card "deactivated". + */ + sci->IrqID_Clear = SCI_IRQ_CARD_OUT; +#ifdef SHARP_STUFF + sci->Ctrl2 = SCI_CR2_FINISH; + //sci->InterruptEnable &= ~(SCI_IRQ_CARD_OUT); + lh7a400_sci_init_state = SCI_INIT_STATE_INITIALIZED; + mdelay(1); + lh7a400_sci_init(); +#endif /* SHARP_STUFF */ + vdprintk("LEAVE: lh7a400_sci_deactivate()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_card_up +* +* Purpose: To configure the SCI interface when a Smart card has been +* activated. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: Enables the Card Out interrupt. +*****************************************************************************/ +static void +lh7a400_sci_card_up(void) +{ + vdprintk("ENTER: lh7a400_sci_card_up()\n"); + sci->IrqID_Clear = SCI_IRQ_POWER_UP; + sci->InterruptEnable |= SCI_IRQ_CARD_OUT; + lh7a400_sci_init_state = SCI_INIT_STATE_ATR_COMPLETE; + vdprintk("LEAVE: lh7a400_sci_card_up()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_atr_timeout +* +* Purpose: +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_atr_timeout(void) +{ + vdprintk("ENTER: lh7a400_sci_atr_timeout()\n"); + sci->IrqID_Clear = SCI_IRQ_ATRD_TIMEOUT; + sci->InterruptEnable &= ~(SCI_IRQ_ATRS_TIMEOUT); + lh7a400_sci_deactivate(); + vdprintk("LEAVE: lh7a400_sci_atr_timeout()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_atr_start_to +* +* Purpose: +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_atr_start_to(void) +{ + vdprintk("ENTER: lh7a400_sci_atr_start_to()\n"); + sci->IrqID_Clear = SCI_IRQ_ATRD_TIMEOUT; + sci->InterruptEnable &= ~(SCI_IRQ_ATRS_TIMEOUT); + lh7a400_sci_deactivate(); + vdprintk("LEAVE: lh7a400_sci_atr_start_to()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read_atr_ts +* +* Purpose: To check the TS character received from the SCI interface +* to determine what data mode the Smart card uses. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: Reads the TS char, and if a correct char is read, set the +* correct data mode, increase the FIFO watermark, and replace +* the ISR with the next stage handler. +*****************************************************************************/ +static void +lh7a400_sci_read_atr_ts(void) +{ + uint32_t ts_char; + + vdprintk("ENTER: lh7a400_sci_read_atr_ts()\n"); + dprintk_regs("read_atr_ts"); + if (sci->RxCount > 0) { + vdprintk("RxCount = %d\n", sci->RxCount); + ts_char = (uint8_t) sci->Data; + if (ts_char == DIRECT_MODE) { + // vdprintk("Using DIRECT Mode"); + sci->Ctrl0 = CR0_INIT; + } else if (ts_char == INVERSE_MODE) { + // vdprintk("Using INVERSE Mode"); + sci->Ctrl0 = (CR0_INIT | SCI_CR0_SENSE | SCI_CR0_ORDER); + } else { + /* This is a good place to add Sync mode init/id code*/ + // lh7a400_sci_deactivate(); --- Just ignore it - JMG + vdprintk("LEAVE: lh7a400_sci_read_atr_ts(UnknownMode:0x%02X)\n", + ts_char); + return; + } + lh7a400_sci_init_state = SCI_INIT_STATE_RECEIVED_TS; + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 2, + lh7a400_sci_read_atr_t0); + sci->InterruptEnable |= SCI_IRQ_ATRD_TIMEOUT; + vdprintk("LEAVE: lh7a400_sci_read_atr_ts(%s:0x%02X)\n", + ((ts_char == DIRECT_MODE) ? + "DirectMode":"InverseMode"), ts_char); + } else { + vdprintk("LEAVE: lh7a400_sci_read_atr_ts(Nothing read)\n"); + } + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read_atr_t0 +* +* Purpose: To check the T0 character received from the SCI interface +* to determine the additional configuration for the interface. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_read_atr_t0(void) +{ + uint32_t temp; + + vdprintk("ENTER: lh7a400_sci_read_atr_t0()\n"); + SCI_CARD_PARAMS.char_T0 = (uint8_t) sci->Data; + SCI_CARD_PARAMS.char_TD[0] = (SCI_CARD_PARAMS.char_T0 & 0xF0); + lh7a400_sci_atr_chars = 0; + for (temp = 0x10; temp < 0x100; temp <<= 1) { + if (SCI_CARD_PARAMS.char_T0 & temp) { + lh7a400_sci_atr_chars++; + } + } + if (lh7a400_sci_atr_chars) { + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 2, + lh7a400_sci_read_atr_op); + } else { + lh7a400_sci_atr_chars = (SCI_CARD_PARAMS.char_T0 && 0xF); + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 2, + lh7a400_sci_read_atr_hc); + } + lh7a400_sci_init_state = SCI_INIT_STATE_RECEIVED_T0; + vdprintk("LEAVE: lh7a400_sci_read_atr_t0()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read_atr_op +* +* Purpose: To check the T0 character received from the SCI interface +* to determine the additional configuration for the interface. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_read_atr_op(void) +{ + static uint32_t opt_chars; + uint32_t temp, data; + + vdprintk("ENTER: lh7a400_sci_read_atr_op()\n"); + data = sci->Data; + if (lh7a400_sci_init_state == SCI_INIT_STATE_RECEIVED_T0) { + opt_chars = 0; + } + if (lh7a400_sci_atr_chars) { + if (SCI_CARD_PARAMS.char_TD[opt_chars] & 0x10) { + SCI_CARD_PARAMS.char_TA[opt_chars] = (uint8_t) data; + SCI_CARD_PARAMS.char_TD[opt_chars] &= ~(0x10); + lh7a400_sci_atr_chars--; + } else if (SCI_CARD_PARAMS.char_TD[opt_chars] & 0x20) { + SCI_CARD_PARAMS.char_TB[opt_chars] = (uint8_t) data; + SCI_CARD_PARAMS.char_TD[opt_chars] &= ~(0x20); + lh7a400_sci_atr_chars--; + } else if (SCI_CARD_PARAMS.char_TD[opt_chars] & 0x40) { + SCI_CARD_PARAMS.char_TC[opt_chars] = (uint8_t) data; + SCI_CARD_PARAMS.char_TD[opt_chars] &= ~(0x40); + lh7a400_sci_atr_chars--; + } else if (SCI_CARD_PARAMS.char_TD[opt_chars] & 0x80) { + opt_chars++; + SCI_CARD_PARAMS.char_TD[opt_chars] = (uint8_t) data; + lh7a400_sci_atr_chars--; + for (temp = 0x10; temp < 0x100; temp <<= 1) { + if (SCI_CARD_PARAMS.char_TD[opt_chars] & temp) + { + lh7a400_sci_atr_chars++; + } + } + } + } + if (lh7a400_sci_atr_chars == 0) { + if (SCI_CARD_PARAMS.char_T0 && 0xF != 0) { + lh7a400_sci_atr_chars = SCI_CARD_PARAMS.char_T0 & 0xF; + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 2, + lh7a400_sci_read_atr_hc); + } else { + sci_session_if_config(); + } + } + lh7a400_sci_init_state = SCI_INIT_STATE_RECEIVED_ALL; + vdprintk("LEAVE: lh7a400_sci_read_atr_op()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read_atr_hc +* +* Purpose: To handle the optional "Historical Characters received +* from the SCI interface. Currently these chars are ignored. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_read_atr_hc(void) +{ + static uint32_t hist_chars = 0; + + vdprintk("ENTER: lh7a400_sci_read_atr_hc()\n"); + SCI_CARD_PARAMS.char_HC[hist_chars++] = (uint8_t) sci->Data; + lh7a400_sci_atr_chars--; + if (lh7a400_sci_atr_chars == 0) { + sci_session_if_config(); + } + vdprintk("LEAVE: lh7a400_sci_read_atr_hc()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_read_data +* +* Purpose: +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static void +lh7a400_sci_read_data(void) +{ + uint32_t idx; + + vdprintk("ENTER: lh7a400_sci_read_data()\n"); + for (idx = 0; idx < 8; idx++) { + lh7a400_sci_data_from_card[idx] = (uint8_t) sci->Data; + } + vdprintk("LEAVE: lh7a400_sci_read_data()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_rx_to +* +* Purpose: +* +* Parameters: none +* +* Outputs: nothing +* +* Returns: nothing +* +* Notes: None +*****************************************************************************/ +static void +lh7a400_sci_rx_to(void) +{ + uint32_t idx; + + vdprintk("ENTER: lh7a400_sci_rx_to()\n"); + for (idx = 0; idx < sci->RxCount; idx++) { + lh7a400_sci_data_from_card[idx] = (uint8_t) sci->Data; + } + vdprintk("LEAVE: lh7a400_sci_rx_to()\n"); + + return; +} + +/***************************************************************************** +* FUNC: lh7a400_sci_init +* +* Purpose: Configures the SCI for initial communication. Initializes +* the interrupt handler, and instals ISR's to prepare for +* card insertion. +* +* Parameters: None +* +* Outputs: Nothing +* +* Returns: Nothing +* +* Notes: +*****************************************************************************/ +static int __init +lh7a400_sci_init(void) +{ + int sts = 0; + int refclk; + int sciclk; + int baudPlusOne; + int value; + + dprintk("ENTER: lh7a400_sci_init()\n"); + + lh7a400_sci_init_state = SCI_INIT_STATE_NOT_INITIALIZED; + + /* If we start out and there is already power, reset & wait a moment */ + if (sci->Status & SCI_STATUS_POWER) + { + sci->Ctrl2 = SCI_CR2_WRESET; /* SCI_CR2_FINISH; */ + mdelay(1); + } + + /* + * SCIREFCLK is either HCLK or HCLK/2, + * depending on the SCI_CTL_PREDIV bit + */ + refclk = hclkfreq_get() * 1000; + sci->Control = 0; /* Start out in a known state */ + sci->Control = SCI_CTL_MUX_DETECT /* Enable card detection */ + | SCI_CTL_MUX_VCCEN; /* Enable power */ + if ((clksc->clkset & CLKSET_PCLKDIV4) /* | (refclk > 50000000) */ ) + { + refclk /= 2; + sci->Control |= SCI_CTL_PREDIV; /* Use (HCLK / 2) */ + } + sci->Control |= SCI_CTL_EN; /* Enable the SCI */ + + /* + * Frequency = (SCIREFCLK / ((SCICLKICC + 1) * 2)) + * -so- + * ((SCICLKICC + 1) * 2) = (SCIREFCLK / Frequency) + * -so- + * (SCICLKICC + 1) = ((SCIREFCLK / Frequency) / 2) + * -so- + * SCICLKICC = (((SCIREFCLK / Frequency) / 2) - 1) + */ + sciclk = (((refclk / SCI_CLOCK_FREQUENCY) / 2) - 1); + sci->ClockICC = SCI_CLKDIV(sciclk); + dprintk("SCI_CLK(freq:%d, refclk:%d, clkicc:%d)Hz.\n", + SCI_CLOCK_FREQUENCY, refclk, sciclk); + + sci->Ctrl0 = CR0_INIT; + sci->Ctrl1 = CR1_INIT; + sci->Ctrl2 = CR2_INIT; + sci->InterruptEnable = IER_INIT; + sci->Stable = SCI_STABLE(((refclk / (CARD_DEBOUNCE * 0xFFFF)) - 1)); + + /* + * The pulse width of an etu is one refclk. + * 1 etu = ((baud + 1) * value) / refclk + * 5 <= value <= 0xFF + * 0 <= baud <= 0xFFFF + * + * NOTE: I (JMG) assumed refclk was / 1000 as otherwise the resulting + * "Value" is too large for the register which is only 8-bits in size. + */ + baudPlusOne = SCI_BAUD_RATE + 1; + value = (refclk / 1000) / baudPlusOne; + if (value < 0x05) value = 0x05; + if (value > 0xFF) value = 0xFF; + baudPlusOne = (refclk / 1000) / value; + sci->Baud = SCI_BAUD((baudPlusOne - 1)); + sci->Value = SCI_VALUE(value); + + /* + * SCI_CLOCK derived from SCIREFCLK + * SCIDATA transmit (tx) FIFO drives SCI_IO + */ + sci->SyncCR = 0; + sci->SyncData = SCI_SYNCDR_WCLKEN | SCI_SYNCDR_WDATAEN; + + sci->DeactivationTime = ((refclk / DTIME_MAX) / 3); + sci->ActivationTime = ATIME_INIT; + sci->ATRStartTimeout = (SCI_ATRSTIME(ATRS_INIT)); + sci->ATRDurationTimeout = (SCI_ATRDTIME(ATRD_INIT)); + sci->CharTimeout = SCI_CHTIME(CHTIME_MAX); + sci->RxTimeout = SCI_RXTIME(0xFFFF); + sci->Retry = (SCI_TXRETRY(0) | SCI_RXRETRY(0)); + sci->TxCount = SCI_TXCOUNTCLR; + sci->RxCount = SCI_RXCOUNTCLR; + sci->CharGuardTime = SCI_CHGUARD(1); + sci->Status = DSTAT_INIT; + sci->IrqID_Clear = SCI_IRQ_ALL; + sci->BlockTimeout = SCI_BLKTIME(0); /* ??? JMG ??? */ + sci->BlockGuardTime = SCI_BLKGUARD(0); + sci->TideMark = (SCI_TIDE_TX(0) | SCI_TIDE_RX(0)); + + { + int idx; + SCI_CARD_PARAMS.char_T0 = 0; + SCI_CARD_PARAMS.char_TA[0] = 0x11; + for (idx = 1; idx < 4; idx++) + { + SCI_CARD_PARAMS.char_TA[idx] = 0; + } + for (idx = 0; idx < 4; idx++) + { + SCI_CARD_PARAMS.char_TB[idx] = 0; + } + for (idx = 0; idx < 4; idx++) + { + SCI_CARD_PARAMS.char_TC[idx] = 0; + } + for (idx = 0; idx < 3; idx++) + { + SCI_CARD_PARAMS.char_TD[idx] = 0; + } + for (idx = 0; idx < 16; idx++) + { + SCI_CARD_PARAMS.char_HC[idx] = 0; + } + } + + /******************************************************************** + * The remainder of the init function is for registering as a MISC + * driver, initializing the interrupt handler, and to parse the ATR + * sequence. If a user wants to use a polling method for the ATR parsing, + * the interrupt code below would not be needed. + ********************************************************************/ + + misc_register(&lh7a400_sci_miscdev); + create_proc_read_entry("driver/sci", 0, 0, lh7a400_sci_read_proc, NULL); + + /************************************** + ***** IRQ Bit, Priority, Function ***** + **************************************/ + lh7a400_sci_install_int_handler(SCI_IRQ_CARD_OUT, 0, + lh7a400_sci_deactivate); + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIDE, 1, + lh7a400_sci_read_atr_ts); + lh7a400_sci_install_int_handler(SCI_IRQ_CARD_IN, 2, + lh7a400_sci_activate); + lh7a400_sci_install_int_handler(SCI_IRQ_ATRD_TIMEOUT, 3, + lh7a400_sci_atr_timeout); + lh7a400_sci_install_int_handler(SCI_IRQ_ATRS_TIMEOUT, 4, + lh7a400_sci_atr_start_to); + lh7a400_sci_install_int_handler(SCI_IRQ_RX_TIMEOUT, 5, + lh7a400_sci_rx_to); +#if (0) + lh7a400_sci_install_int_handler(SCI_IRQ_CHAR_TIMEOUT, 6, + XXXXX); + lh7a400_sci_install_int_handler(SCI_IRQ_POWER_UP, 3, + lh7a400_sci_card_up); +#endif + + if (sci->Status & SCI_STATUS_CARDPRESENT) { + sci->InterruptEnable = + (SCI_IRQ_CARD_OUT | SCI_IRQ_ATRS_TIMEOUT); + } else { + sci->InterruptEnable = + (SCI_IRQ_CARD_IN | SCI_IRQ_ATRS_TIMEOUT); + } + + dprintk_regs("init"); + + sts = request_irq(IRQ_SCI, lh7a400_sci_interrupt, SA_INTERRUPT, + "LH7A400 SCI", NULL); + if(sts) { + printk(KERN_ERR "sci: request_irq failed, sts=0x%x.\n", sts); + remove_proc_entry("driver/sci", NULL); + misc_deregister(&lh7a400_sci_miscdev); + return(sts); + } + + if (sci->Status & SCI_STATUS_CARDPRESENT) { + lh7a400_sci_activate(); + } + + printk(KERN_INFO "LH7A400 Smart Card Interface driver v%s\n", + DRIVER_VERSION); + + dprintk("LEAVE: lh7a400_sci_init()\n"); + + return(sts); +} + +/***************************************************************************** +* FUNC: lh7a400_sci_exit +*****************************************************************************/ +static void __exit +lh7a400_sci_exit(void) +{ + dprintk("ENTER: lh7a400_sci_exit()\n"); + free_irq(IRQ_SCI, NULL); + remove_proc_entry("driver/sci", NULL); + misc_deregister(&lh7a400_sci_miscdev); + dprintk("LEAVE: lh7a400_sci_exit()\n"); + + return; +} + +module_init(lh7a400_sci_init); +module_exit(lh7a400_sci_exit); + +MODULE_AUTHOR("Jim Gleason "); +MODULE_DESCRIPTION("Sharp LH7A400 Smart Card Driver (SCI)"); +EXPORT_NO_SYMBOLS; + diff -urN --exclude=CVS --exclude='.*' --exclude='*~' linux-2.4.21-rmk1/drivers/misc/ssp-lh7a400.c linux-2.4.21-rmk1-lh7a400/drivers/misc/ssp-lh7a400.c --- linux-2.4.21-rmk1/drivers/misc/ssp-lh7a400.c Wed Dec 31 19:00:00 1969 +++ linux-2.4.21-rmk1-lh7a400/drivers/misc/ssp-lh7a400.c Sat Oct 18 13:30:10 2003 @@ -0,0 +1,1471 @@ +/* + * linux/drivers/misc/ssp-lh7x.c + * + * Provide SSP (synchronous Serial Port) functionality for LH7x EVB boards + * + * Copyright (C) 2002 Lineo, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPL) version 2 + * as published by the Free Software Foundation. + * + */ + +/* + * I think this could be made generic for any LH7A400 or LH79520, but + * right now it's specific to the two eval boards... + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG +#undef VERBOSE +#define DRVNAME "ssp_lh7x" + +#include + +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +#endif /* MODULE */ + +#include +#include + +#ifdef CONFIG_MACH_KEV79520 +#include +#include +#include +#include +#define IRQ_SSP IRQ_CPLD +#endif + +#ifdef CONFIG_MACH_KEV7A400 +#include +#include +// DDD #include + +#define IRQ_SSP IRQ_KEV7A400_TS + +static int initted = 0; /* set iff init routine has run */ +#endif + +#ifdef CONFIG_CPU_FREQ +#include +#endif + +#include + +#include "ssp.h" + +#define vdprintk if (0) printk +#define dprintk if (0) printk + +static int ssp_lh7x_get_speed(void); +static void ssp_lh7x_write16(sspContext_t *sspContext, unsigned int data); +static unsigned int ssp_lh7x_read16(sspContext_t *sspContext); +static int __init ssp_lh7x_init(void); + +#ifdef CONFIG_MACH_KEV79520 +static gpioARegs_t *gpioa = (gpioARegs_t *)GPIO0_PHYS; +static ioconRegs_t *iocon = (ioconRegs_t *)IOCON_PHYS; +static rcpcRegs_t *rcpc = (rcpcRegs_t *)RCPC_PHYS; +static cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; +#endif + +#ifdef CONFIG_MACH_KEV7A400 +static gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); +#endif + +static sspRegs_t *ssp = (sspRegs_t *)IO_ADDRESS(SSP_BASE); + +/* +* hclk_freq: +* The frequency of the clock that feeds the SSP clock prescaler in the RCPC +* The frequency is in Hz +*/ +static unsigned int hclk_freq = 0; + +#ifdef CONFIG_MACH_KEV79520 +/********************************************************************** +* Additional RCPC defines +**********************************************************************/ +#define rcpc_sspClkControl spareClkCtrl +#define rcpc_sspClkPrescale spare1Prescale + +#define RCPC_LOCK 1 +#define RCPC_LOCKED RCPC_LOCK +#define RCPC_UNLOCK 0 +#define RCPC_UNLOCKED RCPC_UNLOCK +#endif + +/********************************************************************** +* Function: ssp_busy_wait +* Function: ssp_tx_full_wait +* +* Purpose: +* Wait until the state of the SSP busy bit from the status register +* indicates the SSP is no longer busy. +* +* Returns: +* N/A +**********************************************************************/ +static void ssp_busy_wait(void) +{ + while ( ssp->sr & SSP_SR_BSY ) { + barrier(); + } + return; +} + +static void ssp_tx_full_wait(void) +{ + while ( (ssp->sr & SSP_SR_TNF) == 0 ) { + barrier(); + } + return; +} + +/********************************************************************** +* Function: ssp_flush_tx_fifo +* Function: ssp_flush_rx_fifo +* +* Purpose: +* Flush the transmit (tx) and receive (rx) fifo buffer +* +* Returns: +* N/A +**********************************************************************/ +static void ssp_flush_tx_fifo(sspContext_t *sspContext) +{ + int i; + + for (i = sspContext->ts_txTimeout; ((i > 0) && (ssp->sr & SSP_SR_TFE)); i--) + { + barrier(); + } + return; +} + +static void ssp_flush_rx_fifo(sspContext_t *sspContext) +{ + int i; + unsigned int junk; + + for (i = sspContext->ts_rxTimeout; ((i > 0) && (ssp->sr & SSP_SR_RNE)); i--) + { + barrier(); + junk = ssp->dr; + //printk("ssp_flush_rx_fifo(0x%04X)\n", junk); + } + return; +} + +#if defined(CONFIG_MACH_KEV79520) +/********************************************************************** +* Function: ssp_chipselect_enable +* Function: ssp_chipselect_disable +* Function: ssp_chipselect_manual +* Function: ssp_chipselect_automatic +* +* Purpose: +* Controls the chipselect pin associated with the SSP +* +* Returns: +* N/A +* +**********************************************************************/ +static void ssp_chipselect_enable(void) +{ + /* Make the SSPFRM signal (ChipSelect) high (enabled) */ + /* Note: This must have had ssp_chipselect_manual() called first */ + //printk("ssp_chipselect_enable()\n"); + gpioa->dr &= ~(SSPFRM_GPIO_BIT); /* LOW == Enabled */ +} + +static void ssp_chipselect_disable(void) +{ + /* Make the SSPFRM signal (ChipSelect) low (disabled) */ + /* Note: This must have had ssp_chipselect_manual() called first */ + //printk("ssp_chipselect_disable()\n"); + gpioa->dr |= SSPFRM_GPIO_BIT; /* HIGH == Disabled */ +} + +static void ssp_chipselect_manual(void) +{ + /* First, disable the ChipSelect */ + //JMG ssp_chipselect_disable(); + /* Set up muxing so that we manually control the ChipSelect pin */ + /* via GPIO port A bit 2 */ + gpioa->ddr |= SSPFRM_GPIO_BIT; /* Make GPIO an output */ + iocon->SSIMux &= ~SSIMUX_SSPFRM; +} + +static void ssp_chipselect_automatic(void) +{ + /* First, disable the ChipSelect */ + ssp_chipselect_disable(); + /* Set up muxing so the SSP automatically controls the ChipSelect pin */ + iocon->SSIMux |= SSIMUX_SSPFRM; +} +#endif + +#if defined(CONFIG_MACH_KEV7A400) +/********************************************************************** +* Function: ssp_eeprom_busy_poll +* +* Purpose: +* Following a write or erase, wait for the EEPROM busy signal to go high. +* We control the EEPROM chipselect pin by keeping the SSP busy until the +* associated EEPROM BSY signal is no longer asserted. +* +* Processing: +* Following an erase or write command, the EEPROM will signal that the +* write or erase operation is complete by transitioning its data output +* from a 0 to a 1 provided that its chip select is desserted after the +* write command completes and reasserted 500 ns after the chip select +* has been deasserted. SSPFRM cannot be directly controlled as GPIO pin. +* +* This relatively complex algorithm results: +* Convert timeout_ms to units of the time it takes to +* send a single word. Wait for the last SSP transaction +* to complete. Flush the receive FIFO. Wait +* approximately 500 ns. This time is not really +* critical. It can be longer. Write a 0 to the +* transmit FIFO and then keep writing 0 to the transmit +* FIFO until the data read back from the EEPROM is not +* 0. This keeps the EEPROM's chip select asserted while +* we wait for the EEPROM data output to transition from +* 0 to 1. +* +* NOTE: +* BUSY_POLL_METHOD_1 follows the above method as closely as possible +* BUSY_POLL_METHOD_2 does a generic busy wait of timeout_ms +* +* Parameters: +* timeout_ms: number of milliseconds before +* aborting the busy poll operation +* +* Returns: +* 0 if timed out +* 1 otherwise +* +**********************************************************************/ +#undef BUSY_POLL_METHOD_1 /* DOESN'T WORK --- JimG */ +#define BUSY_POLL_METHOD_2 +static int ssp_eeprom_busy_poll(sspContext_t *sspContext, int timeout_ms) +{ + int i; + int timeout_in_words; +#define EEPROM_BITS_PER_SSP_WORD 16 + + // !!! WARNING !!! Printouts mess up the timing + + timeout_in_words = (ssp_lh7x_get_speed() * timeout_ms) + / (EEPROM_BITS_PER_SSP_WORD * 1000); + +#if defined(BUSY_POLL_METHOD_1) + /* wait for SSP to be not busy */ + ssp_busy_wait(); + + /* flush the receive FIFO */ + ssp_flush_rx_fifo(sspContext); + + /* + ** assume 10 ns bus speed. Wait at least 500 ns before + ** checking if write is complete + */ + for (i = 0; i < 50; i++) continue; +#endif /* BUSY_POLL_METHOD_1 */ + + /* keep CS active by keeping data in the transmit buffer */ + ssp_tx_full_wait(); + ssp_lh7x_write16(sspContext, 0); + do + { +#if defined(BUSY_POLL_METHOD_2) + ssp_flush_rx_fifo(sspContext); +#endif /* BUSY_POLL_METHOD_2 */ + ssp_tx_full_wait(); + ssp_lh7x_write16(sspContext, 0); + } +#if defined(BUSY_POLL_METHOD_1) + while (timeout_in_words-- && ssp_lh7x_read16(sspContext) == 0); +#elif defined(BUSY_POLL_METHOD_2) + while (timeout_in_words--); +#endif + + /* wait for SSP to be not busy */ + ssp_busy_wait(); + + /* flush the receive FIFO */ + ssp_flush_rx_fifo(sspContext); + + /* Give the rest of the system a chance to work */ + schedule(); + + /* return success or timeout */ + return (timeout_in_words != 0); +} +#endif + +#ifdef CONFIG_MACH_KEV79520 +/********************************************************************** +* Function: rcpc_lh7x_locked +* +* Purpose: +* Determine write access to the RCPC +* +* Returns: +* The lock state of the RCPC +* +**********************************************************************/ +static int rcpc_lh7x_locked(void) +{ + int lockState; + + vdprintk("ENTER: rcpc_lh7x_locked()\n"); + if (rcpc->control & RCPC_CTRL_WRTLOCK_ENABLED) { + lockState = RCPC_LOCKED; + } else { + lockState = RCPC_UNLOCKED; + } + vdprintk("LEAVE: rcpc_lh7x_locked(%s)\n", + (lockState==RCPC_LOCKED)?"Locked":"UnLocked"); + + return(lockState); +} + +/********************************************************************** +* Function: rcpc_lh7x_lock +* +* Purpose: +* Control write access to the RCPC +* +* Parameters: +* action: RCPC_UNLOCK == can write to RCPC +* RCPC_LOCK == cannot write to RCPC +* +* Returns: +* The previous lock state of the RCPC +* +**********************************************************************/ +static int rcpc_lh7x_lock(int action) +{ + int priorState; + + vdprintk("ENTER: rcpc_lh7x_lock(%s)\n", + (action==RCPC_LOCK)?"Lock":"UnLock"); + priorState = rcpc_lh7x_locked(); + if (action == RCPC_UNLOCK) { + rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; + } else /* (action == RCPC_LOCK) */ { + rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; + } + vdprintk("LEAVE: rcpc_lh7x_lock(%s)\n", + (action==RCPC_LOCK)?"Lock":"UnLock"); + + return(priorState); +} +#endif + + + +/********************************************************************** +* Function: ssp_lh7x_get_speed +* +* Purpose: +* Get the SSP speed in bits per second +**********************************************************************/ +static int ssp_lh7x_get_speed(void) +{ + int bps; +#ifdef CONFIG_MACH_KEV79520 + int rcpc_prescale; +#endif + int ssp_prescale; + int ssp_divider; + + vdprintk("ENTER: ssp_lh7x_get_speed()\n"); +#if defined(CONFIG_MACH_KEV79520) + rcpc_prescale = rcpc->rcpc_sspClkPrescale; + if (rcpc_prescale == 0) rcpc_prescale = 1; + else rcpc_prescale <<= 1; + ssp_prescale = ssp->cpsr; + ssp_divider = (ssp->cr0 & _SBF(8,_BITMASK(8) ) ) >> 8; + bps = hclk_freq / (rcpc_prescale * (ssp_prescale) * (ssp_divider + 1) ); +#elif defined(CONFIG_MACH_KEV7A400) + ssp_prescale = ssp->cpsr; + ssp_divider = (ssp->cr0 & 0xff00) >> 8; + + bps = CLKSC_SSP_CLK / (ssp_prescale * (ssp_divider + 1) ); +#endif + vdprintk("LEAVE: ssp_lh7x_get_speed(%d bps)\n", bps); + + return(bps); +} + +#ifdef CONFIG_MACH_KEV7A400 +/********************************************************************** +* Function: ssp_lh7x_set_speed +* +* Purpose: +* set the SSPCLK frequency as close to the requested bits per second +* as possible and return the actual bits per second. +* +* Processing: +* If the requested bits per second is greater than or equal to +* the maximum possible SSPCLK frequency, set the divider and +* the prescaler to the minimum values. +* +* If not too fast, compute the closest integer result of dividing the +* base sspclk frequency (approximately 7.4 MHz) by the requested +* bits per second. If this quotient is larger than the result +* of multiplying the maximum possible prescaler by the maximum +* possible divider, then the requested clock is too slow. Use +* the maximum possible divider and prescaler to get the slowest +* SSPCLK speed. +* +* If the clock frequency is neither too fast nor too slow, then +* step through all possible prescaler values to determine which +* combination of prescaler and divider values give the SSPCLK +* value closest to the requested bits per second. +* +* Set the SSP clock prescaler register to the prescaler value +* determined above. Clear out the old divider value from SSP +* control register 0 and OR in the new divider value - 1. Return +* the value returned by ssp_get_speed(). +* +* Parameters: +* requested_bits_per_second: the desired frequency of the SSPCLK +* pin in bits per second. +* +* Outputs: None +* +* Returns: +* 0 if the requested frequency is illegal. Otherwise, return +* the actual clock speed. +* +* Notes: +* +**********************************************************************/ + +#define MAX_SSP_FREQ (CLKSC_SSP_CLK / SSP_PRESCALE_MIN) + +static int ssp_lh7x_set_speed(int bps) +{ + int ssp_prescale; + int ssp_divider; + int new_prescale; + int new_divider; + int quotient; + int delta1; + int delta2; + int min_error; + int new_error; + + vdprintk("ENTER: ssp_lh7x_set_speed(%d bps)\n", bps); + + if (bps <= 0) + /* requested frequency is illegal. Return 0 */ + return 0; + + /* get the dividers as close to the requested freq as possible */ + if (bps >= MAX_SSP_FREQ) { + /* requested clock frequency is too fast. Set to max freq */ + ssp_prescale = SSP_PRESCALE_MIN; + ssp_divider = 1; + } else { + /* compute the required divider as close as possible */ + quotient = CLKSC_SSP_CLK / bps; + + /* round the quotient */ + delta1 = bps - (CLKSC_SSP_CLK / quotient ); + if (delta1 < 0) + delta1 = - delta1; + delta2 = bps - (CLKSC_SSP_CLK / (quotient + 1) ); + if (delta2 < 0) + delta2 = - delta2; + if (delta1 > delta2) + quotient++; + + if (quotient >= (SSP_PRESCALE_MAX * SSP_DIVIDER_MAX) ) { + /* + Then requested clock frequency is <= minimum possible. + Make it as slow as possible. + */ + ssp_prescale = SSP_PRESCALE_MAX; + ssp_divider = SSP_DIVIDER_MAX; + } else { + /* + The computed quotient is in range. + quotient is the target clock divide frequency; + get as close as possible + */ + + /* + * factor the quotient into the divider and + * prescaler combo that minimizes the error in + * the quotient by exhaustively searching all + * legal ssp pre