diff options
author | David Anders <dave123@abcsinc.com> | 2006-01-19 13:51:23 +0000 |
---|---|---|
committer | David Anders <dave123@abcsinc.com> | 2006-01-19 13:51:23 +0000 |
commit | 5d46a9bb79cb1430bbb96311ed94dae0a22f30ac (patch) | |
tree | 64da6e1a5d78407e3c80de9fa66bd5b3bac75cf6 /target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80 | |
parent | 64c3f9b0e87be53a0d5dea71f2565234814b1b0f (diff) | |
download | buildroot-novena-5d46a9bb79cb1430bbb96311ed94dae0a22f30ac.tar.gz buildroot-novena-5d46a9bb79cb1430bbb96311ed94dae0a22f30ac.zip |
add Sharp LH79520 based LNode80 target
Diffstat (limited to 'target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80')
-rw-r--r-- | target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80 | 14498 |
1 files changed, 14498 insertions, 0 deletions
diff --git a/target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80 b/target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80 new file mode 100644 index 000000000..7b0be87f0 --- /dev/null +++ b/target/device/Sharp/LNode80/kernel-patches/002-patch-2.4.26-vrs1-lnode80 @@ -0,0 +1,14498 @@ +diff -urN linux-2.4.26/arch/arm/boot/compressed/head.S linux-2.4.26-vrs1-lnode80/arch/arm/boot/compressed/head.S +--- linux-2.4.26/arch/arm/boot/compressed/head.S 2005-11-02 16:54:16.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/boot/compressed/head.S 2005-11-02 17:37:31.000000000 -0400 +@@ -17,6 +17,7 @@ + * 100% relocatable. Any attempt to do so will result in a crash. + * Please select one of the following when turning on debugging. + */ ++#define DEBUG + #ifdef DEBUG + #if defined(CONFIG_DEBUG_DC21285_PORT) + .macro loadsp, rb +@@ -81,6 +82,20 @@ + */ + str \rb, [r3, #0x14] @ UTDR + .endm ++#elif 1 /* Sharp LH79520-type */ ++ .macro loadsp, rb ++ ldr \rb, =0xfffc0000 @ UART1 base ++ .endm ++ .macro writeb, rb ++ strb \rb, [r3, #0] ++ .endm ++#elif 0 /* Sharp LH7A400-type */ ++ .macro loadsp, rb ++ ldr \rb, =0x80000700 @ UART1 base ++ .endm ++ .macro writeb, rb ++ strb \rb, [r3, #0] ++ .endm + #else + #error no serial architecture defined + #endif +@@ -97,6 +112,7 @@ + bl phex + .endm + ++#undef DEBUG + .macro debug_reloc_start + #ifdef DEBUG + kputc #'\n' +@@ -140,7 +156,9 @@ + .word 0x016f2818 @ Magic numbers to help the loader + .word start @ absolute load/run zImage address + .word _edata @ zImage end address +-1: mov r7, r1 @ save architecture ID ++1: @mov r7, r1 @ save architecture ID ++ mov r7, #0x300 ++ orr r7,r7,#0xe7 + mov r8, #0 @ save r0 + + #ifndef __ARM_ARCH_2__ +@@ -314,6 +332,11 @@ + LC1: .word reloc_end - reloc_start + .size LC0, . - LC0 + ++ .type proc_lh7a400_type,#object ++proc_lh7a400_type: ++ .word 0x41029220 ++ .size proc_lh7a400_type, . - proc_lh7a400_type ++ + /* + * Turn on the cache. We need to setup some page tables so that we + * can have both the I and D caches on. +diff -urN linux-2.4.26/arch/arm/boot/Makefile linux-2.4.26-vrs1-lnode80/arch/arm/boot/Makefile +--- linux-2.4.26/arch/arm/boot/Makefile 2003-08-25 07:44:39.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/boot/Makefile 2005-11-02 17:37:31.000000000 -0400 +@@ -101,6 +101,24 @@ + INITRD_VIRT = 0x0C800000 + endif + ++ifeq ($(CONFIG_ARCH_LH79520),y) ++ ZTEXTADDR = 0x20008000 ++ ZBSSADDR = 0x20200000 ++ ZRELADDR = 0x20008000 ++ INITRD_PHYS = 0x20400000 ++ INITRD_VIRT = 0xC0400000 ++ PARAMS_PHYS = 0x20110000 ++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 linux-2.4.26/arch/arm/config.in linux-2.4.26-vrs1-lnode80/arch/arm/config.in +--- linux-2.4.26/arch/arm/config.in 2005-11-02 16:54:16.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/config.in 2005-11-02 17:37:31.000000000 -0400 +@@ -48,6 +48,8 @@ + RiscPC CONFIG_ARCH_RPC \ + RiscStation CONFIG_ARCH_RISCSTATION \ + SA1100-based CONFIG_ARCH_SA1100 \ ++ LH79520-based CONFIG_ARCH_LH79520 \ ++ LH7A400-based CONFIG_ARCH_LH7A400 \ + Shark CONFIG_ARCH_SHARK \ + AT91RM9200-based CONFIG_ARCH_AT91RM9200 " RiscPC + +@@ -182,6 +184,17 @@ + + endmenu + ++mainmenu_option next_comment ++comment 'Sharp LH79520 Implementations' ++dep_bool ' LH79520 EVB' CONFIG_LH79520_EVB $CONFIG_ARCH_LH79520 ++dep_bool ' 520 BOGUS EVB' CONFIG_BOGON_EVB $CONFIG_ARCH_LH79520 ++endmenu ++ ++mainmenu_option next_comment ++comment 'Sharp LH7A400 Implementations' ++dep_bool ' LH7A400 EVB' CONFIG_LH7A400_EVB $CONFIG_ARCH_LH7A400 ++endmenu ++ + # Definitions to make life easier + if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \ + "$CONFIG_ARCH_RPC" = "y" ]; then +@@ -295,6 +308,7 @@ + # ARM720T + if [ "$CONFIG_ARCH_CLPS711X" = "y" -o \ + "$CONFIG_ARCH_L7200" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o \ + "$CONFIG_ARCH_CDB89712" = "y" ]; then + define_bool CONFIG_CPU_ARM720T y + else +@@ -320,7 +334,8 @@ + + + # ARM922T +-if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then ++if [ "$CONFIG_ARCH_CAMELOT" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" ]; then + define_bool CONFIG_CPU_ARM922T y + else + if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then +@@ -399,6 +414,7 @@ + "$CONFIG_ARCH_TBOX" = "y" -o "$CONFIG_ARCH_SHARK" = "y" -o \ + "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_CLPS711X" = "y" -o \ + "$CONFIG_ARCH_INTEGRATOR" = "y" -o "$CONFIG_ARCH_SA1100" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o "$CONFIG_ARCH_LH7A400" = "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 +@@ -440,6 +456,8 @@ + + # Select various configuration options depending on the machine type + if [ "$CONFIG_ARCH_EDB7211" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" -o \ + "$CONFIG_ARCH_RISCSTATION" = "y" ]; then + define_bool CONFIG_DISCONTIGMEM y +@@ -473,6 +491,8 @@ + "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_CDB89712" = "y" -o \ + "$CONFIG_ARCH_EDB7211" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" ]; then + define_bool CONFIG_ISA y + else +@@ -690,6 +710,8 @@ + "$CONFIG_ARCH_TBOX" = "y" -o \ + "$CONFIG_ARCH_CLPS7500" = "y" -o \ + "$CONFIG_ARCH_P720T" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" -o \ + "$CONFIG_ARCH_ANAKIN" = "y" -o \ + "$CONFIG_ARCH_MX1ADS" = "y" ]; then + define_bool CONFIG_PC_KEYMAP y +@@ -707,6 +729,8 @@ + "$CONFIG_ARCH_TBOX" = "y" -o \ + "$CONFIG_ARCH_SHARK" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" -o \ ++ "$CONFIG_ARCH_LH79520" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" -o \ + "$CONFIG_PCI" = "y" ]; then + mainmenu_option next_comment + comment 'Sound' +diff -urN linux-2.4.26/arch/arm/def-configs/lnode80 linux-2.4.26-vrs1-lnode80/arch/arm/def-configs/lnode80 +--- linux-2.4.26/arch/arm/def-configs/lnode80 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/def-configs/lnode80 2005-11-03 09:11:23.000000000 -0400 +@@ -0,0 +1,804 @@ ++# ++# Automatically generated make config: don't edit ++# ++CONFIG_ARM=y ++# CONFIG_EISA is not set ++# CONFIG_SBUS is not set ++# CONFIG_MCA is not set ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set ++# CONFIG_GENERIC_BUST_SPINLOCK is not set ++# CONFIG_GENERIC_ISA_DMA is not set ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++# CONFIG_OBSOLETE is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_KMOD is not set ++ ++# ++# System Type ++# ++# CONFIG_ARCH_ANAKIN is not set ++# CONFIG_ARCH_ARCA5K is not set ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_OMAHA is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_MX1ADS is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_RISCSTATION is not set ++# CONFIG_ARCH_SA1100 is not set ++CONFIG_ARCH_LH79520=y ++# CONFIG_ARCH_LH7A400 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 ++# CONFIG_MACH_CSB337 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 LH79520 Implementations ++# ++CONFIG_LH79520_EVB=y ++# CONFIG_BOGON_EVB is not set ++ ++# ++# Sharp LH7A400 Implementations ++# ++# CONFIG_LH7A400_EVB is not set ++# CONFIG_ARCH_ACORN is not set ++# CONFIG_PLD 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=y ++# CONFIG_CPU_ARM920T is not set ++# CONFIG_CPU_ARM922T is not set ++# CONFIG_CPU_ARM926T is not set ++# CONFIG_CPU_ARM1020 is not set ++# CONFIG_CPU_ARM1020E is not set ++# CONFIG_CPU_ARM1022 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=y ++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_HOTPLUG is not set ++# CONFIG_PCMCIA is not set ++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=y ++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_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_GEOMETRY 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=y ++CONFIG_MTD_PHYSMAP_START=40400000 ++CONFIG_MTD_PHYSMAP_LEN=400000 ++CONFIG_MTD_PHYSMAP_BUSWIDTH=2 ++# CONFIG_MTD_NORA is not set ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_CDB89712 is not set ++# CONFIG_MTD_SA1100 is not set ++# CONFIG_MTD_DC21285 is not set ++# CONFIG_MTD_IQ80310 is not set ++# CONFIG_MTD_FORTUNET is not set ++# CONFIG_MTD_EPXA is not set ++# CONFIG_MTD_AUTCPU12 is not set ++# CONFIG_MTD_EDB7312 is not set ++# CONFIG_MTD_IMPA7 is not set ++# CONFIG_MTD_CEIVA is not set ++# CONFIG_MTD_PCI is not set ++# CONFIG_MTD_PCMCIA is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC1000 is not set ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOCPROBE is not set ++ ++# ++# NAND Flash Device Drivers ++# ++# CONFIG_MTD_NAND is not set ++ ++# ++# Plug and Play configuration ++# ++# CONFIG_PNP is not set ++# CONFIG_ISAPNP is not set ++ ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_DEV_XD is not set ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_CPQ_DA is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_CISS_SCSI_TAPE is not set ++# CONFIG_CISS_MONITOR_THREAD 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 is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_FILTER is not set ++CONFIG_UNIX=y ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++# CONFIG_IP_PNP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_ARPD is not set ++# CONFIG_INET_ECN is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_IPV6 is not set ++# CONFIG_KHTTPD is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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 is not set ++ ++# ++# Amateur Radio support ++# ++# CONFIG_HAMRADIO is not set ++ ++# ++# IrDA (infrared) support ++# ++# CONFIG_IRDA is not set ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++# CONFIG_IDE is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI support ++# ++# CONFIG_SCSI is not set ++ ++# ++# I2O device support ++# ++# CONFIG_I2O is not set ++# CONFIG_I2O_BLOCK is not set ++# CONFIG_I2O_LAN is not set ++# CONFIG_I2O_SCSI is not set ++# CONFIG_I2O_PROC is not set ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input core support ++# ++# CONFIG_INPUT is not set ++# CONFIG_INPUT_KEYBDEV is not set ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_UINPUT is not set ++# CONFIG_INPUT_MX1TS is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++# CONFIG_SERIAL is not set ++# CONFIG_SERIAL_EXTENDED is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_ANAKIN is not set ++# CONFIG_SERIAL_ANAKIN_CONSOLE is not set ++# CONFIG_SERIAL_AMBA is not set ++# CONFIG_SERIAL_AMBA_CONSOLE is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_LH7A400 is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_CLPS711X_CONSOLE is not set ++# CONFIG_SERIAL_21285 is not set ++# CONFIG_SERIAL_21285_OLD is not set ++# CONFIG_SERIAL_21285_CONSOLE is not set ++# CONFIG_SERIAL_UART00 is not set ++# CONFIG_SERIAL_UART00_CONSOLE is not set ++# CONFIG_SERIAL_SA1100 is not set ++# CONFIG_SERIAL_SA1100_CONSOLE is not set ++# CONFIG_SERIAL_OMAHA is not set ++# CONFIG_SERIAL_OMAHA_CONSOLE is not set ++# CONFIG_SERIAL_AT91 is not set ++# CONFIG_SERIAL_AT91_CONSOLE is not set ++# CONFIG_SERIAL_8250 is not set ++# CONFIG_SERIAL_8250_CONSOLE is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++# CONFIG_SERIAL_8250_SHARE_IRQ is not set ++# CONFIG_SERIAL_8250_DETECT_IRQ is not set ++# CONFIG_SERIAL_8250_MULTIPORT is not set ++# CONFIG_SERIAL_8250_HUB6 is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_UNIX98_PTY_COUNT=256 ++ ++# ++# I2C support ++# ++# CONFIG_I2C is not set ++ ++# ++# L3 serial bus support ++# ++# CONFIG_L3 is not set ++# CONFIG_L3_ALGOBIT is not set ++# CONFIG_L3_BIT_SA1100_GPIO is not set ++ ++# ++# Other L3 adapters ++# ++# CONFIG_L3_SA1111 is not set ++# CONFIG_BIT_SA1100_GPIO is not set ++ ++# ++# Mice ++# ++# CONFIG_BUSMOUSE is not set ++CONFIG_MOUSE=y ++CONFIG_PSMOUSE=y ++# CONFIG_82C710_MOUSE is not set ++# CONFIG_PC110_PAD is not set ++# CONFIG_MK712_MOUSE is not set ++ ++# ++# Joysticks ++# ++# CONFIG_INPUT_GAMEPORT is not set ++ ++# ++# Input core support is needed for gameports ++# ++ ++# ++# Input core support is needed for joysticks ++# ++# 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=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++# CONFIG_ACQUIRE_WDT is not set ++# CONFIG_ADVANTECH_WDT is not set ++# CONFIG_ALIM1535_WDT is not set ++# CONFIG_ALIM7101_WDT is not set ++# CONFIG_SC520_WDT is not set ++# CONFIG_PCWATCHDOG is not set ++# CONFIG_21285_WATCHDOG is not set ++# CONFIG_977_WATCHDOG is not set ++# CONFIG_SA1100_WATCHDOG is not set ++# CONFIG_LH79520_WATCHDOG is not set ++# CONFIG_EPXA_WATCHDOG is not set ++# CONFIG_OMAHA_WATCHDOG is not set ++# CONFIG_AT91_WATCHDOG is not set ++# CONFIG_EUROTECH_WDT is not set ++# CONFIG_IB700_WDT is not set ++# CONFIG_WAFER_WDT is not set ++# CONFIG_I810_TCO is not set ++# CONFIG_MIXCOMWD is not set ++# CONFIG_60XX_WDT is not set ++# CONFIG_SC1200_WDT is not set ++# CONFIG_SCx200_WDT is not set ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_W83877F_WDT is not set ++# CONFIG_WDT is not set ++# CONFIG_WDTPCI is not set ++# CONFIG_MACHZ_WDT is not set ++# CONFIG_AMD7XX_TCO is not set ++# CONFIG_SCx200 is not set ++# CONFIG_SCx200_GPIO is not set ++# CONFIG_LH79520_PWM is not set ++# CONFIG_AMD_PM768 is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_FTAPE is not set ++# CONFIG_AGP is not set ++ ++# ++# Direct Rendering Manager (XFree86 DRI support) ++# ++# CONFIG_DRM is not set ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# File systems ++# ++# CONFIG_QUOTA is not set ++# CONFIG_QFMT_V2 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_HFSPLUS_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 is not set ++# CONFIG_UMSDOS_FS is not set ++CONFIG_VFAT_FS=y ++# CONFIG_EFS_FS is not set ++# CONFIG_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++# CONFIG_CRAMFS is not set ++# CONFIG_TMPFS 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=y ++# CONFIG_VXFS_FS is not set ++# CONFIG_NTFS_FS is not set ++# CONFIG_NTFS_RW is not set ++# CONFIG_HPFS_FS is not set ++CONFIG_PROC_FS=y ++# CONFIG_DEVFS_FS is not set ++# CONFIG_DEVFS_MOUNT is not set ++# CONFIG_DEVFS_DEBUG is not set ++CONFIG_DEVPTS_FS=y ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_QNX4FS_RW is not set ++# CONFIG_ROMFS_FS is not set ++CONFIG_EXT2_FS=y ++# CONFIG_SYSV_FS is not set ++# CONFIG_UDF_FS is not set ++# CONFIG_UDF_RW is not set ++# CONFIG_UFS_FS is not set ++# CONFIG_UFS_FS_WRITE is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_XFS_QUOTA is not set ++# CONFIG_XFS_RT is not set ++# CONFIG_XFS_TRACE is not set ++# CONFIG_XFS_DEBUG is not set ++ ++# ++# Network File Systems ++# ++# CONFIG_CODA_FS is not set ++# CONFIG_INTERMEZZO_FS is not set ++# CONFIG_NFS_FS is not set ++# CONFIG_NFS_V3 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_ROOT_NFS is not set ++# CONFIG_NFSD is not set ++# CONFIG_NFSD_V3 is not set ++# CONFIG_NFSD_TCP is not set ++# CONFIG_SUNRPC is not set ++# CONFIG_LOCKD is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_NCPFS_PACKET_SIGNING is not set ++# CONFIG_NCPFS_IOCTL_LOCKING is not set ++# CONFIG_NCPFS_STRONG is not set ++# CONFIG_NCPFS_NFS_NS is not set ++# CONFIG_NCPFS_OS2_NS is not set ++# CONFIG_NCPFS_SMALLDOS is not set ++# CONFIG_NCPFS_NLS is not set ++# CONFIG_NCPFS_EXTRAS is not set ++# CONFIG_ZISOFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_SMB_NLS is not set ++CONFIG_NLS=y ++ ++# ++# Native Language Support ++# ++CONFIG_NLS_DEFAULT="iso8859-1" ++# CONFIG_NLS_CODEPAGE_437 is not set ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++# CONFIG_NLS_ISO8859_1 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 is not set ++ ++# ++# Sound ++# ++# CONFIG_SOUND is not set ++ ++# ++# Multimedia Capabilities Port drivers ++# ++# CONFIG_MCP is not set ++# CONFIG_MCP_SA1100 is not set ++# CONFIG_MCP_UCB1200 is not set ++# CONFIG_MCP_UCB1200_AUDIO is not set ++# CONFIG_MCP_UCB1200_TS is not set ++ ++# ++# Misc devices ++# ++# CONFIG_TOUCHSCREEN_LH79520 is not set ++# CONFIG_EEPROM_LH79520 is not set ++# CONFIG_7SEGMENT_LH79520 is not set ++ ++# ++# USB support ++# ++# CONFIG_USB is not set ++ ++# ++# Support for USB gadgets ++# ++# CONFIG_USB_GADGET 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_CRC32 is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff -urN linux-2.4.26/arch/arm/kernel/debug-armv.S linux-2.4.26-vrs1-lnode80/arch/arm/kernel/debug-armv.S +--- linux-2.4.26/arch/arm/kernel/debug-armv.S 2003-08-25 07:44:39.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/kernel/debug-armv.S 2005-11-02 17:37:31.000000000 -0400 +@@ -470,6 +470,53 @@ + + + ++#elif defined(CONFIG_ARCH_LH79520) ++ ++ .macro addruart,rx ++ ldr \rx, =0xfffc1000 @UART1 base ++ .endm ++ ++ .macro senduart,rd,rx ++ strb \rd, [\rx] @ UART1_DR ++ .endm ++ ++ .macro busyuart,rd,rx @ spin while busy ++1001: ldr \rd, [\rx, #0x18] @ UART1_FR ++ tst \rd, #1 << 3 @ BUSY ? ++ bne 1001b @ yes, spin ++ .endm ++ ++ .macro waituart,rd,rx @ wait for Tx FIFO room ++1001: ldrb \rd, [\rx, #0x18] @ UART1_FR ++ tst \rd, #1 << 5 @ TXFF full? ++ bne 1001b @ yes, spin ++ .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 + #endif +diff -urN linux-2.4.26/arch/arm/kernel/entry-armv.S linux-2.4.26-vrs1-lnode80/arch/arm/kernel/entry-armv.S +--- linux-2.4.26/arch/arm/kernel/entry-armv.S 2005-11-02 16:54:17.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/kernel/entry-armv.S 2005-11-02 17:37:31.000000000 -0400 +@@ -615,6 +615,49 @@ + .text + .endm + ++#elif defined(CONFIG_ARCH_LH79520) ++#include <asm/arch/hardware.h> ++ ++ .macro disable_fiq ++ .endm ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ ldr \irqstat, =VIC_BASE @ Virt addr IRQ regs ++ ldr \irqstat, [\irqstat, #0] @ get masked interrupt status ++ mov \irqnr, #0 ++1001: tst \irqstat, #1 ++ addeq \irqnr, \irqnr, #1 ++ moveq \irqstat, \irqstat, lsr #1 ++ tsteq \irqnr, #32 ++ beq 1001b ++ teq \irqnr, #32 ++ .endm ++ ++ .macro irq_prio_table ++ .endm ++ ++#elif defined(CONFIG_ARCH_LH7A400) ++#include <asm/arch/hardware.h> ++ ++ .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 interrupt status ++ mov \irqnr, #0 ++1001: tst \irqstat, #1 ++ bne 1002f ++ add \irqnr, \irqnr, #1 ++ mov \irqstat, \irqstat, lsr #1 ++ cmp \irqnr, #28 ++ bcc 1001b ++1002: /* EQ will be set if we reach 28 */ ++ .endm ++ ++ .macro irq_prio_table ++ .endm ++ + #else + #error Unknown architecture + #endif +diff -urN linux-2.4.26/arch/arm/kernel/irq.c linux-2.4.26-vrs1-lnode80/arch/arm/kernel/irq.c +--- linux-2.4.26/arch/arm/kernel/irq.c 2005-11-02 16:54:17.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/kernel/irq.c 2005-11-02 17:37:31.000000000 -0400 +@@ -216,6 +216,18 @@ + + desc->triggered = 1; + ++#ifdef CONFIG_ARCH_LH79520 ++ if( irq < 8) { /* external interrupt */ ++ vicRegs_t *vic = (vicRegs_t *)VIC_BASE; ++ rcpcRegs_t *rcpc = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; /* unlock RCPC registers */ ++ barrier(); ++ rcpc->intClear = (1 << irq); /* clear corresponding IRQ */ ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; /* lock RCPC registers */ ++ } ++#endif ++ + /* + * Acknowledge and clear the IRQ, but (if its + * a level-based IRQ, don't mask it) +diff -urN linux-2.4.26/arch/arm/kernel/ptrace.c linux-2.4.26-vrs1-lnode80/arch/arm/kernel/ptrace.c +--- linux-2.4.26/arch/arm/kernel/ptrace.c 2005-11-02 16:54:17.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/kernel/ptrace.c 2005-11-02 17:37:31.000000000 -0400 +@@ -594,6 +594,9 @@ + */ + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: ++ if(data == 0xe7ffdefe) ++ data = 0xef9f0001; ++ + ret = access_process_vm(child, addr, &data, + sizeof(unsigned long), 1); + if (ret == sizeof(unsigned long)) +diff -urN linux-2.4.26/arch/arm/mach-lh79520/arch.c linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/arch.c +--- linux-2.4.26/arch/arm/mach-lh79520/arch.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/arch.c 2005-11-03 10:30:56.000000000 -0400 +@@ -0,0 +1,65 @@ ++/* ++ * linux/arch/arm/mach-lh79520/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 <linux/config.h> ++#include <linux/types.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/setup.h> ++#include <asm/mach-types.h> ++ ++#include <asm/mach/arch.h> ++ ++extern void genarch_init_irq( void); ++extern void lh79520_map_io( void); ++ ++#ifdef CONFIG_ARCH_LH79520 ++ ++static void __init ++fixup_lh79520(struct machine_desc *desc, struct param_struct *unused, ++ char **cmdline, struct meminfo *mi) ++{ ++ mi->nr_banks = 1; ++ mi->bank[0].start = PHYS_OFFSET; ++ mi->bank[0].size = (32*1024*1024); ++ mi->bank[0].node = 0; ++ ++ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); ++ setup_ramdisk( 1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE); ++ setup_initrd( __phys_to_virt(0x20400000), 3 * 1024 * 1024); ++ ++ /* Serial Console on UART 1 */ ++ strcpy( *cmdline, "console=ttyAM1,115200"); ++} ++ ++ ++MACHINE_START(LH79520EVB, "Sharp LH79520 Evaluation Board") ++ MAINTAINER("Duck") ++ BOOT_MEM( 0x20000000, 0xff800000, 0xff800000) // pio, vio must be 8MB ++ FIXUP( fixup_lh79520) ++ MAPIO( lh79520_map_io) ++ INITIRQ( genarch_init_irq) ++MACHINE_END ++#endif +diff -urN linux-2.4.26/arch/arm/mach-lh79520/dma.c linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/dma.c +--- linux-2.4.26/arch/arm/mach-lh79520/dma.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/dma.c 2005-11-02 17:38:44.000000000 -0400 +@@ -0,0 +1,841 @@ ++/* ++ * arch/arm/mach-lh79520/dma-lh79520.c ++ * Copyright (C) 2002 Embedix, Inc. ++ * ++ * Support functions for the Sharp LH79520 internal DMA channels. ++ * ++ * 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. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/spinlock.h> ++#include <linux/slab.h> ++#include <linux/errno.h> ++ ++#include <asm/system.h> ++#include <asm/irq.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/dma.h> ++#include <asm/mach/dma.h> ++#include <asm/arch/iocon.h> ++ ++ ++#undef DEBUG ++ ++#ifdef DEBUG ++#define DPRINTK( s, arg... ) printk( "dma<%s>: " s, dma->device_id , ##arg ) ++#define DUMPREGS(r,d) \ ++ printk( "regs=0x%x src=0x%x:%x dest=0x%x:%x count=%d control=0x%x tcnt=%d mask=0x%x status=0x%x\n", \ ++ (u32)r, r->srcHi, r->srcLow, r->destHi, r->destLow, r->count, r->control, r->termCnt, d->mask, d->status) ++#define DUMPQ(d) dumpq(d) ++#else ++#define DPRINTK( x... ) ++#define DUMPREGS(r,d) ++#define DUMPQ(d) ++#endif ++ ++/* ++ * DMA channel registers structure ++ */ ++typedef struct { ++ volatile u32 srcLow; /* Source base addr, low 16 bits */ ++ volatile u32 srcHi; /* Source base addr, hi 16 bits */ ++ volatile u32 destLow; /* Dest base addr, low 16 bits */ ++ volatile u32 destHi; /* Dest base addr, hi 16 bits */ ++ volatile u32 count; /* Maximum Count */ ++ volatile u32 control; /* Control */ ++ volatile u32 currSrcHi; /* Current src addr, hi 16 bits*/ ++ volatile u32 currSrcLow; /* Current src addr, low 16 bits*/ ++ volatile u32 currDstHi; /* Curr dest addr, hi 16 bits*/ ++ volatile u32 currDstLow; /* Curr src addr, low 16 bits*/ ++ volatile u32 termCnt; /* Terminal Count */ ++} channelRegs_t; ++ ++ ++/* ++ * Control Register Bit Field ++ */ ++#define DMAC_CTRL_ENABLE _BIT(0) /* Enable DMA */ ++#define DMAC_CTRL_SOINC _BIT(1) /* Source Reg inc.bit */ ++#define DMAC_CTRL_DEINC _BIT(2) /* Dest Reg inc.bit */ ++/* Source Size */ ++#define DMAC_CTRL_SOSIZE_1BYTE _SBF(3,0) ++#define DMAC_CTRL_SOSIZE_2BYTE _SBF(3,1) ++#define DMAC_CTRL_SOSIZE_4BYTE _SBF(3,2) ++/* Destination Size */ ++#define DMAC_CTRL_DESIZE_1BYTE _SBF(7,0) ++#define DMAC_CTRL_DESIZE_2BYTE _SBF(7,1) ++#define DMAC_CTRL_DESIZE_4BYTE _SBF(7,2) ++/* Peripheral Burst Sizes */ ++#define DMAC_CTRL_SOBURST_SINGLE _SBF(5,0) /* Single */ ++#define DMAC_CTRL_SOBURST_4INC _SBF(5,1) /* 4 incrementing */ ++#define DMAC_CTRL_SOBURST_8INC _SBF(5,2) /* 8 incrementing */ ++#define DMAC_CTRL_SOBURST_16INC _SBF(5,3) /* 16 incrementing */ ++/* Address Modes */ ++#define DMAC_CTRL_ADDR_MODE_WRAP _SBF(9,0) ++#define DMAC_CTRL_ADDR_MODE_INCR _SBF(9,1) ++ ++#define DMAC_CTRL_MEM2MEM _BIT(11) /* Memory to Memory */ ++/* Direction */ ++#define DMAC_CTRL_PERIPH_SOURCE _SBF(13,0) ++#define DMAC_CTRL_PERIPH_DEST _SBF(13,1) ++ ++ ++typedef struct { ++ channelRegs_t stream0; /* Data Stream 0 */ ++ volatile u32 reserved0[5]; ++ channelRegs_t stream1; /* Data Stream 1 */ ++ volatile u32 reserved1[5]; ++ channelRegs_t stream2; /* Data Stream 2 */ ++ volatile u32 reserved2[5]; ++ channelRegs_t stream3; /* Data Stream 3 */ ++ volatile u32 reserved3; ++ volatile u32 mask; ++ volatile u32 clear; ++ volatile u32 status; ++ volatile u32 reserved4; ++} dmaRegs_t; ++ ++channelRegs_t *streamRegs[] = { ++ &((dmaRegs_t *)IO_ADDRESS(DMAC_PHYS))->stream0, ++ &((dmaRegs_t *)IO_ADDRESS(DMAC_PHYS))->stream1, ++ &((dmaRegs_t *)IO_ADDRESS(DMAC_PHYS))->stream2, ++ &((dmaRegs_t *)IO_ADDRESS(DMAC_PHYS))->stream3 ++}; ++ ++/* ++ * mask - Mask Register Bit Fields ++ * clear - Clear Register Bit Fields ++ * status - Clear Register Bit Fields ++ * ++ * Writing DMAC_xN to mask register enables corresponding interrupt ++ * Writing DMAC_xN to clear register disables corresponding interrupt ++ * AND'ing DMAC_xN with status register yields status ++ * Note: "ACTIVEx" constants are only applicable to Status Register ++ */ ++#define DMAC_INT0 _BIT(0) /* Stream 0 Interrupt */ ++#define DMAC_INT1 _BIT(1) /* Stream 1 Interrupt */ ++#define DMAC_INT2 _BIT(2) /* Stream 2 Interrupt */ ++#define DMAC_INT3 _BIT(3) /* Stream 3 Interrupt */ ++#define DMAC_ERRINT0 _BIT(4) /* Stream 0 Error Interrupt */ ++#define DMAC_ERRINT1 _BIT(5) /* Stream 1 Error Interrupt */ ++#define DMAC_ERRINT2 _BIT(6) /* Stream 2 Error Interrupt */ ++#define DMAC_ERRINT3 _BIT(7) /* Stream 3 Error Interrupt */ ++#define DMAC_ACTIVE0 _BIT(8) /* Stream 0 Active */ ++#define DMAC_ACTIVE1 _BIT(9) /* Stream 1 Active */ ++#define DMAC_ACTIVE2 _BIT(10) /* Stream 2 Active */ ++#define DMAC_ACTIVE3 _BIT(11) /* Stream 3 Active */ ++ ++/* all DMA error bits */ ++#define DMAC_ERROR (DMAC_ERRINT0 | DMAC_ERRINT1 | DMAC_ERRINT2 | DMAC_ERRINT3 ) ++ ++/* all DMA done bits */ ++#define DMAC_DONE (DMAC_INT0 | DMAC_INT1 | DMAC_INT2 | DMAC_INT3) ++ ++/* all the bits in the clear register */ ++#define DMAC_CLEAR_ALL (DMAC_DONE | DMAC_ERROR) ++ ++ ++#include "dma.h" ++ ++lh79520_dma_t dma_chan[LH79520_DMA_CHANNELS]; ++ ++/* ++ * Maximum physical DMA buffer size ++ */ ++#define MAX_DMA_SIZE 0x3ffff ++#define MAX_DMA_ORDER 18 ++ ++ ++static inline void dumpq (lh79520_dma_t *dma) ++{ ++ dma_buf_t *p=dma->tail; ++ ++ printk( "Q: curr=0x%p tail=0x%p head=0x%p bid: ", dma->curr, dma->tail, dma->head); ++ ++ while( p) { ++ printk( "(0x%p 0x%p) ", p, p->id); ++ p = p->next; ++ } ++ printk("\n"); ++} ++ ++ ++/* ++ * DMA processing... ++ */ ++ ++static inline int start_lh79520_dma(lh79520_dma_t * dma, dma_addr_t dma_ptr, int size) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ channelRegs_t *regs = dma->regs; ++ int status; ++ ++ status = dmaRegs->status; ++ ++ /* If the DMA channel is active, there's nothing else we can do. */ ++ if( status & (DMAC_ACTIVE0 << dma->channel)) { ++ DPRINTK("start: st %#x busy\n", status); ++ return -EBUSY; ++ } ++ ++ /* If there's an interrupt pending, split now ++ * and let it happen. ++ */ ++ if( status & (DMAC_INT0 << dma->channel)) { ++ DPRINTK("start: st %#x IRQ pending\n", status); ++ return -EAGAIN; ++ } ++ ++ /* ++ * if we're goint to the uda1341, we have to tell the CPLD ++ * to start to send/receive via DMA. ++ */ ++ switch( dma->channel) { ++ case 2: ++ cpld->audio_control |= CPLD_DAC_DMA_ENABLE; ++ dmaRegs->mask |= DMAC_INT2; ++ break; ++ ++ case 3: ++ cpld->audio_control |= (CPLD_DAC_DMA_ENABLE | CPLD_DAC_USE_REQ1 ); ++ dmaRegs->mask |= DMAC_INT3; ++ break; ++ } ++ ++ /* ++ * set the source or destination registers, based on which ++ * direction the data's going. ++ */ ++ if( dma->direction == DMA_IN) { /* data coming from peripheral */ ++ regs->destLow = dma_ptr & 0xffff; ++ regs->destHi = (dma_ptr >> 16 ) & 0xffff; ++ } else { /* data going to peripheral */ ++ regs->srcLow = dma_ptr & 0xffff; ++ regs->srcHi = (dma_ptr >> 16 ) & 0xffff; ++ } ++ ++ regs->count = size >> 2; /* DDD assumes 4-byte transfer size */ ++ regs->control |= DMAC_CTRL_ENABLE; ++ ++ DPRINTK("audio_control=0x%x\n", cpld->audio_control); ++ DPRINTK("jif=%d start a=%#x sz=%d st=0x%x dma=0x%p dir=%d\n", ++ jiffies, dma_ptr, size, status, dma, dma->direction); ++ DUMPREGS(regs,dmaRegs); ++ ++#if 0 ++ { ++ u32 *p = phys_to_virt(dma_ptr); ++ int i; ++ ++ for( i=0; i<8; i++) ++ printk( " %08x %08x %08x %08x\n", *p++, *p++, *p++, *p++); ++ } ++#endif // 0 ++ ++ return 0; ++} ++ ++ ++static int start_dma(lh79520_dma_t *dma, dma_addr_t dma_ptr, int size) ++{ ++ return start_lh79520_dma(dma, dma_ptr, size); ++} ++ ++ ++/* This must be called with IRQ disabled */ ++static void process_dma(lh79520_dma_t * dma) ++{ ++ dma_buf_t *buf; ++ int chunksize; ++ ++ DUMPQ(dma); ++ ++ for (;;) { ++ buf = dma->tail; ++ ++ if (!buf || dma->stopped) { ++ /* no more data available */ ++ DPRINTK("process: no more buf (dma %s) buf=0x%p stopped=%d\n", ++ dma->curr ? "active" : "inactive", buf, dma->stopped); ++ /* ++ * 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 (dma->spin_size && dma->spin_ref >= 0) { ++ chunksize = dma->spin_size; ++ if (chunksize > MAX_DMA_SIZE) ++ chunksize = (1 << MAX_DMA_ORDER); ++ while (start_dma(dma, dma->spin_addr, chunksize) == 0) ++ dma->spin_ref++; ++ if (dma->curr != NULL) ++ dma->spin_ref = -dma->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 (start_dma(dma, buf->dma_ptr, chunksize) != 0) ++ break; ++ ++ if (!dma->curr) { ++ dma->curr = buf; ++ DPRINTK("process: set curr %#p\n", dma->curr); ++ } ++ ++ buf->ref++; ++ buf->dma_ptr += chunksize; ++ buf->size -= chunksize; ++ if (buf->size == 0) { ++ /* current buffer is done: move tail to the next one */ ++ dma->tail = buf->next; ++ DPRINTK("process: set tail b=%#x\n", (int) dma->tail); ++ } ++ } ++ ++ DUMPQ(dma); ++} ++ ++ ++/* This must be called with IRQ disabled */ ++void lh79520_dma_done (lh79520_dma_t *dma) ++{ ++ dma_buf_t *buf = dma->curr; ++ ++ if (dma->spin_ref > 0) { ++ dma->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=%#p\n", buf->next); ++ dma->curr = buf->next; ++ if (dma->curr == NULL) ++ dma->spin_ref = -dma->spin_ref; ++ if (dma->head == buf) ++ dma->head = NULL; ++ if (dma->callback) { ++ int size = buf->dma_ptr - buf->dma_start; ++ dma->callback(buf->id, size); ++ } ++ kfree(buf); ++ } ++ } ++ ++ process_dma(dma); ++} ++ ++ ++static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ lh79520_dma_t *dma = (lh79520_dma_t *) dev_id; ++ int status = dmaRegs->status; ++ ++ DPRINTK("jif=%d IRQ: irq=%d regs=0x%x bid=%#x st=%#x, dma=0x%p\n", ++ jiffies, irq, (u32)dma->regs, (int) dma->curr->id, status, dma); ++ ++ if (status & (DMAC_ERROR)) { ++ printk(KERN_ERR "DMA on \"%s\" caused an error\n", dma->device_id); ++ dmaRegs->clear = DMAC_ERROR; ++ } ++ ++ dmaRegs->clear = status & DMAC_DONE; ++ ++ if (status & DMAC_DONE) ++ lh79520_dma_done (dma); ++} ++ ++ ++/* ++ * DMA interface functions ++ */ ++ ++static spinlock_t dma_list_lock; ++ ++int lh79520_request_dma (dmach_t * channel, const char *device_id, dma_device_t device) ++{ ++ lh79520_dma_t *dma = NULL; ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ channelRegs_t *regs; ++ int i, err; ++ ++ /* DMA address (physical) of audio device */ ++ void *cpldAudioAddr = (void *) &((cpldRegs_t *)CPLD_START)->adc_dac_left; ++ ++ ++#ifdef DEBUG ++ printk( __FUNCTION__ "(channel=0x%x, device_id=0x%x device=0x%x)\n", ++ (u32)channel, (u32)device_id, device); ++#endif ++ ++ *channel = -1; /* to be sure we catch the freeing of a misregistered channel */ ++ ++ err = 0; ++ spin_lock(&dma_list_lock); ++ ++ /* ++ * Allocate a channel. On the lh79520, channels 0 and 1 ++ * are dedicated to the SSP. Channels 2 and 3 are general purpose, ++ * but channel 3 can only be used for audio if the rework described ++ * in the User's Guide has been performed. ++ */ ++ switch( device) { ++ case DMA_Audio_Out: ++ dma = &dma_chan[2]; ++ regs = dma->regs; ++ ++ dma->direction = DMA_OUT; ++ ++ regs->destLow = (u32)cpldAudioAddr & 0xffff; ++ regs->destHi = ((u32)cpldAudioAddr >> 16) & 0xffff; ++ regs->control = DMAC_CTRL_SOINC | ++ DMAC_CTRL_SOSIZE_4BYTE | ++ DMAC_CTRL_DESIZE_4BYTE | ++ DMAC_CTRL_SOBURST_SINGLE | ++ DMAC_CTRL_ADDR_MODE_WRAP | ++ DMAC_CTRL_PERIPH_DEST; ++ break; ++ ++ case DMA_Audio_In: ++ dma = &dma_chan[3]; ++ regs = dma->regs; ++ ++ dma->direction = DMA_IN; ++ ++ regs->srcLow = (u32)cpldAudioAddr & 0xffff; ++ regs->srcHi = ((u32)cpldAudioAddr >> 16) & 0xffff; ++ regs->control = DMAC_CTRL_SOINC | ++ DMAC_CTRL_SOSIZE_4BYTE | ++ DMAC_CTRL_DESIZE_4BYTE | ++ DMAC_CTRL_SOBURST_SINGLE | ++ DMAC_CTRL_ADDR_MODE_WRAP | ++ DMAC_CTRL_PERIPH_SOURCE; ++ break; ++ ++ case DMA_SSP_Rx: /* not supported */ ++ case DMA_SSP_Tx: /* not supported */ ++ default: ++ err = -ENOSR; ++ break; ++ } ++ ++ if (!err) { ++ if (dma) ++ dma->in_use = 1; ++ else ++ err = -ENOSR; ++ } ++ spin_unlock(&dma_list_lock); ++ if (err) ++ return err; ++ ++ err = request_irq(dma->irq, dma_irq_handler, SA_INTERRUPT, ++ device_id, (void *) dma); ++ if (err) { ++ printk(KERN_ERR ++ "%s: unable to request IRQ %d for DMA channel. error=0x%x\n", ++ device_id, dma->irq, err); ++ return err; ++ } ++ ++ *channel = dma - dma_chan; ++ dma->device_id = device_id; ++ dma->device = device; ++ dma->callback = NULL; ++ dma->spin_size = 0; ++ ++ regs = dma->regs; ++ ++ DPRINTK( "channel=%d regs=0x%x\n", *channel, (u32)regs); ++ DPRINTK("requested\n"); ++ ++ return 0; ++} ++ ++ ++int lh79520_dma_set_callback(dmach_t channel, dma_callback_t cb) ++{ ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ dma->callback = cb; ++ DPRINTK("cb = %p\n", cb); ++ return 0; ++} ++ ++ ++int lh79520_dma_set_spin(dmach_t channel, dma_addr_t addr, int size) ++{ ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ int flags; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ DPRINTK("set spin %d at %#x\n", size, addr); ++ local_irq_save(flags); ++ dma->spin_addr = addr; ++ dma->spin_size = size; ++ if (size) ++ process_dma(dma); ++ ++ local_irq_restore(flags); ++ return 0; ++} ++ ++ ++int lh79520_dma_queue_buffer(dmach_t channel, void *buf_id, ++ dma_addr_t data, int size) ++{ ++ lh79520_dma_t *dma; ++ dma_buf_t *buf; ++ int flags; ++ ++ dma = &dma_chan[channel]; ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ buf = kmalloc(sizeof(*buf), 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); ++ ++ DPRINTK("queueing bid=%#x a=%#x s=%d\n", (int) buf_id, data, size); ++ ++ if (dma->head) ++ dma->head->next = buf; ++ ++ dma->head = buf; ++ if (!dma->tail) ++ dma->tail = buf; ++ ++ process_dma(dma); ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++ ++int lh79520_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr) ++{ ++ int flags, ret; ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ channelRegs_t *regs; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ regs = dma->regs; ++ local_irq_save(flags); ++ if (dma->curr && dma->spin_ref <= 0) { ++ dma_buf_t *buf = dma->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; ++ ++ if( dma->direction == DMA_IN) ++ *addr = (regs->currDstHi << 16 ) | (regs->currDstLow); ++ else ++ *addr = (regs->currSrcHi << 16 ) | (regs->currSrcLow); ++ ++ /* ++ * 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)dma->curr->id, *addr); ++ ret = 0; ++ } else if (dma->tail && dma->stopped) { ++ dma_buf_t *buf = dma->tail; ++ if (buf_id) ++ *buf_id = buf->id; ++ *addr = buf->dma_ptr; ++ ret = 0; ++ } else { ++ if (buf_id) ++ *buf_id = NULL; ++ *addr = 0; ++ ret = -ENXIO; ++ } ++ local_irq_restore(flags); ++ return ret; ++} ++ ++ ++int lh79520_dma_stop(dmach_t channel) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ int flags; ++ ++ DPRINTK( "lh79520_dma_stop channel=%d\n", channel); ++ ++ if (dma->stopped) ++ return 0; ++ ++ local_irq_save(flags); ++ dma->stopped = 1; ++ ++ /* ++ * Stop DMA and tweak state variables so everything could restart ++ * from there when resume/wakeup occurs. ++ */ ++ dma->regs->control &= ~DMAC_CTRL_ENABLE; ++ dmaRegs->mask &= ~((DMAC_INT0 << channel) | (DMAC_ERRINT0 << channel)); ++ ++ if (dma->curr) { ++ dma_buf_t *buf = dma->curr; ++ if (dma->spin_ref <= 0) { ++ dma_addr_t curpos; ++ lh79520_dma_get_current(channel, NULL, &curpos); ++ buf->size += buf->dma_ptr - curpos; ++ buf->dma_ptr = curpos; ++ } ++ buf->ref = 0; ++ dma->tail = buf; ++ dma->curr = NULL; ++ } ++ dma->spin_ref = 0; ++ process_dma(dma); ++ local_irq_restore(flags); ++ return 0; ++} ++ ++ ++int lh79520_dma_resume(dmach_t channel) ++{ ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ if (dma->stopped) { ++ int flags; ++ save_flags_cli(flags); ++ dma->stopped = 0; ++ dma->spin_ref = 0; ++ process_dma(dma); ++ restore_flags(flags); ++ } ++ return 0; ++} ++ ++ ++int lh79520_dma_flush_all(dmach_t channel) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ dma_buf_t *buf, *next_buf; ++ int flags; ++ ++ DPRINTK("dma_flush_all channel=%d\n", channel); ++ DUMPQ(dma); ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ /* ++ * Disable the channel, and mask off its interrupts ++ */ ++ dma->regs->control &= ~(DMAC_CTRL_ENABLE); ++ dmaRegs->mask &= ~((DMAC_INT0 << channel) | (DMAC_ERRINT0 << channel)); ++ ++ buf = dma->curr; ++ if (!buf) ++ buf = dma->tail; ++ ++ dma->head = dma->tail = dma->curr = NULL; ++ dma->stopped = 0; ++ dma->spin_ref = 0; ++ process_dma(dma); ++ local_irq_restore(flags); ++ ++ while (buf) { ++ next_buf = buf->next; ++ kfree(buf); ++ buf = next_buf; ++ } ++ DPRINTK("flushed\n"); ++ return 0; ++} ++ ++ ++void lh79520_free_dma(dmach_t channel) ++{ ++ lh79520_dma_t *dma; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS) ++ return; ++ ++ dma = &dma_chan[channel]; ++ if (!dma->in_use) { ++ printk(KERN_ERR "Trying to free free DMA%d\n", channel); ++ return; ++ } ++ ++ lh79520_dma_set_spin(channel, 0, 0); ++ lh79520_dma_flush_all(channel); ++ ++ free_irq(dma->irq, (void *) dma); ++ dma->in_use = 0; ++ ++ DPRINTK("freed\n"); ++} ++ ++ ++EXPORT_SYMBOL(lh79520_request_dma); ++EXPORT_SYMBOL(lh79520_dma_set_callback); ++EXPORT_SYMBOL(lh79520_dma_set_spin); ++EXPORT_SYMBOL(lh79520_dma_queue_buffer); ++EXPORT_SYMBOL(lh79520_dma_get_current); ++EXPORT_SYMBOL(lh79520_dma_stop); ++EXPORT_SYMBOL(lh79520_dma_resume); ++EXPORT_SYMBOL(lh79520_dma_flush_all); ++EXPORT_SYMBOL(lh79520_free_dma); ++ ++ ++#ifdef CONFIG_PM ++/* Drivers should call this from their PM callback function */ ++ ++int lh79520_dma_sleep(dmach_t channel) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ int orig_state; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ orig_state = dma->stopped; ++ lh79520_dma_stop(channel); ++ dma->regs->control &= ~DMAC_CTRL_ENABLE; ++ dmaRegs->mask &= ~((DMAC_INT0 << channel) | (DMAC_ERRINT0 << channel)); ++ ++ dma->stopped = orig_state; ++ dma->spin_ref = 0; ++ return 0; ++} ++ ++int lh79520_dma_wakeup(dmach_t channel) ++{ ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ lh79520_dma_t *dma = &dma_chan[channel]; ++ int flags; ++ ++ if ((unsigned)channel >= LH79520_DMA_CHANNELS || !dma->in_use) ++ return -EINVAL; ++ ++ dma->regs->control &= ~DMAC_CTRL_ENABLE; ++ dmaRegs->mask &= ~((DMAC_INT0 << channel) | (DMAC_ERRINT0 << channel)); ++ ++ local_irq_save(flags); ++ process_dma(dma); ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(lh79520_dma_sleep); ++EXPORT_SYMBOL(lh79520_dma_wakeup); ++ ++#endif /* CONFIG_PM */ ++ ++ ++static int __init lh79520_init_dma(void) ++{ ++ int channel; ++ dmaRegs_t *dmaRegs = (dmaRegs_t *)IO_ADDRESS(DMAC_PHYS); ++ ioconRegs_t *ioconRegs = (ioconRegs_t *)IO_ADDRESS( IOCON_PHYS); ++ channelRegs_t *regs; ++ ++#ifdef DEBUG ++ printk( __FUNCTION__ "\n"); ++#endif ++ ++ dmaRegs->clear = DMAC_CLEAR_ALL; ++ dmaRegs->mask = 0; ++ ++ for (channel = 0; channel < LH79520_DMA_CHANNELS; channel++) { ++ dma_chan[channel].regs = regs = streamRegs[channel]; ++ ++ regs->control = 0; ++ regs->count = 0; ++ regs->srcHi = 0; ++ regs->srcLow = 0; ++ regs->destHi = 0; ++ regs->destLow = 0; ++ ++ dma_chan[channel].irq = IRQ_DMA; ++ dma_chan[channel].channel = channel; ++ ++#ifdef DEBUG ++ printk( "dma channel %d at 0x%x\n", channel, (u32)regs); ++#endif ++ } ++ ++ /* assign pins to DMA stream 2 */ ++ ioconRegs->DMAMux |= (DMAMUX_DCDEOT0 | DMAMUX_DCDREQ0) ; ++ ++ /* assign pins to DMA Stream 3 */ ++ // These two lines interfere with PWM Audio ++ // ioconRegs->MiscMux |= MISCMUX_DCDEOT1; ++ // ioconRegs->MiscMux &= ~MISCMUX_RCEII5; ++ ++ return 0; ++} ++ ++__initcall(lh79520_init_dma); +diff -urN linux-2.4.26/arch/arm/mach-lh79520/dma.h linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/dma.h +--- linux-2.4.26/arch/arm/mach-lh79520/dma.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/dma.h 2005-11-02 17:38:44.000000000 -0400 +@@ -0,0 +1,61 @@ ++/* ++ * 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 <nico@cam.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/config.h> ++ ++/* ++ * DMA buffer structure ++ */ ++ ++typedef struct dma_buf_s { ++ 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 */ ++ struct dma_buf_s *next; /* next buffer to process */ ++} dma_buf_t; ++ ++typedef enum { ++ DMA_OUT, ++ DMA_IN ++} dma_direction_t; ++ ++/* ++ * DMA channel structure. ++ */ ++typedef struct { ++ unsigned int in_use; /* Device is allocated */ ++ const char *device_id; /* Device name */ ++ dma_device_t device; /* ... to which this channel is attached */ ++ dma_buf_t *head; /* where to insert buffers */ ++ dma_buf_t *tail; /* where to remove buffers */ ++ dma_buf_t *curr; /* buffer currently DMA'ed */ ++ int stopped; /* 1 if DMA is stalled */ ++ channelRegs_t *regs; /* points to appropriate DMA registers */ ++ int irq; /* IRQ used by the channel */ ++ dma_callback_t callback; /* ... 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 */ ++ int channel; /* channel number */ ++ dma_direction_t direction; /* DMA direction: 0=Out / 1=In */ ++} lh79520_dma_t; ++ ++extern lh79520_dma_t dma_chan[LH79520_DMA_CHANNELS]; ++ ++ ++void lh79520_dma_done( lh79520_dma_t *dma); ++ ++ ++ ++ +diff -urN linux-2.4.26/arch/arm/mach-lh79520/generic.c linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/generic.c +--- linux-2.4.26/arch/arm/mach-lh79520/generic.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/generic.c 2005-11-02 17:38:09.000000000 -0400 +@@ -0,0 +1,71 @@ ++/* ++ * linux/arch/arm/mach-lh79520/generic.c ++ * ++ * Common code for all LH79520 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 <linux/config.h> ++#include <linux/types.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++ ++#include <asm/hardware.h> ++#include <asm/irq.h> ++#include <asm/setup.h> ++#include <asm/mach-types.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/arch/rcpc.h> ++ ++ ++/* ++ * return the CPU clock frequency (FCLK) in Hz. ++ */ ++unsigned int ++cpufreq_get( int cpu) ++{ ++ int divider; ++ rcpcRegs_t *RCPC = (rcpcRegs_t *)IO_ADDRESS(RCPC_PHYS); ++ ++ divider = RCPC->CpuClkPrescale * 2; ++ if( divider == 0) ++ divider = 1; ++ return PLL_CLOCK / divider;; ++} ++EXPORT_SYMBOL(cpufreq_get); ++ ++ ++/* ++ * return the bus clock frequency (HCLK) in Hz. ++ */ ++unsigned int ++hclkfreq_get( void) ++{ ++ int divider; ++ rcpcRegs_t *RCPC = (rcpcRegs_t *)IO_ADDRESS(RCPC_PHYS); ++ ++ divider = RCPC->HCLKPrescale * 2; /* HCLK prescale value */ ++ ++ if( divider == 0) /* no prescalar == divide by 1 */ ++ divider = 1; ++ ++ return PLL_CLOCK / divider; ++} ++ ++ +diff -urN linux-2.4.26/arch/arm/mach-lh79520/generic.h linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/generic.h +--- linux-2.4.26/arch/arm/mach-lh79520/generic.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/generic.h 2005-11-02 17:38:09.000000000 -0400 +@@ -0,0 +1,24 @@ ++/* ++ * linux/arch/arm/mach-lh79520/generic.h ++ * ++ * Common code for all LH79520 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 ++ */ ++ ++unsigned int cpufreq_get( int cpu); ++unsigned int hclkfreq_get( void); +diff -urN linux-2.4.26/arch/arm/mach-lh79520/Makefile linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/Makefile +--- linux-2.4.26/arch/arm/mach-lh79520/Makefile 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/Makefile 2005-11-02 17:38:09.000000000 -0400 +@@ -0,0 +1,24 @@ ++# ++# 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 := lh79520.o ++ ++# Object file lists. ++ ++obj-y := arch.o mm.o generic.o dma.o ++obj-m := ++obj-n := ++obj- := ++ ++export-objs := generic.o dma.o ++ ++# obj-$(CONFIG_LEDS) += leds.o ++# obj-$(CONFIG_PCI) += pci_v3.o pci.o ++ ++include $(TOPDIR)/Rules.make +diff -urN linux-2.4.26/arch/arm/mach-lh79520/mm.c linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/mm.c +--- linux-2.4.26/arch/arm/mach-lh79520/mm.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/mach-lh79520/mm.c 2005-11-02 17:38:09.000000000 -0400 +@@ -0,0 +1,38 @@ ++/* ++ * linux/arch/arm/mach-lh79520/mm.c ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++#include <linux/sched.h> ++#include <linux/mm.h> ++#include <linux/init.h> ++ ++#include <asm/pgtable.h> ++#include <asm/page.h> ++#include <asm/io.h> ++ ++#include <asm/mach/map.h> ++ ++static struct map_desc lh79520_io_desc[] __initdata = { ++ /* virt phys size r w c b */ ++ { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { CPLD_BASE, CPLD_START, CPLD_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { CS8900_BASE, CS8900_START, CS8900_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { IDE_BASE, IDE_START, IDE_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { IDE2_BASE, IDE2_START, IDE2_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { INT_SRAM_BASE, INT_SRAM_START, INT_SRAM_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { APB_BASE, APB_START, APB_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { AHB_BASE, AHB_START, AHB_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ { VIC_BASE, VIC_START, VIC_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, ++ LAST_DESC ++}; ++ ++void __init lh79520_map_io(void) ++{ ++ iotable_init( lh79520_io_desc); ++} ++ +diff -urN linux-2.4.26/arch/arm/Makefile linux-2.4.26-vrs1-lnode80/arch/arm/Makefile +--- linux-2.4.26/arch/arm/Makefile 2005-11-02 16:54:16.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/Makefile 2005-11-02 17:37:31.000000000 -0400 +@@ -160,6 +160,16 @@ + MACHINE = anakin + endif + ++ifeq ($(CONFIG_ARCH_LH79520),y) ++# C0008000 is the default, so not needed -- DDD ++# DDD TEXTADDR = 0xC0008000 ++MACHINE = lh79520 ++endif ++ ++ifeq ($(CONFIG_ARCH_LH7A400),y) ++MACHINE = lh7a400 ++endif ++ + ifeq ($(CONFIG_ARCH_OMAHA),y) + MACHINE = omaha + endif +diff -urN linux-2.4.26/arch/arm/tools/mach-types linux-2.4.26-vrs1-lnode80/arch/arm/tools/mach-types +--- linux-2.4.26/arch/arm/tools/mach-types 2005-11-02 16:54:18.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/arch/arm/tools/mach-types 2005-11-02 17:37:31.000000000 -0400 +@@ -525,3 +525,5 @@ + omap_osk MACH_OMAP_OSK OMAP_OSK 515 + rg100v3 MACH_RG100V3 RG100V3 516 + mx2ads MACH_MX2ADS MX2ADS 517 ++lh79520evb LH79520_EVB LH79520EVB 999 ++lh7a400evb LH7A400_EVB LH7A400EVB 998 +diff -urN linux-2.4.26/Documentation/Configure.help linux-2.4.26-vrs1-lnode80/Documentation/Configure.help +--- linux-2.4.26/Documentation/Configure.help 2005-11-02 16:54:16.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/Documentation/Configure.help 2005-11-02 17:37:31.000000000 -0400 +@@ -25531,6 +25531,136 @@ + a debugging option; you probably do not want to set it unless you + are an S390 port maintainer. + ++Sharp LH79520 based bords ++CONFIG_ARCH_LH79520 ++ Say Y here to support the Sharp LH79520 System on Chip. ++ ++Sharp LH79520 Evaluation Board (Isis) ++CONFIG_LH79520_EVB ++ Say Y here to support the Sharp LH79520 Evaluation Board. ++ ++Sharp LH79520 Watchdog Timer ++CONFIG_LH79520_WATCHDOG ++ Say Y here to include support for the LH79520 watchdog timer. ++ The watchdog timer will reboot your system when the timeout is reached. ++ Note that once enabled, this timer cannot be disabled. ++ ++ This driver is also available as a module ( = code which can be ++ inserted in and removed from the running kernel whenever you want). ++ If you want to compile it as a module, say M here and read ++ Documentation/modules.txt. The module will be called lh79520_wdt.o. ++ ++ If unsure, say N. ++ ++Sharp LH79520 PWM controller ++CONFIG_LH79520_PWM ++ Say Y here to include support for the PWM device. ++ PWM0 is for the LCD backlight intensity, and ++ PWM1 is for audio. The major number is dynamically assigned unless ++ module parameter is provided. Device nodes must exist to control ++ the ioctls. ++ /dev/pwm0 c 254 0 ++ /dev/pwm1 c 254 1 ++ 254 may or may not be the major number for your driver. ++ Check /proc/devices for major number of pwm520. ++ ++ If unsure, say N. ++ ++Sharp LH79520 7-segment display ++CONFIG_7SEGMENT_LH79520 ++ Say Y here to include support for the LH79520 7-segment display. ++ ++ If unsure, say N. ++ ++Sharp LH79520 Touchscreen ++CONFIG_TOUCHSCREEN_LH79520 ++ Say Y here to include support for the LH79520 touchscreen. ++ ++ If unsure, say N. ++ ++Sharp LH79520 LCD EEPROM ++CONFIG_EEPROM_LH79520 ++ Say Y here to include support for the EEPROM on the LCD ++ board on the Sharp LH79520 EVB. ++ ++ If unsure, say N. ++ ++ARM PrimeCell PL011 UART ++CONFIG_SERIAL_AMBA_PL011 ++ Say Y here to include support for the ARM PrimeCell PL011 UART. ++ ++ If unsure, say N. ++ ++Console on ARM PL011 UART ++CONFIG_SERIAL_AMBA_PL011_CONSOLE ++ Say Y here to support a serial console on an ARM PrimeCell PL011 UART. ++ ++ If unsure, say N. ++ ++ARM PrimeCell PL110 LCD Controller ++CONFIG_FB_PL110 ++ Say Y here to include support the ARM PrimeCell PL110 ++ LCD controller. ++ ++ If unsure, say N. ++ ++Sharp LQ039Q2DS53-HR-TFT LCD panel ++CONFIG_PL110_LQ39 ++ Say Y here to if you've got a Sharp LQ039Q2DS53-HR-TFT ++ LCD panel connected to an ARM PL110 LCD controller. ++ ++ If unsure, say N. ++ ++Sharp LM057QCTT03-QVGA-STN LCD panel ++CONFIG_PL110_LM57 ++ Say Y here to if you've got a Sharp LM057QCTT03-QVGA-STN ++ LCD panel connected to an ARM PL110 LCD controller. ++ ++ If unsure, say N. ++ ++Sharp LQ057Q3DC02-VGA/QVGA-TFT LCD panel ++CONFIG_PL110_LQ57 ++ Say Y here to if you've got a Sharp LQ057Q3DC02-VGA/QVGA-TFT ++ LCD panel connected to an ARM PL110 LCD controller. ++ ++ If unsure, say N ++ ++Sharp LQ121S1DG31-800x600-TFT LCD panel ++CONFIG_PL110_LQ121 ++ Say Y here to if you've got a Sharp LQ121S1DG31-800x600-TFT ++ LCD panel connected to an ARM PL110 LCD controller. ++ ++ If unsure, say N ++ ++Sharp LQ104V1DG11-640x480-TFT LCD panel ++CONFIG_PL110_LQ104 ++ Say Y here to if you've got a Sharp LQ104V1DG11-640x480-TFT ++ LCD panel connected to an ARM PL110 LCD controller. ++ ++ If unsure, say N ++ ++Sharp LH7A400 based bords ++CONFIG_ARCH_LH7A400 ++ Say Y here to support the Sharp LH7A400 System on Chip. ++ ++Sharp LH7A400 Evaluation Board (Aruba) ++CONFIG_LH7A400_EVB ++ 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. ++ + # + # ARM options + # +diff -urN linux-2.4.26/drivers/char/Config.in linux-2.4.26-vrs1-lnode80/drivers/char/Config.in +--- linux-2.4.26/drivers/char/Config.in 2005-11-02 16:54:20.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/Config.in 2005-11-02 17:37:31.000000000 -0400 +@@ -253,6 +253,7 @@ + dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE + dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER + dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100 ++ dep_tristate ' Sharp LH79520 watchdog' CONFIG_LH79520_WATCHDOG $CONFIG_ARCH_LH79520 + dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT + dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA + dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200 +@@ -304,6 +305,11 @@ + if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then + dep_tristate 'AMD 768/8111 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI + fi ++ ++if [ "$CONFIG_ARCH_LH79520" = "y" ]; then ++ tristate 'LH79520 PWM support' CONFIG_LH79520_PWM ++fi ++ + if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then + dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI + fi +diff -urN linux-2.4.26/drivers/char/console.c linux-2.4.26-vrs1-lnode80/drivers/char/console.c +--- linux-2.4.26/drivers/char/console.c 2005-11-02 16:54:20.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/console.c 2005-11-02 17:37:31.000000000 -0400 +@@ -169,7 +169,7 @@ + int console_blanked; + + static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ +-static int blankinterval = 10*60*HZ; ++static int blankinterval = 0; // 10*60*HZ; + static int vesa_off_interval; + + static struct tq_struct console_callback_tq = { +diff -urN linux-2.4.26/drivers/char/cradle.c linux-2.4.26-vrs1-lnode80/drivers/char/cradle.c +--- linux-2.4.26/drivers/char/cradle.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/cradle.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,486 @@ ++/* ++** cradle.c ++** ++** Device driver for the cradle interface on the Touchblock device. ++** ++** Copyright (C) 2002 The PTR Group, Inc. <www.theptrgroup.com> ++** ++** This program is free software; you can redistribute it and/or modify ++** it under the terms of the GNU General Public License as published by ++** the Free Software Foundation; either version 2 of the License, or ++** (at your option) any later version. ++** ++** This program is distributed in the hope that it will be useful, ++** but WITHOUT ANY WARRANTY; without even the implied warranty of ++** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++** GNU General Public License for more details. ++** ++** You should have received a copy of the GNU General Public License ++** along with this program; if not, write to the Free Software ++** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++** ++*/ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/signal.h> ++#include <linux/errno.h> ++#include <linux/mm.h> ++#include <linux/slab.h> ++#include <linux/poll.h> ++#include <linux/miscdevice.h> ++#include <linux/random.h> ++#include <linux/init.h> ++#include <asm/system.h> ++#include <asm/hardware.h> ++#include <asm/arch/iocon.h> ++#include <asm/arch/gpio.h> ++#include <asm/hardware/cradle.h> ++ ++static ssize_t cradle_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ++static int cradle_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); ++static int cradle_open(struct inode *inode, struct file *filp); ++static int cradle_release(struct inode *inode, struct file *filp); ++static int cradle_fasync(int fd, struct file *filp, int mode ); ++static unsigned int cradle_poll(struct file *filp, poll_table *wait); ++ ++ ++static char read_docking_state(void); ++static inline void cradle_update_buffer(volatile char **index, int delta, char *buf, int size); ++ ++#if 0 ++void cradle_do_tasklet_docked(unsigned long data); ++DECLARE_TASKLET( cradle_tasklet_docked, cradle_do_tasklet_docked,0); ++void cradle_do_tasklet_undocked(unsigned long data); ++DECLARE_TASKLET( cradle_tasklet_undocked, cradle_do_tasklet_undocked,0); ++#endif ++ ++//#define min(a,b) (((a)<(b))?(a):(b)) ++ ++#define CRADLE_IBUF_SIZE 2 ++ ++typedef struct ++{ ++ int users; ++ int ready; ++ volatile char *ibuf_wp; ++ volatile char *ibuf_rp; ++ char *ibuf; ++ wait_queue_head_t wait_inq; ++ struct fasync_struct *fasync; /* asynchronous readers */ ++} cradle_dev_t; ++ ++static cradle_dev_t cradle_dev; ++ ++struct file_operations cradle_fops = { ++// NULL, // seek ++read: cradle_read, // read ++// NULL, // write ++// NULL, // readdir ++poll: cradle_poll, // poll/select ++ioctl: cradle_ioctl, // ioctl ++// NULL, // mmap ++open: cradle_open, // open ++// NULL, // flush ++release: cradle_release, // release ++// NULL, // fsync ++fasync: cradle_fasync, // fasync ++}; ++ ++/************************************************************************ ++** Read the docking state from the hardware ++************************************************************************/ ++static char read_docking_state(void) ++{ ++ ++ return( (GPIOG->dr & 0x10) ? CRADLE_UNDOCKED_STATE : CRADLE_DOCKED_STATE ); ++} ++ ++/************************************************************************ ++** Manipulate the buffer pointers safely without using locks ++************************************************************************/ ++static inline void cradle_update_buffer(volatile char **index, int delta, char *buf, int size) ++{ ++ volatile char *new = *index + delta; ++ barrier(); ++ *index=(new >= (buf+size)) ? buf : new; ++} ++ ++ ++#if 0 ++/************************************************************************ ++** Enable the interrupt(s) associated with the cradle ++************************************************************************/ ++static void cradle_enable_interrupt(void) ++{ ++ /* printk(KERN_INFO "cradle: interrupts enabled\n"); */ ++} ++ ++/************************************************************************ ++** Disable the interrupt(s) associated with the cradle ++************************************************************************/ ++static void cradle_disable_interrupt(void) ++{ ++ /* printk(KERN_INFO "cradle: interrupts disabled\n"); */ ++} ++ ++/************************************************************************ ++** ++************************************************************************/ ++static void cradle_docked_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ cradle_dev_t *dev=dev_id; ++ ++ /* printk(KERN_INFO "cradle: docked irq\n"); */ ++ ++ /* Reset the interrupt request */ ++ ++ /* Get the state */ ++ *dev->ibuf_wp=read_docking_state(); ++ cradle_update_buffer(&dev->ibuf_wp, 1, dev->ibuf, CRADLE_IBUF_SIZE); ++ ++ /* Notify any asynchronous readers */ ++ if( dev->fasync ) ++ { ++ /* printk(KERN_INFO "cradle: kill_fasync()\n"); */ ++ kill_fasync(dev->fasync, SIGIO, POLL_IN); ++ } ++ ++ wake_up_interruptible( &dev->wait_inq ); ++ ++ /* Schedule the bottom-half */ ++ /* tasklet_schedule(&cradle_tasklet_docked); */ ++} ++ ++/************************************************************************ ++** ++************************************************************************/ ++static void cradle_undocked_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ cradle_dev_t *dev=dev_id; ++ ++ /* printk(KERN_INFO "cradle: undocked irq\n"); */ ++ ++ /* Reset the interrupt request */ ++ ++ /* Get the state */ ++ *dev->ibuf_wp=read_docking_state(); ++ cradle_update_buffer(&dev->ibuf_wp, 1, dev->ibuf, CRADLE_IBUF_SIZE); ++ ++ /* Notify any asynchronous readers */ ++ if( dev->fasync ) ++ { ++ /* printk(KERN_INFO "cradle: kill_fasync()\n"); */ ++ kill_fasync(dev->fasync, SIGIO, POLL_IN); ++ } ++ ++ wake_up_interruptible( &dev->wait_inq ); ++ ++ /* Schedule the bottom-half */ ++ /* tasklet_schedule(&cradle_tasklet_undocked); */ ++} ++ ++/************************************************************************* ++** Bottom-half processing ++*************************************************************************/ ++void cradle_do_tasklet_docked(unsigned long data) ++{ ++ printk(KERN_INFO "cradle: tasklet\n"); ++} ++ ++ ++/************************************************************************* ++** Bottom-half processing ++*************************************************************************/ ++void cradle_do_tasklet_undocked(unsigned long data) ++{ ++ printk(KERN_INFO "cradle: tasklet undocked\n"); ++} ++#endif ++ ++/************************************************************************ ++** Open the cradle device ++************************************************************************/ ++static int cradle_open(struct inode *inode, struct file *filp) ++{ ++ cradle_dev_t *dev; ++ int status; ++ ++ /* printk(KERN_INFO "cradle: open()\n"); */ ++ ++ /* Initialize the device information */ ++ dev=(cradle_dev_t *)filp->private_data; ++ if(!dev) ++ { ++ dev=&cradle_dev; ++ filp->private_data=dev; ++ } ++ ++ if( dev->users++ ) return 0; ++ ++ MOD_INC_USE_COUNT; ++ ++ /* allocate the buffers */ ++ dev->ibuf=(char *)kmalloc(CRADLE_IBUF_SIZE,GFP_KERNEL); ++ if( !dev->ibuf ) ++ { ++ MOD_DEC_USE_COUNT; ++ return -ENOMEM; ++ } ++ ++ /* clear the buffers */ ++ dev->ibuf_wp=dev->ibuf_rp=dev->ibuf; ++ ++ /* mark the device ready */ ++ dev->ready=1; ++ ++ /* Install the interrupt handler(s) */ ++ ++ /* Enable the interrupts */ ++ //cradle_enable_interrupt(); ++ ++ ++ return 0; ++} ++ ++/************************************************************************ ++** Release the cradle device ++************************************************************************/ ++static int cradle_release(struct inode *inode, struct file *filp) ++{ ++ ++ cradle_dev_t *dev=(cradle_dev_t *)filp->private_data; ++ ++ /* printk(KERN_INFO "cradle: release\n"); */ ++ ++ if( --dev->users ) return 0; ++ ++ //cradle_disable_interrupt(); ++ ++ //free the irq ++ ++ /* release any asynchronous readers */ ++ cradle_fasync(-1,filp,0); ++ ++ /* free up resources */ ++ kfree(dev->ibuf); ++ ++ ++ MOD_DEC_USE_COUNT; ++ ++ return 0; ++} ++ ++/************************************************************************ ++** Read the cradle device ++** ++** This implementation supports both non-blocking and blocking i/o. ++************************************************************************/ ++static ssize_t cradle_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) ++{ ++ cradle_dev_t *dev=(cradle_dev_t *)filp->private_data; ++ wait_queue_t wait; ++ ++ /* printk(KERN_INFO "cradle: read()\n"); */ ++ ++ /* unseekable device */ ++ if( f_pos!=&filp->f_pos ) ++ return -ESPIPE; ++ ++ /* ++ ** safe implementation of sleeping that avoids race conditions ++ */ ++ ++ /* init our local wait queue */ ++ init_waitqueue_entry(&wait, current); ++ ++ /* add out queue to the drivers queue */ ++ add_wait_queue(&dev->wait_inq, &wait); ++ ++ while( 1 ) ++ { ++ /* tell the schedule we are asleep (even though we aren't yet) */ ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ /* check for available data */ ++ if( dev->ibuf_wp != dev->ibuf_rp ) ++ { ++ break; ++ } ++ ++ if( filp->f_flags & O_NONBLOCK ) ++ { ++ remove_wait_queue(&dev->wait_inq, &wait); ++ set_current_state(TASK_RUNNING); ++ return -EAGAIN; ++ /* return -EWOULDBLOCK; */ ++ } ++ ++ /* check to see if it is a signal */ ++ if( signal_pending(current)) ++ { ++ remove_wait_queue(&dev->wait_inq, &wait); ++ set_current_state(TASK_RUNNING); ++ return -ERESTARTSYS; ++ } ++ ++ /* allow other processes to run (we'll go to sleep) */ ++ schedule(); ++ } ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&dev->wait_inq, &wait); ++ ++ /* calculate how much data is available */ ++ if( dev->ibuf_wp > dev->ibuf_rp ) ++ count=min(count, dev->ibuf_wp - dev->ibuf_rp ); ++ else ++ count=min(count, (dev->ibuf+CRADLE_IBUF_SIZE) - dev->ibuf_rp ); ++ ++ /* printk("cradle: read() %d available\n", count); */ ++ ++ /* copy the data to user space */ ++ if( copy_to_user(buf, dev->ibuf_rp, count) ) ++ { ++ return -EFAULT; ++ } ++ ++ /* manager the buffer pointers */ ++ cradle_update_buffer(&dev->ibuf_rp, count, dev->ibuf, CRADLE_IBUF_SIZE); ++ ++ ++ return count; ++} ++ ++/************************************************************************ ++** Poll/select the cradle device ++************************************************************************/ ++static unsigned int cradle_poll(struct file *filp, poll_table *wait) ++{ ++ cradle_dev_t *dev=filp->private_data; ++ unsigned int mask=0; ++ ++ poll_wait(filp, &dev->wait_inq, wait); ++ ++ /* check for readable */ ++ if( dev->ibuf_wp != dev->ibuf_rp ) ++ mask |= POLLIN | POLLRDNORM; ++ ++ return mask; ++} ++ ++/************************************************************************ ++** IOCTL interface for the cradle device ++************************************************************************/ ++static int cradle_ioctl(struct inode *inode, struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ int docking_state; ++ int retval=0; ++ ++ /* printk(KERN_INFO "cradle: ioct %d\n", cmd); */ ++ ++ switch(cmd) ++ { ++ case CRADLE_GET_DOCKING_STATE_IOCTL: ++ docking_state=read_docking_state(); ++ //this code is here temporarily until ++ // a timer is added to check the state and set ++ // the LED automatically ++ if(docking_state == CRADLE_DOCKED_STATE) ++ { ++ // turn on dock led ++ GPIOF->dr |= 0x40; ++ } ++ else ++ { ++ // turn off dock led ++ GPIOF->dr &= ~0x40; ++ } ++ ++ retval=put_user(docking_state, (int *)arg); ++ ++ break; ++ default: ++ printk(KERN_INFO "cradle: unknown ioctl %d\n", cmd); ++ retval=-1; ++ break; ++ } ++ ++ return retval; ++} ++ ++/************************************************************************ ++** Aynchronous i/o support for the cradle device ++************************************************************************/ ++static int cradle_fasync(int fd, struct file *filp, int on ) ++{ ++ int retval; ++ cradle_dev_t *dev=filp->private_data; ++ ++ /* ++ printk(KERN_INFO "cradle: fasync fd=%d filp=0x%08x mode=%d\n", ++ fd, (unsigned int) filp, on ); ++ */ ++ ++ retval=fasync_helper(fd, filp, on, &dev->fasync); ++ if( retval < 0 ) ++ return retval; ++ else ++ return 0; ++} ++ ++/************************************************************************ ++** Initialize the cradle interface and the hardware associated with the ++** cradle. ++** ++** This configuration is specific to the hardware design for the ++** Touchblock device. Moreover, this configuration *must* match the ++** configuration of the MIPS interrupt handler. ++************************************************************************/ ++void cradle_init(void) ++{ ++ int retval; ++ int cradle_major = 0; ++ ++ /* register the device */ ++ retval=register_chrdev( cradle_major, "cradle", &cradle_fops ); ++ if( retval < 0 ) ++ { ++ printk(KERN_WARNING "cradle: Failed to register device\n"); ++ } ++ if (cradle_major == 0) ++ { ++ cradle_major = retval; /* Dynamic Allocation of major number */ ++ printk("<4>Cradle Dynamic Major Number %d\n",cradle_major); ++ } ++ ++ ++ /* initialize the device structure */ ++ memset( &cradle_dev, 0, sizeof( cradle_dev_t ) ); ++ init_waitqueue_head(&cradle_dev.wait_inq); ++ ++ ++ /* printk(KERN_INFO "cradle: initalized\n"); */ ++} ++ ++/************************************************************************ ++** ++** Since the cradle device is statically compiled into the kernel this ++** is not really used. However, when the driver switches to loadable ++** modules this should be the basis of the ++** module cleanup routine. ++************************************************************************/ ++void cradle_cleanup(void) ++{ ++ /* unregister the device */ ++ unregister_chrdev( CRADLE_MAJOR, "cradle"); ++ ++ ++ /* printk(KERN_INFO "cradle: cleanup\n"); */ ++} ++ ++ ++module_init(cradle_init); ++module_exit(cradle_cleanup); +diff -urN linux-2.4.26/drivers/char/lh79520_wdt.c linux-2.4.26-vrs1-lnode80/drivers/char/lh79520_wdt.c +--- linux-2.4.26/drivers/char/lh79520_wdt.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/lh79520_wdt.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,259 @@ ++/* ++ * Watchdog driver for the LH79520 ++ * ++ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> ++ * Based on SoftDog driver by Alan Cox <alan@redhat.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide ++ * warranty for any of this software. This material is provided ++ * "AS-IS" and at no charge. ++ * ++ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu> ++ * ++ * 27/11/2000 Initial release ++ */ ++ ++#include <linux/module.h> ++#include <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/fs.h> ++#include <linux/mm.h> ++#include <linux/miscdevice.h> ++#include <linux/watchdog.h> ++#include <linux/reboot.h> ++#include <linux/smp_lock.h> ++#include <linux/init.h> ++#include <asm/uaccess.h> ++#include <asm/hardware.h> ++#include <asm/bitops.h> ++ ++#include "lh79520_wdt.h" ++ ++unsigned int hclkfreq_get( void); ++ ++#define TIMER_MARGIN 60 /* default in seconds */ ++#ifdef OLDWAY ++#define PCLK 51609600 /* ticks per second of AHB clock, 51MHz */ ++#else ++#define PCLK hclkfreq_get() ++#endif ++#define SLEEP_TIME 10 /* number of seconds between each counter reload */ ++ ++static int lh79520_margin = TIMER_MARGIN; /* in seconds */ ++static int lh79520wdt_users; /* mutex */ ++#ifdef FIQ_ENABLED ++static int irq = 0x1c; /* FIQ. Normally 0x18 for standard irq */ ++#else ++static int irq = 0x18; /* IRQ. Normally the FIQ is 0x1c */ ++#endif ++ ++#define WDTBase 0xFFFE3000L /* Base Address for all LH79520 Watchdog Registers */ ++WDTIMERREGS *wtdregs = (WDTIMERREGS *) WDTBase; ++ ++#ifdef MODULE ++MODULE_PARM(lh79520_margin,"i"); ++#endif ++ ++/* ++ * Allow only one person to hold it open ++ */ ++ ++static int lh79520dog_open(struct inode *inode, struct file *file) ++{ ++ if(test_and_set_bit(1,&lh79520wdt_users)) ++ return -EBUSY; ++ MOD_INC_USE_COUNT; ++ ++ if ((lh79520_margin > (PCLK / 0xffffffff)) || /* 83 seconds max, 20 sec min margin */ ++ (lh79520_margin <= SLEEP_TIME * 2)) ++ lh79520_margin = TIMER_MARGIN; ++ ++/* setting bits 7-4 of WDCTLR to 0x0 through 0xF sets the *initial* counter value upon a reset */ ++/* 0x0 is 2^16 tics of PCLK, or reset immediatly, 0x10 is 2^17 tics of PCLK, ... */ ++/* 0xF is 2^31 tics of PCLK, if PCLK is 51 MHz, 2^31 / 51 MHz = 41.6 seconds */ ++/* WDCTLR=0xF, the F sets initial counter to 41.6 seconds (assuming PCLK is 51 MHz) */ ++/* The counter will be set to the user selected margin the first time a reload occurs */ ++ wtdregs->wdctlr |= 0xF0; ++ ++ /* Activate LH79520 Watchdog timer */ ++ wtdregs->wdctlr |= WDT_CTRL_ENABLE; ++ ///wtdregs->wdctlr |= WDT_CTRL_FRZ_ENABLE; ++ // The 1 sets the enable bit (bit 0) to 1 enabling the watchdog fuctionality ++ // The freeze or lock bit (bit 4) makes bit 0 read-only (to avoid accidental disabling) ++ // Bit 1 is left at 0 signifing that when the counter reaches 0, a machine reset occurs ++ // If bit 1 were 1, then the first time the counter reached 0 an interrupt occurs, and ++ // the second time the counter reaches 0 the machine is reset. ++ ++ // Now reset Watchdog to let the above settings take effect ++ wtdregs->wdcntr = WDT_WDCNTR; // 0x1984 is a special reset value ++ return 0; ++} ++ ++static int lh79520dog_release(struct inode *inode, struct file *file) ++{ ++ /* ++ * Shut off the timer. ++ * Lock it in if it's a module and we defined ...NOWAYOUT ++ */ ++ ///wtdregs->wdctr |= 0x0; // turns off bit 4 the freeze lock so we can write to bit 0 ++ wtdregs->wdctlr |= WDT_CTRL_DISABLE; // turns off watchdog bit 0 ++ ++ lh79520wdt_users = 0; ++ MOD_DEC_USE_COUNT; ++ return 0; ++} ++ ++static ssize_t lh79520dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) ++{ ++ /* Can't seek (pwrite) on this device */ ++ if (ppos != &file->f_pos) ++ return -ESPIPE; ++ ++ /* Refresh/reload counter */ ++ if(len) { ++ unsigned int count = (lh79520_margin * PCLK); ++ wtdregs->wdcnt3 = count && 0xFF000000; ++ wtdregs->wdcnt2 = count && 0x00FF0000; ++ wtdregs->wdcnt1 = count && 0x0000FF00; ++ wtdregs->wdcnt0 = count && 0x000000FF; ++ return 1; ++ } ++ return 0; ++} ++ ++static int lh79520dog_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ static struct watchdog_info ident = { ++ identity: "LH79520 Watchdog", ++ }; ++ ++ switch(cmd){ ++ default: ++ return -ENOIOCTLCMD; ++ case WDIOC_GETSUPPORT: ++ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)); ++ case WDIOC_GETSTATUS: ++ return put_user(0,(int *)arg); ++ case WDIOC_GETBOOTSTATUS: /* 1 = last reboot was cause by watchdog, 0 means no */ ++ return put_user( ! (wtdregs->wdtstr & WDT_WD_NWDRES), (int *)arg); ++ case WDIOC_KEEPALIVE: ++ { ++ unsigned int count = (lh79520_margin * PCLK); ++ wtdregs->wdcnt3 = count && 0xFF000000; ++ wtdregs->wdcnt2 = count && 0x00FF0000; ++ wtdregs->wdcnt1 = count && 0x0000FF00; ++ wtdregs->wdcnt0 = count && 0x000000FF; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * lh79520dog_interrupt: ++ * @irq: Interrupt number ++ * @dev_id: Unused as we don't allow multiple devices. ++ * @regs: Unused. ++ * ++ * Handle an interrupt from the board. These are raised when the status ++ * map changes in what the board considers an interesting way. That means ++ * a failure condition occuring. ++ */ ++ ++void lh79520dog_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ /* ++ * Read the status register see what is up and ++ * then printk it. ++ */ ++ ++ unsigned char status=wtdregs->wdtstr; ++ ++/* status|=FEATUREMAP1; ++ status&=~FEATUREMAP2; */ ++ ++ printk(KERN_CRIT "WDT status %d\n", status); ++ ++ wtdregs->wdcntr = WDT_WDCNTR; // 0x1984 is a special reset value ++/* ++ if(!(status&WDC_SR_TGOOD)) ++ printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); ++ if(!(status&WDC_SR_PSUOVER)) ++ printk(KERN_CRIT "PSU over voltage.\n"); ++ if(!(status&WDC_SR_PSUUNDR)) ++ printk(KERN_CRIT "PSU under voltage.\n"); ++ if(!(status&WDC_SR_FANGOOD)) ++ printk(KERN_CRIT "Possible fan fault.\n"); ++ if(!(status&WDC_SR_WCCR)) ++#ifdef SOFTWARE_REBOOT ++#ifdef ONLY_TESTING ++ printk(KERN_CRIT "Would Reboot.\n"); ++#else ++ printk(KERN_CRIT "Initiating system reboot.\n"); ++ machine_restart(NULL); ++#endif ++#else ++ printk(KERN_CRIT "Reset in 5ms.\n"); ++#endif ++*/ ++} ++ ++ ++static struct file_operations lh79520dog_fops= ++{ ++ owner: THIS_MODULE, ++ write: lh79520dog_write, ++ ioctl: lh79520dog_ioctl, ++ open: lh79520dog_open, ++ release: lh79520dog_release, ++}; ++ ++static struct miscdevice lh79520dog_miscdev= ++{ ++ WATCHDOG_MINOR, ++ "LH79520 watchdog", ++ &lh79520dog_fops ++}; ++ ++static int __init lh79520dog_init(void) ++{ ++ int ret; ++ ++ ret = misc_register(&lh79520dog_miscdev); ++ ++ if (ret) ++ { ++ goto out; ++ } ++ ++// ret = request_irq(irq, lh79520dog_interrupt, SA_INTERRUPT, "lh79520wdt", NULL); ++// if(ret) { ++// printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); ++// goto outmisc; ++// } ++ ++ printk("LH79520 Watchdog Timer: timer margin %d sec\n", lh79520_margin); ++ ++ ret=0; ++ out: ++ return ret; ++ ++ outmisc: ++ misc_deregister(&lh79520dog_miscdev); ++ goto out; ++ ++} ++ ++static void __exit lh79520dog_exit(void) ++{ ++ misc_deregister(&lh79520dog_miscdev); ++} ++ ++module_init(lh79520dog_init); ++module_exit(lh79520dog_exit); +diff -urN linux-2.4.26/drivers/char/lh79520_wdt.h linux-2.4.26-vrs1-lnode80/drivers/char/lh79520_wdt.h +--- linux-2.4.26/drivers/char/lh79520_wdt.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/lh79520_wdt.h 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,63 @@ ++/********************************************************************** ++ * $Workfile: LH79520_wdt.h $ ++ * $Revision: 1.1.1.1 $ ++ * $Author: brad $ ++ * $Date: 2003/01/04 17:20:29 $ ++ * ++ * Project: LH79520 headers ++ * ++ * Description: ++ * This file contains the structure definitions and manifest ++ * constants for LH79520 component: ++ * Watchdog Timer ++ * ++ * References: ++ * (1) ARM Isis Technical Reference Manual, System on Chip Group, ++ * ARM SC063-TRM-0001-B ++ * ++ * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC. ++ * CAMAS, WA ++ *********************************************************************/ ++ ++#ifndef LH79520_WDT_H ++#define LH79520_WDT_H ++ ++/* ++ * Watchdog Timer Module Register Structure ++ */ ++typedef struct { ++ volatile unsigned int wdctlr; /* Control */ ++ volatile unsigned int wdcntr; /* Counter Reset */ ++ volatile unsigned int wdtstr; /* Test */ ++ volatile unsigned int wdcnt0; /* Counter Bits [7:0] */ ++ volatile unsigned int wdcnt1; /* Counter Bits [15:8] */ ++ volatile unsigned int wdcnt2; /* Counter Bits [23:16] */ ++ volatile unsigned int wdcnt3; /* Counter Bits [31:24] */ ++} WDTIMERREGS; ++ ++/********************************************************************** ++ * Watchdog Timer Register Bit Fields ++ *********************************************************************/ ++ ++/********************************************************************** ++ * Watchdog Control Register Bit Fields ++ *********************************************************************/ ++#define WDT_CTRL_DISABLE 0 ++#define WDT_CTRL_ENABLE _SBF(0,1) ++#define WDT_CTRL_RSP_FIQ _SBF(1,0) ++#define WDT_CTRL_RSP_RESET _SBF(1,1) ++#define WDT_CTRL_FRZ_ENABLE _BIT(3) ++#define WDT_CTRL_TOP _SBF(4,((n)&0xF) ++ ++/********************************************************************** ++ * Watchdog Counter Reset Register Bit Fields ++ *********************************************************************/ ++#define WDT_WDCNTR (0x1984) ++ ++/********************************************************************** ++ * Watchdog Register Bit Fields ++ *********************************************************************/ ++#define WDT_WD_NWDFIQ _BIT(7) ++#define WDT_WD_NWDRES _BIT(6) ++ ++#endif /* LH79520_WDT_H */ +diff -urN linux-2.4.26/drivers/char/Makefile linux-2.4.26-vrs1-lnode80/drivers/char/Makefile +--- linux-2.4.26/drivers/char/Makefile 2005-11-02 16:54:20.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/Makefile 2005-11-02 17:37:31.000000000 -0400 +@@ -16,7 +16,7 @@ + + O_TARGET := char.o + +-obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o ++obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o cradle.o + + # All of the (potential) objects that export symbols. + # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. +@@ -349,6 +349,7 @@ + obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o + obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o + obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o ++obj-$(CONFIG_LH79520_WATCHDOG) += lh79520_wdt.o + obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o + obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o + obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o +@@ -359,6 +360,12 @@ + # I2C char devices + obj-$(CONFIG_I2C_DS1307) += ds1307.o + ++# Specific to the LH79520 Sharp dev board. ++# Controls both PWM0 and PWM1 ++# PWM0 is the backlighting ++# PWM1 is the audio ++obj-$(CONFIG_LH79520_PWM) += pwm520.o ++ + subdir-$(CONFIG_MWAVE) += mwave + ifeq ($(CONFIG_MWAVE),y) + obj-y += mwave/mwave.o +diff -urN linux-2.4.26/drivers/char/pwm520.c linux-2.4.26-vrs1-lnode80/drivers/char/pwm520.c +--- linux-2.4.26/drivers/char/pwm520.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/pwm520.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,870 @@ ++/* ++ * linux/drivers/char/pwm520.c ++ * ++ * Copyright (C) 2002 Lineo. ++ * ++ * Original code write was authored by Craig Matsuura <cmatsuura@lineo.com> ++ * Parts of this code are from Sharp. ++ * This code falls under the license of the GPL. ++ * ++ * This modules is for controlling the PWM audio and backlighting. ++ * Jumps for backlighting and audio must be set correctly on the LH79520 ++ * Board for this module to work properly. See Sharp LH79520 Documentation ++ * for jumper settings. ++ */ ++//#define MODULES ++#include <linux/config.h> ++#include <linux/delay.h> ++#include <linux/types.h> ++#include <linux/fcntl.h> ++#include <linux/fs.h> ++#include <linux/init.h> ++#include <linux/ioctl.h> ++#include <asm/irq.h> ++#include <asm/segment.h> ++#include <asm/uaccess.h> ++#include <linux/module.h> ++//#include <limits.h> ++#include <asm/arch/rcpc.h> ++#include <asm/arch/iocon.h> ++#include <asm/arch/hardware.h> ++ ++#include "pwm520.h" ++ ++pwmRegs_t *pwmregs = (pwmRegs_t *) IO_ADDRESS( PWM_PHYS); ++ioconRegs_t *ioconregs = (ioconRegs_t *)IO_ADDRESS( IOCON_PHYS); ++rcpcRegs_t *rcpcregs = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ ++#define TYPE(dev) (MINOR(dev) >> 4) /* high nibble */ ++#define NUM(dev) (MINOR(dev) & 0xf) /* low nibble */ ++#if OLDWAY ++#define PCLK 51609600 /* ticks per second of AHB clock, 51MHz */ ++static int pwm_xtal_freq = XTAL_IN; // From hardware.h ++static int pwm_clkin_freq = 0; // PLL_CLOCK? LH79520_CLKIN_FREQ; ++#else ++unsigned int hclkfreq_get( void); ++#endif ++ ++static int pwm_major = 0; // Major Number for Driver 0 indicates dynamic assignment ++static int pwm_prescale = 1; ++ ++// Default Freq and Duty Cycles ++static int pwm_audio_freq = 440; // Freq of tone ++static int pwm_audio_dcycle = 50; // Duty Cycle for Audio ++static int pwm_audio_duration = 100000;// Delay (udelay) for beep ++ ++static int pwm_backlight_dcycle = 100;// DC for Backlight ++static int pwm_backlight_mode = 0; // Normal Mode ++static int pwm_backlight_freq = BACKLIGHT_INVERTER_PWM_FREQUENCY; // Freq of backlight ++ ++#ifdef MODULES ++MODULE_PARM(pwm_major,"i"); ++MODULE_PARM(pwm_prescale,"i"); ++MODULE_PARM(pwm_xtal_freq,"i"); ++MODULE_PARM(pwm_clkin_freq,"i"); ++MODULE_PARM(pwm_audio_freq,"i"); ++MODULE_PARM(pwm_audio_dcycle,"i"); ++MODULE_PARM(pwm_audio_duration,"i"); ++MODULE_PARM(pwm_backlight_dcycle,"i"); ++MODULE_PARM(pwm_backlight_mode,"i"); ++MODULE_PARM(pwm_backlight_freq,"i"); ++#endif ++ ++ ++//void showPWM0Registers(); ++ ++#if OLDWAY ++/********************************************************************** ++* ++* Function: rcpc_get_bus_clock - From Sharp Source ++* ++* Purpose: ++* return the frequency of the bus clock. ++* ++* Processing: ++* this function returns the frequency of the bus clock in Hz ++* based on the value of frequencies passed in and the value ++* of the RCPC control register CLK_SEL bit. ++* ++* Parameters: ++* xtalin: the frequency at the XTALIN pin; use 0 if there is no ++* crystal or external clock driving the pin. ++* clkin: the frequency driving the CLKIN pin; use 0 if that pin ++* is not driven. ++* ++* Outputs: None ++* ++* Returns: ++* The bus clock frequency in Hz ++* ++* Notes: ++* The nominal crystal input frequency in 14745600 Hz. ++* ++**********************************************************************/ ++volatile unsigned long rcpc_get_bus_clock(unsigned long xtalin, unsigned long clkin) ++{ ++ unsigned long timebase, divider; ++ ++ if ( (rcpcregs->control & RCPC_CTRL_CLKSEL_EXT) ++ == RCPC_CTRL_CLKSEL_EXT) ++ { ++ /* clock source is external clock */ ++ timebase = clkin; ++ } ++ else ++ { ++ /* clock source is from PLL output */ ++ timebase = xtalin * 21; ++ } ++ ++ divider = rcpcregs->HCLKPrescale * 2; ++ if (divider == 0) ++ divider = 1; ++ ++ return timebase / divider; ++} ++#endif // OLDWAY ++ ++/********************************************************************** ++* ++* Function: pwm1_enable - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Enable PWM output on the PWM1 channel of the LH79520 ++* ++* Processing: ++* N/A ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++inline volatile void pwm1_enable(void) ++{ ++ pwmregs->pwm1.enable = PWM_EN_ENABLE; ++} ++ ++/********************************************************************** ++* ++* Function: pwm1_disable - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Disable PWM output on the PWM1 channel of the LH79520 ++* ++* Processing: ++* N/A ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++inline volatile void pwm1_disable(void) ++{ ++ pwmregs->pwm1.enable = ~PWM_EN_ENABLE; ++} ++ ++/********************************************************************** ++* ++* Function: pwm0_enable - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Enable PWM output on the PWM0 channel of the LH79520 ++* ++* Processing: ++* N/A ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++inline volatile void pwm0_enable(void) ++{ ++ pwmregs->pwm0.enable = PWM_EN_ENABLE; ++} ++ ++/********************************************************************** ++* ++* Function: pwm0_disable - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Disable PWM output on the PWM0 channel of the LH79520 ++* ++* Processing: ++* N/A ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++inline volatile void pwm0_disable(void) ++{ ++ pwmregs->pwm0.enable = ~PWM_EN_ENABLE; ++} ++ ++/********************************************************************** ++* ++* Function: pwm0_normal - Taken for Sharp Driver Example code146 ++* ++* Purpose: ++* Restores the normal sense of the PWM output signal on the PWM0 ++* channel of the LH79520 ++* ++* Processing: ++* N/A ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++inline volatile void pwm0_normal(void) ++{ ++ pwmregs->pwm0.invert = ~PWM_INV_INVERT; ++} ++ ++ ++/********************************************************************** ++* ++* Function: pwm1_frequency - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Sets the PWM1 output frequency to the value specified ++* ++* Processing: ++* Compute the prescale and period count to be programmed from the ++* PCLK frequency. If the frequency value is too high or too low to ++* be programmed within the permissible ranges of prescale and period, ++* signal an error. ++* ++* Parameters: ++* freq - Desired frequency, in Hz ++* ++* Outputs: None ++* ++* Returns: ++* -1 - if frequency specified is zero ++* -1 - if prescale is zero (an impossible condition) ++* -1 - if the frequency is out of bounds ++* 0 - if the frequency is changed successfully ++* ++* Notes: ++* This function depends on the values of LH79520_XTAL_FREQ and ++* LH79520_CLKIN_FREQ to be set correctly in the LH79520_evb.h file. ++* If external clock is used, LH79520_CLKIN_FREQ should be set ++* to the external clock frequency. Otherwise, this function will ++* fail. ++* ++* ++**********************************************************************/ ++long pwm1_frequency(unsigned long freq) ++{ ++ unsigned long pclk, pwm1clk, prescale; ++ unsigned long div; ++ ++ if (0 == freq) { ++ return -1; ++ } ++ ++#if OLDWAY ++ pclk = rcpc_get_bus_clock(pwm_xtal_freq,pwm_clkin_freq); ++#else ++ pclk = hclkfreq_get(); ++#endif ++ prescale = rcpcregs->PWM1Prescale; ++ if (prescale > 0) { ++ pwm1clk = pclk / (prescale * 2); ++ } else { ++ printk("<4>THIS IS BAD. SHOULD NOT GET HERE...\n"); ++ //this should not happen ++ return -1; ++ } ++ div = pwm1clk / freq; ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ ++ while (div > USHRT_MAX && prescale <= SHRT_MAX) { ++ prescale += 1; ++ rcpcregs->PWM1Prescale = prescale; ++ pwm1clk = pclk / (prescale * 2); ++ div = pwm1clk / freq; ++ } ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ pwmregs->pwm1.tc = div; ++ ++ return 0; ++} ++ ++ ++/********************************************************************** ++* ++* Function: pwm1_duty_cycle - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Sets the PWM1 duty cycle to the value specified ++* ++* Processing: ++* Compute the duty cycle count to program into the dc register ++* from the percentage specified and the tc count. Accounts for ++* integer division truncation errors. ++* ++* Parameters: ++* dcpercent - Desired duty cycle as a percentage of the total period ++* ++* Outputs: None ++* ++* Returns: ++* the previous value of the duty cycle, as a percentage ++* ++* Notes: ++* ++**********************************************************************/ ++long pwm1_duty_cycle(short dcpercent) ++{ ++ unsigned short period; ++ unsigned long duty_cycle, prev_dc, prev_dc_percent; ++ period = (unsigned short) pwmregs->pwm1.tc; ++ prev_dc = pwmregs->pwm1.dc; ++ if (period > 0) { ++ prev_dc_percent = ((prev_dc * 100) + (period >> 1)) / period; ++ } else { ++ prev_dc_percent = 100; ++ } ++ duty_cycle = ((dcpercent * period) + 50) / 100; ++ pwmregs->pwm1.dc = duty_cycle; ++ return(long)prev_dc_percent; ++} ++ ++/********************************************************************** ++* ++* Function: pwm0_frequency - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Sets the PWM0 output frequency to the value specified ++* ++* Processing: ++* Compute the prescale and period count to be programmed from the ++* PCLK frequency. If the frequency value is too high or too low to ++* be programmed within the permissible ranges of prescale and period, ++* signal an error. ++* ++* Parameters: ++* freq - Desired frequency, in Hz ++* ++* Outputs: None ++* ++* Returns: ++* -1 - if frequency specified is zero ++* -1 - if prescale is zero (an impossible condition) ++* -1 - if the frequency is out of bounds ++* 0 - if the frequency is changed successfully ++* ++* Notes: ++* This function depends on the values of LH79520_XTAL_FREQ and ++* LH79520_CLKIN_FREQ to be set correctly in the LH79520_evb.h file. ++* If external clock is used, LH79520_CLKIN_FREQ should be set ++* to the external clock frequency. Otherwise, this function will ++* fail. ++* ++* ++**********************************************************************/ ++long pwm0_frequency(unsigned long freq) ++{ ++ unsigned long pclk, pwm0clk, prescale; ++ unsigned long div; ++ ++ if (0 == freq) { ++ return -1; ++ } ++ ++#if OLDWAY ++ pclk = rcpc_get_bus_clock(pwm_xtal_freq,pwm_clkin_freq); ++#else ++ pclk = hclkfreq_get(); ++#endif ++ prescale = rcpcregs->PWM0Prescale; ++ if (prescale > 0) { ++ pwm0clk = pclk / (prescale * 2); ++ } else { ++ printk("<4>THIS IS BAD. SHOULD NOT GET HERE...\n"); ++ //this should not happen ++ return -1; ++ } ++ div = pwm0clk / freq; ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ ++ //FJB hack for orderite ++ rcpcregs->PWM0Prescale = 0x0a; ++#if 0 ++ while (div > USHRT_MAX && prescale <= SHRT_MAX) { ++ prescale += 1; ++ rcpcregs->PWM0Prescale = prescale; ++ pwm0clk = pclk / (prescale * 2); ++ div = pwm0clk / freq; ++ } ++#endif ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ //pwmregs->pwm0.tc = div; ++ pwmregs->pwm0.tc = 0x285; ++ ++ return 0; ++} ++ ++ ++/********************************************************************** ++* ++* Function: pwm0_duty_cycle - Taken for Sharp Driver Example code ++* ++* Purpose: ++* Sets the PWM0 duty cycle to the value specified ++* ++* Processing: ++* Compute the duty cycle count to program into the dc register ++* from the percentage specified and the tc count. Accounts for ++* integer division truncation errors. ++* ++* Parameters: ++* dcpercent - Desired duty cycle as a percentage of the total period ++* ++* Outputs: None ++* ++* Returns: ++* the previous value of the duty cycle, as a percentage ++* ++* Notes: ++* ++**********************************************************************/ ++long pwm0_duty_cycle(short dcpercent) ++{ ++ unsigned short period; ++ unsigned long duty_cycle, prev_dc, prev_dc_percent; ++ period = (unsigned short) pwmregs->pwm0.tc; ++ prev_dc = pwmregs->pwm0.dc; ++ if (period > 0) { ++ prev_dc_percent = ((prev_dc * 100) + (period >> 1)) / period; ++ } else { ++ prev_dc_percent = 100; ++ } ++ duty_cycle = ((dcpercent * period) + 50) / 100; ++ pwmregs->pwm0.dc = duty_cycle; ++ return(long)prev_dc_percent; ++} ++ ++/********************************************************************** ++* ++* Function: backlight_decrease_brightness ++* ++* Purpose: ++* Decrease the LCD backlight brightness ++* ++* Processing: ++* Decrement static variable holding current brightness level and ++* set the PWM duty cycle. ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++void backlight_increase_brightness(void) ++{ ++ pwm_backlight_dcycle--; ++ if (pwm_backlight_dcycle < 0) ++ { ++ pwm_backlight_dcycle = 0; ++ } ++ pwm0_duty_cycle(pwm_backlight_dcycle); ++} ++ ++/********************************************************************** ++* ++* Function: backlight_increase_brightness ++* ++* Purpose: ++* Increase the LCD backlight brightness ++* ++* Processing: ++* Increment static variable holding current brightness level and ++* set the PWM duty cycle. ++* ++* Parameters: None ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++void backlight_decrease_brightness(void) ++{ ++ pwm_backlight_dcycle++; ++ if (pwm_backlight_dcycle > 100) ++ { ++ pwm_backlight_dcycle = 100; ++ } ++ pwm0_duty_cycle(pwm_backlight_dcycle); ++} ++ ++/********************************************************************** ++* ++* Function: backlight_set_brightness ++* ++* Purpose: ++* Set the LCD backlight brightness to the level specified ++* ++* Processing: ++* N/A ++* ++* Parameters: ++* bright - desired brightness level as a percentage of maximum ++* brightness ++* ++* Outputs: None ++* ++* Returns: Nothing ++* ++* Notes: ++* ++**********************************************************************/ ++void backlight_set_brightness(int bright) ++{ ++ //bright = 0 means least brightness ++ //bright = 100 means max brightness ++ if (bright > 100) ++ { ++ bright = 100; ++ } ++ if (bright < 0) ++ { ++ bright = 0; ++ } ++ ++ pwm_backlight_dcycle = 100 - bright; ++ pwm0_duty_cycle(pwm_backlight_dcycle); ++} ++ ++ ++/**************************************************************************** ++ * Open Function - Open the device either the Backlight or the Audio ++ * /dev/pwm0 c 254 1 is the Backlighting ++ * /dev/pwm1 c 254 0 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 pwm_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: // Audio ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpcregs->periphClkCtrl &= ~RCPC_CLKCTRL_PWM0_DISABLE; ++ rcpcregs->PWM0Prescale = ((~_BIT(15)) & pwm_prescale); ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ ioconregs->MiscMux |= MISCMUX_PWM0; ++ break; ++#if 0 ++ case 1: // Backlight ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpcregs->periphClkCtrl &= ~RCPC_CLKCTRL_PWM1_DISABLE; ++ rcpcregs->PWM0Prescale = ((~_BIT(15)) & pwm_prescale); ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ ioconregs->MiscMux |= MISCMUX_PWM1; ++ ++ if (pwm_backlight_mode) { ++ pwmregs->pwm0.sync = PWM_SYNC_SYNC; ++ ioconregs->MiscMux |= MISCMUX_PWM0SYNC; ++ } ++ else ++ { ++ pwmregs->pwm0.sync = PWM_SYNC_NORMAL; ++ } ++ ++ pwm0_frequency(pwm_backlight_freq); ++ pwm0_duty_cycle(pwm_backlight_dcycle); ++ pwm0_normal(); ++ pwm0_enable(); ++ break; ++#endif ++ default: ++ printk("<4>Minor device unknown %d\n",NUM(inode->i_rdev)); ++ break; ++ } ++ ++ return 0; ++} ++ ++/**************************************************************************** ++ * ++ */ ++int pwm_release(struct inode *inode, struct file * filp) ++{ ++// printk("<4>release pwm...\n"); ++ switch (NUM(inode->i_rdev)) { ++ case 0: // Audio ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpcregs->periphClkCtrl |= RCPC_CLKCTRL_PWM0_DISABLE; ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ ioconregs->MiscMux &= ~MISCMUX_PWM0; ++ pwm0_disable(); ++ break; ++ case 1: // Should be backlight of touchscreen ++ //rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ //barrier(); ++ //rcpcregs->periphClkCtrl |= RCPC_CLKCTRL_PWM0_DISABLE; ++ //rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ //ioconregs->MiscMux &= ~MISCMUX_PWM0; ++ //pwmregs->pwm0.enable = ~PWM_EN_ENABLE; ++ break; ++ ++ default: ++ printk("<4>Minor device unknown %d\n",NUM(inode->i_rdev)); ++ break; ++ } ++ ++ MOD_DEC_USE_COUNT; ++ return 0; ++} ++ ++/**************************************************************************** ++ * ++ */ ++ssize_t pwm_read(struct file * file, char * buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++/**************************************************************************** ++ * ++ */ ++ssize_t pwm_write(struct file * file, const char * buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++/**************************************************************************** ++ * ++ */ ++int pwm_ioctl(struct inode *inode, struct file * file, ++ unsigned int cmd, unsigned long arg) ++{ ++ //int err = 0, size = _IOC_SIZE(cmd); ++ ++ if (_IOC_TYPE(cmd) != PWM520_IOC_MAGIC) { ++ return -EINVAL; ++ } ++ if (_IOC_NR(cmd) > PWM520_IOC_MAXNR) { ++ return -EINVAL; ++ } ++ ++ /* ++ Should check for direction bits see page 101 in "Linux Device Drivers Book" ++ size and err used here. ++ */ ++ ++ switch (NUM(inode->i_rdev)) { ++ case 0: // Audio ++ switch (cmd) { ++ case PWM520_IOCBEEP: ++ pwm0_frequency(pwm_audio_freq); ++ pwm0_duty_cycle(pwm_audio_dcycle); ++ pwm0_enable(); ++ udelay(pwm_audio_duration); ++ pwm0_disable(); ++ break; ++ ++ case PWM520_IOCSTARTSND: ++ pwm0_frequency(pwm_audio_freq); ++ pwm0_duty_cycle(pwm_audio_dcycle); ++ pwm0_enable(); ++ break; ++ ++ case PWM520_IOCSTOPSND: ++ pwm0_disable(); ++ break; ++ ++ case PWM520_IOCSETFREQ: // Set Frequency ++ pwm_audio_freq = arg; ++ break; ++ ++ case PWM520_IOCSETDCYCLE: // Set Duty Cycle ++ pwm_audio_dcycle = arg; ++ break; ++ ++ case PWM520_IOCGETFREQ: // Get Frequency ++ __put_user(pwm_audio_freq, (int *) arg); ++ break; ++ ++ case PWM520_IOCGETDCYCLE: // Get Duty Cycle ++ __put_user(pwm_audio_dcycle, (int *) arg); ++ break; ++ } ++ break; ++#if 0 ++ case 1: // Should be backlight of touchscreen ++ switch (cmd) { ++ case PWM520_IOCRESET: ++// printk("Reset pwm0\n"); ++ pwm_backlight_dcycle = 100;// DC for Backlight ++ pwm_backlight_mode = 0; // Normal Mode ++ pwm_backlight_freq = BACKLIGHT_INVERTER_PWM_FREQUENCY; // Freq of backlight ++ break; ++ case PWM520_IOCSTOPPWM0: // Stop PWM0 ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpcregs->periphClkCtrl |= RCPC_CLKCTRL_PWM0_DISABLE; ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ ioconregs->MiscMux &= ~MISCMUX_PWM0; ++ pwmregs->pwm0.enable = ~PWM_EN_ENABLE; ++ break; ++ case PWM520_IOCINCREASEBL: ++// printk("Brighter\n"); ++ backlight_increase_brightness(); ++ break; ++ ++ case PWM520_IOCDECREASEBL: ++// printk("Lighter\n"); ++ backlight_decrease_brightness(); ++ break; ++ ++ case PWM520_IOCSETBL: ++// printk("Set to %ld\n",arg); ++ backlight_set_brightness(arg); ++ break; ++ } ++ break; ++#endif ++ ++ } ++ ++ return 0; ++} ++ ++ ++/**************************************************************************** ++ * ++ */ ++struct file_operations pwm_fops = { ++ owner: THIS_MODULE, ++ llseek: no_llseek, ++ read: pwm_read, ++ write: pwm_write, ++ ioctl: pwm_ioctl, ++ open: pwm_open, ++ release: pwm_release, ++}; ++ ++#if 0 ++void test_pwm1() ++{ ++ printk("TEST CASE PLEASE REMOVE ONCE DONE\n"); ++ ++ rcpcregs->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpcregs->periphClkCtrl &= ~RCPC_CLKCTRL_PWM1_DISABLE; ++ rcpcregs->PWM1Prescale = ((~_BIT(15)) & pwm_prescale); ++ rcpcregs->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ ioconregs->MiscMux |= MISCMUX_PWM1; ++ ++ pwm1_frequency(pwm_audio_freq); ++ pwm1_duty_cycle(pwm_audio_dcycle); ++ pwm1_enable(); ++} ++ ++void showPWM1Registers() ++{ ++ printk("PWM1 Registers\n"); ++ printk("=============\n\n"); ++ printk("pwm1.tc = %x\n",pwmregs->pwm1.tc); ++ printk("pwm1.dc = %x\n",pwmregs->pwm1.dc); ++ printk("pwm1.enable = %x\n",pwmregs->pwm1.enable); ++ printk("pwm1.invert = %x\n",pwmregs->pwm1.invert); ++ printk("pwm1.sync = %x\n",pwmregs->pwm1.sync); ++} ++ ++void showPWM0Registers() ++{ ++ printk("PWM0 Registers\n"); ++ printk("=============\n\n"); ++ printk("pwm0.tc = %d\n",pwmregs->pwm0.tc); ++ printk("pwm0.dc = %d\n",pwmregs->pwm0.dc); ++ printk("pwm0.enable = 0x%x\n",pwmregs->pwm0.enable); ++ printk("pwm0.invert = 0x%x\n",pwmregs->pwm0.invert); ++ printk("pwm0.sync = 0x%x\n",pwmregs->pwm0.sync); ++} ++ ++#endif ++ ++/**************************************************************************** ++ * ++ */ ++static int __init pwm_init_module(void) ++{ ++ int result; ++ ++ //printk("<1>Start PWM Module\n"); ++ printk("<1>Sharp LH79520 PWM Driver Copyright 2002 Lineo\n"); ++ ++ result = register_chrdev(pwm_major,"pwm",&pwm_fops); ++ if (result < 0) { ++ printk("<4>pwm: can't get major number %d\n",pwm_major); ++ return result; ++ } ++ if (pwm_major == 0) { ++ pwm_major = result; /* Dynamic Allocation of major number */ ++ printk("<4>PWM Dynamic Major Number %d\n",pwm_major); ++ } ++ ++ return 0; ++} ++ ++/**************************************************************************** ++ * ++ */ ++static void __exit pwm_cleanup_module(void) ++{ ++ int result; ++ ++ printk("<1>End PWM Module...\n"); ++ result = unregister_chrdev(pwm_major,"pwm"); ++} ++ ++module_init(pwm_init_module); ++module_exit(pwm_cleanup_module); +diff -urN linux-2.4.26/drivers/char/pwm520.h linux-2.4.26-vrs1-lnode80/drivers/char/pwm520.h +--- linux-2.4.26/drivers/char/pwm520.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/char/pwm520.h 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,58 @@ ++/* ++ * linux/drivers/char/pwm520.h ++ * ++ * Copyright (C) 2002 Lineo. ++ * ++ * Original code write was authored by Craig Matsuura <cmatsuura@lineo.com> ++ * Parts of this code are from Sharp. ++ * This code falls under the license of the GPL. ++ * ++ * This modules is for controlling the PWM audio and backlighting. ++ * Jumps for backlighting and audio must be set correctly on the LH79520 ++ * Board for this module to work properly. See Sharp LH79520 Documentation ++ * for jumper settings. ++ */ ++#ifndef __PWM520_H ++#define __PWM520_H ++ ++typedef struct { ++ volatile unsigned int tc; ++ volatile unsigned int dc; ++ volatile unsigned int enable; ++ volatile unsigned int invert; ++ volatile unsigned int sync; ++ volatile unsigned int res[3]; ++} pwmXRegs_t; ++ ++typedef struct { ++ volatile pwmXRegs_t pwm0; ++ volatile pwmXRegs_t pwm1; ++} pwmRegs_t; ++ ++extern pwmRegs_t *pwmregs; ++ ++#define PWM_EN_ENABLE _BIT(0) ++#define PWM_INV_INVERT _BIT(0) ++#define PWM_SYNC_SYNC _SBF(0,1) ++#define PWM_SYNC_NORMAL _SBF(0,0) ++ ++#define BACKLIGHT_INVERTER_PWM_FREQUENCY (200) // 200Hz ++ ++// IOCTL's ++#define PWM520_IOC_MAGIC 'p' ++#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 linux-2.4.26/drivers/misc/ads784x.c linux-2.4.26-vrs1-lnode80/drivers/misc/ads784x.c +--- linux-2.4.26/drivers/misc/ads784x.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/ads784x.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,1064 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++// #define MODULE ++ ++#define TS_DATA_QTOPIA ++#undef CONFIG_ADS7846 ++ ++/********************************************************************** ++* 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 <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/proc_fs.h> ++#include <linux/smp_lock.h> ++#include <linux/miscdevice.h> ++#include <linux/poll.h> ++ ++#undef DEBUG ++#undef VERBOSE ++#define DRVNAME "ads_784x" ++#include <linux/verbosedebug.h> ++ ++#include <linux/version.h> ++#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,0x1) /* Read X value */ ++#define CTRL_Y _SBF(4,0x5) /* Read Y value */ ++#ifdef CONFIG_ADS7846 ++#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 */ ++#endif // CONFIG_ADS7846 ++ ++// #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_X | CTRL_12BIT | CTRL_DFR | 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) ++#ifdef CONFIG_ADS7846 ++#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) ++#endif // CONFIG_ADS7846 ++ ++/********************************************************************** ++* 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_LH79X ++#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 ++ ++/* ++QTopia data format: ++unsigned char data2[5]; ++data.status=data2[0]; // bit 0x40 is "touch"/left mouse ++data.xpos=(data2[1] << 8) | data2[2]; ++data.ypos=(data2[3] << 8) | data2[4]; ++*/ ++ ++#ifdef TS_DATA_QTOPIA ++#define TS_DATA_STRUCT ++struct tsData_t { ++ unsigned char pressure; ++ unsigned char xhigh; ++ unsigned char xlow; ++ unsigned char yhigh; ++ unsigned char ylow; ++} __attribute__ ((packed)); ++#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 10 ++#define Y_DELTA_MAX 10 ++ ++/* Define the readings we are to take per second (default to 50) */ ++#define SAMPLES_PER_SECOND 10 ++ ++/* ++* 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); ++ void (*chipselect_enable)(void); ++ void (*chipselect_disable)(void); ++ void (*chipselect_manual)(void); ++ ++ 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) ++ ++/********************************************************************** ++* 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; ++ long xcoff, ycoff; ++ ++ vdprintk("ENTER: ads_784x_tsData_add()\n"); ++ next_head = (adsContext->tsDataHead + 1) & (MAX_TS_DATA - 1); ++ if (next_head != adsContext->tsDataTail) { ++#ifndef TS_DATA_QTOPIA ++ 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 ++#else // TS_DATA_QTOPIA ++ adsContext->tsData[adsContext->tsDataHead].pressure = pressure ? 0x40 : 0; ++ adsContext->tsData[adsContext->tsDataHead].xlow = x & 0xFF; ++ adsContext->tsData[adsContext->tsDataHead].xhigh = x >> 8; ++ adsContext->tsData[adsContext->tsDataHead].ylow = y & 0xFF; ++ adsContext->tsData[adsContext->tsDataHead].yhigh = y >> 8; ++#endif // TS_DATA_QTOPIA ++ 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 x_last, y_last; ++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"); ++ ++#define TS_AVG_ITERS 8 ++ ++ /* ++ * 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 ++ */ ++ //FJB ++ adsContext->chipselect_enable(); ++#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); ++ x_1 = adsContext->read(sspContext); ++ adsContext->write(sspContext, ADS_784x_READ_Y); ++ 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); ++ x_2 = adsContext->read(sspContext); ++ adsContext->write(sspContext, ADS_784x_READ_Y); ++ y_2 = adsContext->read(sspContext); ++ ++ //FJB ++ adsContext->chipselect_disable(); ++ ++ /* 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)) ++ || (x_1 == 0) || (y_1 == 0) || (x_2 == 0) || (y_2 == 0)); ++ ++ ++#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; ++ ++ // normalize values ++ // very subject to experimentation ++ ++#if 0 ++ if((x == 0) || (y == 0)) ++ { ++ x = x_last; ++ y = y_last; ++ } ++ else ++ { ++ x_last = x; ++ y_last = y; ++ } ++#endif ++ ++ y = (1 << 12) - y; ++ vdprintk("LEAVE: ads_784x_Read_tsData(x=0x%03x, y=0x%03x)\n", x, y); ++ ads_784x_tsData_add(adsContext, 0x40, x, y); // generate pen up/pen down sequence ++ ads_784x_tsData_add(adsContext, 0x00, 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); ++ vdprintk("TSThrPD: %d\t", pen_down); ++ /* 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 0 ++ 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; ++ } ++#endif ++ 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; ++#if 0 ++ else ++ printk("ads_784x_read: P: %02X X: %4d Y: %4d\n", ++ tsData->pressure & 0x40, (tsData->xhigh << 8) + tsData->xlow, (tsData->yhigh << 8) + tsData->ylow); ++#endif ++ ++ 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; ++ void *ads784x_sspContext = adsContext->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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ ++ //FJB ++ adsContext->chipselect_enable(); ++ ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_BATTERY); ++ sample = adsContext->read(ads784x_sspContext); ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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(ads784x_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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ } ++ sample /= count; ++ milliVolts = (sample * 1000 * 10) / 4096; ++ volts = milliVolts / 1000; ++ hundredthsVolts = (milliVolts - (volts * 1000)) / 10; ++ size = sprintf(buf, "battery: %i %i.%02iV\n", sample, volts, hundredthsVolts); ++ ++ /* Do a dummy read to turn off the internal reference voltage */ ++ /* MUST lock the SSP before accessing it */ ++ adsContext->lock(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_X); ++ sample = adsContext->read(ads784x_sspContext); ++ ++ //FJB ++ adsContext->chipselect_disable(); ++ ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ adsContext->enable_pen_down_irq(ads784x_sspContext); ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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; ++ void *ads784x_sspContext = adsContext->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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ ++ //FJB ++ adsContext->chipselect_enable(); ++ ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP0); ++ sample1 = adsContext->read(ads784x_sspContext); ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP0); ++ sample1 += adsContext->read(ads784x_sspContext); ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_TEMP1); ++ sample91 += adsContext->read(ads784x_sspContext); ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ adsContext->write(ads784x_sspContext, ADS_784x_READ_X); ++ sample1 = adsContext->read(ads784x_sspContext); ++ ++ //FJB ++ adsContext->chipselect_disable(); ++ ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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(ads784x_sspContext, SSP_DEV_TOUCHSCREEN); ++ adsContext->enable_pen_down_irq(ads784x_sspContext); ++ /* MUST unlock the SSP after it has been locked */ ++ adsContext->unlock(ads784x_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; ++ ++ vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "chipselect_enable"); ++ if ( ! vp ) ++ sts = ASSOCIATION_ERROR; ++ adsContext->chipselect_enable = vp; ++ ++ vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "chipselect_disable"); ++ if ( ! vp ) ++ sts = ASSOCIATION_ERROR; ++ adsContext->chipselect_disable = vp; ++ ++ vp = ssp_request_pointer(SSP_DEV_TOUCHSCREEN, "chipselect_manual"); ++ if ( ! vp ) ++ sts = ASSOCIATION_ERROR; ++ adsContext->chipselect_manual = 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->chipselect_manual(); ++ 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 linux-2.4.26/drivers/misc/Config.in linux-2.4.26-vrs1-lnode80/drivers/misc/Config.in +--- linux-2.4.26/drivers/misc/Config.in 2005-11-02 16:54:22.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/Config.in 2005-11-02 17:37:31.000000000 -0400 +@@ -15,3 +15,14 @@ + 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" ]; then ++ tristate 'LH79590 touchscreen support' CONFIG_TOUCHSCREEN_LH79520 ++ tristate 'LH79590 serial eeprom support' CONFIG_EEPROM_LH79520 ++ tristate 'LH79590 7-segment support' CONFIG_7SEGMENT_LH79520 ++fi ++ ++endmenu +diff -urN linux-2.4.26/drivers/misc/eeprom-lh7x.c linux-2.4.26-vrs1-lnode80/drivers/misc/eeprom-lh7x.c +--- linux-2.4.26/drivers/misc/eeprom-lh7x.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/eeprom-lh7x.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,709 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++// #define MODULE ++ ++#define READ_AFTER_WRITE ++ ++/********************************************************************** ++* linux/drivers/misc/eeprom-lh79x.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 <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/proc_fs.h> ++#include <linux/smp_lock.h> ++#include <linux/miscdevice.h> ++#include <linux/poll.h> ++#include <linux/delay.h> ++ ++#undef DEBUG ++#undef VERBOSE ++#define DRVNAME "eeprom-lh79x" ++#include <linux/verbosedebug.h> ++ ++#include <linux/version.h> ++#ifdef MODULE ++char kernel_version[] = UTS_RELEASE; ++#endif /* MODULE */ ++ ++#include <asm/arch/hardware.h> ++ ++#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); ++ void (*ssp_chipselect_automatic)(void); ++ void (*ssp_chipselect_manual)(void); ++ void (*ssp_chipselect_enable)(void); ++ void (*ssp_chipselect_disable)(void); ++ 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_lh79x_erase_write_enable ++* Function: eeprom_lh79x_erase_write_disable ++**********************************************************************/ ++static void ++eeprom_lh79x_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); ++ ++ /* EEPROM Writes must be done using manual control of the ChipSelect */ ++ eepromContext->ssp_chipselect_manual(); ++ eepromContext->ssp_chipselect_enable(); ++ ++ 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); ++ ++ /* Reset back to automatic control of the EEPROM ChipSelect */ ++ eepromContext->ssp_chipselect_disable(); ++ eepromContext->ssp_chipselect_automatic(); ++ ++ /* Unlock the SSP after it has been locked */ ++ eepromContext->unlock(sspContext, SSP_DEV_EEPROM); ++ ++ return; ++} ++ ++static void ++eeprom_lh79x_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); ++ ++ /* EEPROM Writes must be done using manual control of the ChipSelect */ ++ eepromContext->ssp_chipselect_manual(); ++ eepromContext->ssp_chipselect_enable(); ++ ++ 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); ++ ++ /* Reset back to automatic control of the EEPROM ChipSelect */ ++ eepromContext->ssp_chipselect_disable(); ++ eepromContext->ssp_chipselect_automatic(); ++ ++ /* Unlock the SSP after it has been locked */ ++ eepromContext->unlock(sspContext, SSP_DEV_EEPROM); ++ ++ return; ++} ++ ++/********************************************************************** ++* Function: eeprom_lh79x_read_device_word ++**********************************************************************/ ++static void ++eeprom_lh79x_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); ++ ++ /* EEPROM Reads must be done using manual control of the ChipSelect */ ++ eepromContext->ssp_chipselect_manual(); ++ eepromContext->ssp_chipselect_enable(); ++ ++ /* 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 */ ++ ++ /* Reset back to automatic control of the EEPROM ChipSelect */ ++ eepromContext->ssp_chipselect_disable(); ++ eepromContext->ssp_chipselect_automatic(); ++ ++ /* 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_lh79x_write_device_word ++**********************************************************************/ ++static void ++eeprom_lh79x_write_device_word(eepromContext_t *eepromContext, int offset_w) ++{ ++ void *sspContext = eepromContext->sspContext; ++ uint16_t word; ++ long timeoutJiffies; ++ ++ /* 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); ++ ++ /* EEPROM Writes must be done using manual control of the ChipSelect */ ++ eepromContext->ssp_chipselect_manual(); ++ eepromContext->ssp_chipselect_enable(); ++ ++ /* Write modified cache data to the eeprom */ ++ eepromContext->write(sspContext, EEPROM_WRITE(offset_w)); ++ eepromContext->write(sspContext, word); ++ ++ /* Reset back to automatic control of the EEPROM ChipSelect */ ++ eepromContext->ssp_chipselect_disable(); ++ eepromContext->ssp_chipselect_automatic(); ++ ++ 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 */ ++ ++ return; ++} ++ ++/********************************************************************** ++* Function: eeprom_lh79x_read_device ++**********************************************************************/ ++static void ++eeprom_lh79x_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_lh79x_read_device_word(eepromContext, offset_w); ++ } ++ scwp++; ++ } ++ ++ return; ++} ++ ++/********************************************************************** ++* Function: eeprom_lh79x_write_device ++**********************************************************************/ ++static void ++eeprom_lh79x_write_device(eepromContext_t *eepromContext) ++{ ++ uint16_t *scwp; ++ int offset_w; ++ int timeoutJiffies; ++ ++ /* Enable erase/write of the eeprom */ ++ eeprom_lh79x_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_lh79x_write_device_word(eepromContext, offset_w); ++ } ++ scwp++; ++ } ++ ++ /* Disable erase/write of the eeprom */ ++ eeprom_lh79x_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_lh79x_read_device(eepromContext); ++#endif /* READ_AFTER_WRITE */ ++ ++ return; ++} ++ ++/********************************************************************** ++* ***************************************************** ++* *** User space "file operation" driver interfaces *** ++* ***************************************************** ++* Function: lh79x_eeprom_llseek ++* Function: lh79x_eeprom_read ++* Function: lh79x_eeprom_write ++* Function: lh79x_eeprom_poll ( NOT USED --- YET ) ++* Function: lh79x_eeprom_ioctl ( NOT USED --- YET ) ++* Function: lh79x_eeprom_open ++* Function: lh79x_eeprom_flush ( NOT USED --- YET ) ++* Function: lh79x_eeprom_release ( NOT USED --- YET ) ++* Function: lh79x_eeprom_fsync ( NOT USED --- YET ) ++* Function: lh79x_eeprom_fasync ( NOT USED --- YET ) ++* Function: lh79x_eeprom_lock ( NOT USED --- YET ) ++**********************************************************************/ ++ ++static loff_t ++lh79x_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 ++lh79x_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: lh79x_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_lh79x_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: lh79x_eeprom_read(%d)\n", sts); ++ ++ return(sts); ++} ++ ++static ssize_t ++lh79x_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: lh79x_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_lh79x_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_lh79x_write_device(eepromContext); ++ *offsetp += count; ++ sts = count; ++ } else { ++ sts = -EFAULT; ++ } ++ } ++ vdprintk("LEAVE: lh79x_eeprom_write(%d)\n", sts); ++ ++ return(sts); ++} ++ ++#if (0) /* NOT USED --- YET */ ++static unsigned int ++lh79x_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 ++lh79x_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 ++lh79x_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 ++lh79x_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 ++lh79x_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 ++lh79x_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 ++lh79x_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 ++lh79x_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 lh79x_eeprom_fops = { ++ owner: THIS_MODULE, ++ llseek: lh79x_eeprom_llseek, ++ read: lh79x_eeprom_read, ++ write: lh79x_eeprom_write, ++// poll: lh79x_eeprom_poll, ++// ioctl: lh79x_eeprom_ioctl, ++ open: lh79x_eeprom_open, ++// flush: lh79x_eeprom_flush, ++// release: lh79x_eeprom_release, ++// fsync: lh79x_eeprom_fsync, ++// fasync: lh79x_eeprom_fasync, ++// lock: lh79x_eeprom_lock, ++}; ++ ++static struct miscdevice lh79x_eeprom_dev = { ++minor: 22, ++name: "eeprom", ++fops: &lh79x_eeprom_fops, ++}; ++ ++/********************************************************************** ++* Function: lh79x_eeprom_make_ssp_association ++* ++* Purpose: ++* Make the association between the eeprom driver and the ssp driver ++**********************************************************************/ ++static int lh79x_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: lh79x_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; ++ ++ 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; ++ ++ 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: lh79x_eeprom_make_ssp_association(%d)\n", sts); ++ ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: lh79x_eeprom_init ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++static int lh79x_eeprom_init(void) ++{ ++ eepromContext_t *eepromContext = &eepromContext_l; ++ int sts = 0; ++ dprintk("ENTER: lh79x_eeprom_init()\n"); ++ init_waitqueue_head(&eepromContext->read_and_write_wait); ++ /* Retrieve the service information from the SSP driver */ ++ sts = lh79x_eeprom_make_ssp_association(eepromContext); ++ if (sts == 0) { ++ /* Ensure the eeprom cache is valid */ ++ eeprom_lh79x_read_device(eepromContext); ++ sts = misc_register(&lh79x_eeprom_dev); ++ } ++ dprintk("LEAVE: lh79x_eeprom_init(%d)\n", sts); ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: lh79x_eeprom_exit ++* ++* Purpose: ++* Un-Register & Cleanup the module ++**********************************************************************/ ++static void lh79x_eeprom_exit(void) ++{ ++ dprintk("ENTER: lh79x_eeprom_exit()\n"); ++ misc_deregister(&lh79x_eeprom_dev); ++ dprintk("LEAVE: lh79x_eeprom_exit()\n"); ++ return; ++} ++ ++module_init(lh79x_eeprom_init); ++module_exit(lh79x_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 linux-2.4.26/drivers/misc/lh7x-7seg.c linux-2.4.26-vrs1-lnode80/drivers/misc/lh7x-7seg.c +--- linux-2.4.26/drivers/misc/lh7x-7seg.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/lh7x-7seg.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,649 @@ ++/* 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 <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/proc_fs.h> ++#include <linux/smp_lock.h> ++#include <linux/miscdevice.h> ++#include <linux/poll.h> ++ ++#undef DEBUG ++#undef VERBOSE ++#define DRVNAME "lh7x-7seg" ++#include <linux/verbosedebug.h> ++ ++#include <linux/version.h> ++#ifdef MODULE ++char kernel_version[] = UTS_RELEASE; ++#endif /* MODULE */ ++ ++#include <asm/arch/hardware.h> ++#include <asm/arch/cpld.h> ++#include <asm/arch/lh7x-7seg.h> ++ ++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: lh79x_7seg_read_raw_display ++* Function: lh79x_7seg_read_raw_display_lsb ++* Function: lh79x_7seg_read_raw_display_msb ++**********************************************************************/ ++uint16_t lh79x_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("lh79x_7seg_read_raw_display(0x%04X)\n", raw_val); ++ ++ return(raw_val); ++} ++ ++u_char lh79x_7seg_read_raw_display_lsb(void) ++{ ++ uint16_t raw_val; ++ u_char raw_lsb; ++ ++ raw_val = lh79x_7seg_read_raw_display(); ++ raw_lsb = (u_char)(raw_val & 0xFF); ++ ++ return(raw_lsb); ++} ++ ++u_char lh79x_7seg_read_raw_display_msb(void) ++{ ++ uint16_t raw_val; ++ u_char raw_msb; ++ ++ raw_val = lh79x_7seg_read_raw_display(); ++ raw_msb = (u_char)((raw_val >> 8) & 0xFF); ++ ++ return(raw_msb); ++} ++ ++/********************************************************************** ++* Function: lh79x_7seg_read_display ++* Function: lh79x_7seg_read_display_lsb ++* Function: lh79x_7seg_read_display_msb ++**********************************************************************/ ++uint16_t lh79x_7seg_read_display(void) ++{ ++ uint16_t raw_val, val; ++ u_char raw_lsb, lsb; ++ u_char raw_msb, msb; ++ ++ raw_val = lh79x_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 lh79x_7seg_read_display_lsb(void) ++{ ++ u_char raw_lsb, lsb; ++ ++ raw_lsb = lh79x_7seg_read_raw_display_lsb(); ++ lsb = raw_val_to_val(raw_lsb); ++ ++ return(lsb); ++} ++ ++u_char lh79x_7seg_read_display_msb(void) ++{ ++ u_char raw_msb, msb; ++ ++ raw_msb = lh79x_7seg_read_raw_display_msb(); ++ msb = raw_val_to_val(raw_msb); ++ ++ return(msb); ++} ++ ++/********************************************************************** ++* Function: lh79x_7seg_write_raw_display ++* Function: lh79x_7seg_write_raw_display_lsb ++* Function: lh79x_7seg_write_raw_display_msb ++**********************************************************************/ ++void lh79x_7seg_write_raw_display(uint16_t raw_val) ++{ ++ sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; ++ ++ vdprintk("lh79x_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 lh79x_7seg_write_raw_display_lsb(u_char raw_lsb) ++{ ++ uint16_t raw_val; ++ ++ raw_val = lh79x_7seg_read_raw_display(); ++ raw_val &= 0xFF00; ++ raw_val &= ((uint16_t)raw_lsb) & 0x00FF; ++ lh79x_7seg_write_raw_display(raw_val); ++ ++ return; ++} ++ ++void lh79x_7seg_write_raw_display_msb(u_char raw_msb) ++{ ++ uint16_t raw_val; ++ ++ raw_val = lh79x_7seg_read_raw_display(); ++ raw_val &= 0x00FF; ++ raw_val &= (((uint16_t)raw_msb) << 8) & 0xFF00; ++ lh79x_7seg_write_raw_display(raw_val); ++ ++ return; ++} ++ ++/********************************************************************** ++* Function: lh79x_7seg_write_display ++* Function: lh79x_7seg_write_display_lsb ++* Function: lh79x_7seg_write_display_msb ++* Function: lh79x_7seg_write_display_str ++**********************************************************************/ ++void lh79x_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); ++ lh79x_7seg_write_raw_display(raw_val); ++ ++ return; ++} ++ ++void lh79x_7seg_write_display_lsb(u_char lsb) ++{ ++ u_char raw_lsb; ++ ++ raw_lsb = val_to_raw_val(lsb); ++ lh79x_7seg_write_raw_display_lsb(raw_lsb); ++ ++ return; ++} ++ ++void lh79x_7seg_write_display_msb(u_char msb) ++{ ++ u_char raw_msb; ++ ++ raw_msb = val_to_raw_val(msb); ++ lh79x_7seg_write_raw_display_msb(raw_msb); ++ ++ return; ++} ++ ++void lh79x_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 = lh79x_7seg_read_display(); ++ val <<= 8; ++ val &= 0xFF00; ++ c16 = c & 0x00FF; ++ val |= c16; ++ lh79x_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 = lh79x_7seg_read_display_lsb(); ++ break; ++ case ACCESSMODE_MSB: ++ c = lh79x_7seg_read_display_msb(); ++ break; ++ case ACCESSMODE_SHIFT: ++ default: ++ c16 = lh79x_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 = lh79x_7seg_read_raw_display(); ++ } else { ++ val = lh79x_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) { ++ lh79x_7seg_write_raw_display(val); ++ } else { ++ lh79x_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: lh79x_7seg_init ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++static int lh79x_7seg_init(void) ++{ ++ sevenSegmentContext_t *sevenSegmentContext = &sevenSegmentContext_l; ++ int sts = 0; ++ dprintk("ENTER: lh79x_7seg_init()\n"); ++ init_waitqueue_head(&sevenSegmentContext->read_and_write_wait); ++ sts = misc_register(&sevenSegment_dev); ++ lh79x_7seg_write_display_str((u_char *)"HI"); ++ dprintk("LEAVE: lh79x_7seg_init(%d)\n", sts); ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: lh79x_7seg_exit ++* ++* Purpose: ++* Un-Register & Cleanup the module ++**********************************************************************/ ++static void lh79x_7seg_exit(void) ++{ ++ dprintk("ENTER: lh79x_7seg_exit()\n"); ++ misc_deregister(&sevenSegment_dev); ++ lh79x_7seg_write_display_str((u_char *)"BY"); ++ dprintk("LEAVE: lh79x_7seg_exit()\n"); ++ return; ++} ++ ++module_init(lh79x_7seg_init); ++module_exit(lh79x_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 linux-2.4.26/drivers/misc/Makefile linux-2.4.26-vrs1-lnode80/drivers/misc/Makefile +--- linux-2.4.26/drivers/misc/Makefile 2005-11-02 16:54:22.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/Makefile 2005-11-02 17:37:31.000000000 -0400 +@@ -18,6 +18,9 @@ + 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_TOUCHSCREEN_LH79520) += ads784x.o marm-lh7x.o ++obj-$(CONFIG_EEPROM_LH79520) += eeprom-lh7x.o ++obj-$(CONFIG_7SEGMENT_LH79520) += lh7x-7seg.o + + include $(TOPDIR)/Rules.make + +diff -urN linux-2.4.26/drivers/misc/marm-lh7x.c linux-2.4.26-vrs1-lnode80/drivers/misc/marm-lh7x.c +--- linux-2.4.26/drivers/misc/marm-lh7x.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/marm-lh7x.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,521 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++// #define MODULE ++ ++/********************************************************************** ++* 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. ++* ++**********************************************************************/ ++ ++#include <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/wait.h> ++#include <linux/sched.h> ++#include <linux/smp_lock.h> ++#include <linux/spinlock.h> ++#include <linux/delay.h> ++ ++#undef DEBUG ++#undef VERBOSE ++#define DRVNAME "marm_lh7x" ++#include <linux/verbosedebug.h> ++ ++#include <linux/version.h> ++#ifdef MODULE ++char kernel_version[] = UTS_RELEASE; ++#endif /* MODULE */ ++ ++#include <asm/irq.h> ++#include <asm/mach/irq.h> ++#include <asm/arch/irq.h> ++#include <asm/arch/iocon.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/gpio.h> ++#include <asm/arch/ssp_lh7x.h> ++#include <lh79520.h> ++#include "ssp.h" ++ ++// global set by pl110fb driver ++unsigned short marm_backlight; ++ ++#undef BACKLIGHT ++#define BACKLIGHT marm_backlight ++ ++#define MARM_TS_INT 3 ++#define MARM_TS_IOBIT 6 ++ ++static volatile u16 *gpioa = (volatile u16 *) GPOUT16_BASE; ++static gpioARegs_t *gpioadr = (gpioARegs_t *) GPIO0_BASE; ++static ioconRegs_t *iocon = (ioconRegs_t *)IOCON_PHYS; ++static vicRegs_t *vic = (vicRegs_t *)VIC_BASE; ++static rcpcRegs_t *rcpc = (rcpcRegs_t *) RCPC_PHYS; ++ ++/********************************************************************** ++* Function: ssp_busy_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) ++{ ++ vdprintk("ENTER: ssp_busy_wait()\n"); ++}; ++ ++/********************************************************************** ++* 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) ++{ ++ vdprintk("ENTER: ssp_flush_tx_fifo()\n"); ++}; ++ ++static void ssp_flush_rx_fifo(sspContext_t *sspContext) ++{ ++ vdprintk("ENTER: ssp_flush_rx_fifo()\n"); ++}; ++ ++/********************************************************************** ++* 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) ++{ ++ vdprintk("ENTER: ssp_chipselect_enable()\n"); ++}; ++ ++static void ssp_chipselect_disable(void) ++{ ++ vdprintk("ENTER: ssp_chipselect_disable()\n"); ++}; ++ ++static void ssp_chipselect_manual(void) ++{ ++ vdprintk("ENTER: ssp_chipselect_manual()\n"); ++ ++ gpioadr->ddr &= ~(1 << MARM_TS_IOBIT); // make sure PA is input ++ iocon->MiscMux &= ~(MISCMUX_RCEII0); // make it PA6 instead of IRQ0 ++ ++ // ensure TS IRQ pin is interrupt ++ iocon->LCDMux &= ~(MISCMUX_PWM0SYNC); // assumes irq 3 ++}; ++ ++static void ssp_chipselect_automatic(void) ++{ ++ vdprintk("ENTER: ssp_chipselect_automatic()\n"); ++ ssp_chipselect_manual(); ++}; ++ ++/********************************************************************** ++* Function: ssp_lh7x_write16 ++* ++* Purpose: ++* Write the LH7x SSP data register ++**********************************************************************/ ++static void ssp_lh7x_write16(sspContext_t *sspContext, ++ unsigned int data) ++{ ++ int i; ++ int ndata = data & 0xFF; ++ int pdata, qdata; ++ ++ vdprintk("ENTER: ssp_lh7x_write16() 0x%04X\n", data); ++ ++ udelay(10); ++ pdata = BACKLIGHT; // keep on backlight ++ *gpioa = pdata; // assert nCS ++ ++ for (i = 8; i > 0; i--) ++ { ++ *gpioa = qdata = pdata | ((ndata & 0x80) ? TS_DIN : 0); // strobe out bit ++ udelay(1); ++ *gpioa = qdata | TS_DCLK | nLED; // raise clock ++ udelay(1); ++ *gpioa = qdata; // lower clock ++ udelay(1); ++ ++ ndata <<= 1; ++ } ++ udelay(50); // leave enough time for conversion ++ ++ *gpioa = pdata; ++}; ++ ++/********************************************************************** ++* Function: ssp_lh7x_read16 ++* ++* Purpose: ++* Read the LH7x SSP data register ++**********************************************************************/ ++static unsigned int ssp_lh7x_read16(sspContext_t *sspContext) ++{ ++ int i; ++ int pdata, ndata; ++ ++ pdata = BACKLIGHT; ++ ndata = 0; ++ ++ for (i = 16; i > 0; i--) ++ { ++ *gpioa = pdata; ++ udelay(1); ++ *gpioa = pdata | TS_DCLK | nLED; ++ udelay(1); ++ ++ if (gpioadr->dr & (1 << MARM_TS_IOBIT)) ++ ndata |= 1; ++ ++ ndata <<= 1; ++ } ++ ++ vdprintk("LEAVE: ssp_lh7x_read16() 0x%04X (%04d norm) raw\n", ndata, ndata >> 4); ++ return(ndata >> 4); ++}; ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down(sspContext_t *sspContext) ++{ ++ int pen_down = vic->RawIntr & (1 << MARM_TS_INT); //look for IRQ ++ vdprintk("ssp_lh7x_ts_pen_down(%d)\n", pen_down); ++ return (pen_down); ++} ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down_irq_enable ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down_irq_enable(sspContext_t *sspContext) ++{ ++ int lastState = vic->IntEnable & (1 << MARM_TS_INT); ++ vdprintk("ssp_lh7x_ts_pen_down_irq_enable: lastState %d\n", lastState); ++#if 0 ++ //enable_irq(MARM_TS_INT); ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++#endif ++ sspContext->irq_state = 1; ++ return(lastState); ++} ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down_irq_disable ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down_irq_disable( ++ sspContext_t *sspContext) ++{ ++ int lastState = vic->IntEnable & (1 << MARM_TS_INT); ++ vdprintk("ssp_lh7x_ts_pen_down_irq_disable: lastState %d\n", lastState); ++ //disable_irq(MARM_TS_INT); ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; ++ barrier(); ++ rcpc->intClear = (1 << MARM_TS_INT); ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; ++ sspContext->irq_state = 0; ++ return(lastState); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_ts_pen_down_irq ++* ++* We only detect touch screen _touches_ (pen down) with this interrupt ++* handler, and even then we just schedule our task. ++* ++* Note: It has already been determined that this is our interrupt ++* before we ever get it here so checking is minimal to non-existant. ++**********************************************************************/ ++static void ssp_lh7x_ts_pen_down_irq(int irq, sspContext_t *sspContext, ++ struct pt_regs * regs) ++{ ++ /* ++ * Disable the touchscreen interrupts ++ * by disabling the touchscreen IRQ ++ * --- AND --- ++ * Enable regular polling of the touchscreen device ++ * (The touchscreen IRQ will be re-enabled and polling ++ * will be disabled when it is detected that the ++ * pen is no longer down.) ++ */ ++ /* Disable touch screen IRQ */ ++ vdprintk("ENTER: ssp_lh7x_ts_pen_down_irq()\n"); ++ ssp_lh7x_ts_pen_down_irq_disable(sspContext); ++ vdprintk("ENTER: wake_up()\n"); ++ wake_up(sspContext->irq_wait_ptr); ++ vdprintk("LEAVE: ssp_lh7x_ts_pen_down_irq()\n"); ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_irq_handler ++* ++* This interrupt handler only directs traffic for the interrupts ++* by forwarding on the call to the appropriate interrupt handler. ++**********************************************************************/ ++static void ssp_lh7x_irq_handler(int irq, void *_sspContext, ++ struct pt_regs * regs) ++{ ++ sspContext_t *sspContext = _sspContext; ++ ++ vdprintk("ENTER: ssp_lh7x_irq_handler()\n"); ++ if ((sspContext) && (sspContext->irq_wait_ptr)) { ++ if (ssp_lh7x_ts_pen_down(sspContext)) ++ ssp_lh7x_ts_pen_down_irq(irq, sspContext, regs); ++ else ++#if defined(VERBOSE) && defined(DEBUG) ++ printk("ssp_lh7x_irq_handler() --- Not our interrupt\n"); ++#else ++ ; ++#endif ++ } // if(sspContext) ... ++#if defined(VERBOSE) && defined(DEBUG) ++ else { ++ printk("ssp_lh7x_irq_handler( NO ACTION )\n"); ++ } ++#endif ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_lock ++* Function: ssp_lh7x_unlock ++* ++* Purpose: ++* Lock/UnLock the SSP for a particular device (ts/ee) ++**********************************************************************/ ++static int ssp_lh7x_lock(sspContext_t *sspContext, int device) ++{ ++ vdprintk("ENTER: ssp_lh7x_lock()\n"); ++ return -1; ++}; ++ ++static int ssp_lh7x_unlock(sspContext_t *sspContext, int device) ++{ ++ vdprintk("ENTER: ssp_lh7x_unlock()\n"); ++ return -1; ++}; ++ ++/********************************************************************** ++* Function: ssp_lh7x_disable ++* ++* Purpose: ++* Disconnect I/O pins from the SSP module ++* and disable the SSP peripheral and its clocks. ++**********************************************************************/ ++static void ssp_lh7x_disable(void) ++{ ++ vdprintk("ENTER: ssp_lh7x_disable()\n"); ++}; ++ ++/********************************************************************** ++* Function: ssp_lh7x_enable ++* ++* Purpose: ++* Disconnect I/O pins from the SSP module ++* and disable the SSP peripheral and its clocks. ++**********************************************************************/ ++static void ssp_lh7x_enable(void) ++{ ++ vdprintk("ENTER: ssp_lh7x_enable()\n"); ++ return; ++} ++ ++/********************************************************************** ++* Fill in our context structures ++**********************************************************************/ ++ ++static sspContext_t sspContext_l = { ++ ts_txTimeout: 10000, ++ ts_rxTimeout: 10000, ++ ee_txTimeout: 10000, ++ ee_rxTimeout: 10000, ++ haveIrq: 0, ++}; ++ ++/********************************************************************** ++* Function: ssp_request_pointer ++* Function: ssp_provide_pointer ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++void *ssp_request_pointer(int device, char *request) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ void *vp = NULL; ++ ++ vdprintk("ENTER: ssp_request_pointer(\"%d\":\"%s\")\n", device, request); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ if (strcmp(request, "write") == 0) { ++ vp = ssp_lh7x_write16; ++ } else if (strcmp(request, "read") == 0) { ++ vp = ssp_lh7x_read16; ++ } else if (strcmp(request, "enable_pen_down_irq") == 0) { ++ vp = ssp_lh7x_ts_pen_down_irq_enable; ++ } else if (strcmp(request, "disable_pen_down_irq") == 0) { ++ vp = ssp_lh7x_ts_pen_down_irq_disable; ++ } else if (strcmp(request, "is_pen_down") == 0) { ++ vp = ssp_lh7x_ts_pen_down; ++ } else if (strcmp(request, "lock") == 0) { ++ vp = ssp_lh7x_lock; ++ } else if (strcmp(request, "unlock") == 0) { ++ vp = ssp_lh7x_unlock; ++ } else if (strcmp(request, "sspContext") == 0) { ++ vp = sspContext; ++ } else if (strcmp(request, "flush_tx_fifo") == 0) { ++ vp = ssp_flush_tx_fifo; ++ } else if (strcmp(request, "flush_rx_fifo") == 0) { ++ vp = ssp_flush_rx_fifo; ++ } else if (strcmp(request, "ssp_busy_wait") == 0) { ++ vp = ssp_busy_wait; ++ } else if (strcmp(request, "chipselect_enable") == 0) { ++ vp = ssp_chipselect_enable; ++ } else if (strcmp(request, "chipselect_disable") == 0) { ++ vp = ssp_chipselect_disable; ++ } else if (strcmp(request, "chipselect_manual") == 0) { ++ vp = ssp_chipselect_manual; ++ } ++ } else if (device == SSP_DEV_EEPROM) { ++ vp = NULL; ++ } ++ vdprintk("LEAVE: ssp_request_pointer(0x%08X)\n", (unsigned int)vp); ++ ++ return(vp); ++} ++ ++void *ssp_provide_pointer(int device, char *request, void *vp) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ ++ vdprintk("ENTER: ssp_provide_pointer(\"%d\":\"%s\":0x%08X)\n", ++ device, request, (unsigned int)vp); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ if (strcmp(request, "irq_wait_ptr") == 0) { ++ sspContext->irq_wait_ptr = vp; ++ } else { ++ vp = NULL; ++ } ++ } else if (device == SSP_DEV_EEPROM) { ++ vp = NULL; ++ } else { ++ vp = NULL; ++ } ++ vdprintk("LEAVE: ssp_provide_pointer(0x%08X)\n", (unsigned int)vp); ++ ++ return(vp); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_init ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++static int __init ssp_lh7x_init(void) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ int sts = 0; ++ int result; ++ ++ vdprintk("ENTER: ssp_lh7x_init()\n"); ++ ++ /* ++ * Disconnect I/O pins from the SSP module ++ * and disable the SSP peripheral and its clocks. ++ */ ++ ssp_lh7x_disable(); ++ ++ /* Flush the transmit FIFO */ ++ ssp_flush_tx_fifo(sspContext); ++ ++ /* Flush the receive FIFO */ ++ ssp_flush_rx_fifo(sspContext); ++ ++ ssp_chipselect_automatic(); ++ /* ++ * Connect I/O pins from the SSP module ++ * and enable the SSP peripheral and its clocks. ++ */ ++ ssp_lh7x_enable(); ++ ++ /* ++ * Request IRQ and attach it to the touchscreen pen_down line and enable it ++ */ ++ sspContext->haveIrq = 0; ++ result = request_irq(MARM_TS_INT, ssp_lh7x_irq_handler, ++ SA_SAMPLE_RANDOM, DRVNAME, sspContext); ++ if (result < 0) { ++ printk("%s: cannot get requested IRQ(MARM_TS_INT)\n", DRVNAME); ++ } else { ++ sspContext->haveIrq = 1; ++ vdprintk("%s: got requested IRQ(MARM_TS_INT)\n", DRVNAME); ++ } ++ ssp_lh7x_ts_pen_down_irq_enable(sspContext); ++ ++ vdprintk("LEAVE: ssp_lh7x_init()\n"); ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_exit ++* ++* Purpose: ++* Un-Register & Cleanup the module ++**********************************************************************/ ++static void ssp_lh7x_exit(void) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ ++ vdprintk("ENTER: ssp_lh7x_exit()\n"); ++ ++ /* ++ * Disable & Return IRQ ++ */ ++ lock_kernel(); ++ ssp_lh7x_ts_pen_down_irq_disable(sspContext); ++ if (sspContext->haveIrq) { ++ free_irq(MARM_TS_INT, sspContext); ++ sspContext->haveIrq = 0; ++ } ++ unlock_kernel(); ++ ++ vdprintk("LEAVE: ssp_lh7x_exit()\n"); ++ return; ++} ++ ++module_init(ssp_lh7x_init); ++module_exit(ssp_lh7x_exit); ++ ++MODULE_AUTHOR("Jim Gleason / Lineo, Inc."); ++MODULE_DESCRIPTION("SSP Driver for Sharp LH7x EVB"); ++MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); +diff -urN linux-2.4.26/drivers/misc/ssp.h linux-2.4.26-vrs1-lnode80/drivers/misc/ssp.h +--- linux-2.4.26/drivers/misc/ssp.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/ssp.h 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,29 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++/********************************************************************** ++* linux/drivers/misc/ssp.h ++* ++* Copyright (C) 2002 Lineo, Inc. ++* ++* Provide SSP types & definitions ++* ++* 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. ++* ++**********************************************************************/ ++ ++#ifndef _SSP_h ++#define _SSP_h ++ ++/********************************************************************* ++* Global Function Declarations ++*********************************************************************/ ++extern void *ssp_request_pointer(int device, char *request); ++extern void *ssp_provide_pointer(int device, char *request, void *vp); ++ ++#define SSP_DEV_TOUCHSCREEN 1 ++#define SSP_DEV_EEPROM 2 ++ ++#endif /* _SSP_h */ ++ +diff -urN linux-2.4.26/drivers/misc/ssp-lh7x.c linux-2.4.26-vrs1-lnode80/drivers/misc/ssp-lh7x.c +--- linux-2.4.26/drivers/misc/ssp-lh7x.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/misc/ssp-lh7x.c 2005-11-02 17:37:31.000000000 -0400 +@@ -0,0 +1,1024 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++// #define MODULE ++ ++/********************************************************************** ++* 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. ++* ++**********************************************************************/ ++ ++#include <linux/config.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++//#include <linux/wait.h> ++#include <linux/sched.h> ++#include <linux/smp_lock.h> ++#include <linux/spinlock.h> ++//#include <linux/interrupt.h> ++//#include <linux/irq.h> ++ ++#undef DEBUG ++#undef VERBOSE ++#undef DRVNAME //"ssp_lh7x" ++#include <linux/verbosedebug.h> ++ ++#include <linux/version.h> ++#ifdef MODULE ++char kernel_version[] = UTS_RELEASE; ++#endif /* MODULE */ ++ ++#include <asm/irq.h> ++#include <asm/mach/irq.h> ++#include <asm/arch/irq.h> ++#include <asm/arch/iocon.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/gpio.h> ++//#include <asm/arch/cpld.h> ++#include <asm/arch/rcpc.h> ++#include <asm/arch/ssp_lh7x.h> ++#include "ssp.h" ++ ++unsigned int hclkfreq_get( void); ++ ++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; ++static sspRegs_t *ssp = (sspRegs_t *)SSP_BASE; ++static vicRegs_t *vic = (vicRegs_t *)VIC_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; ++ ++/********************************************************************** ++* 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 ++ ++/********************************************************************** ++* Function: ssp_busy_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; ++} ++ ++/********************************************************************** ++* 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; ++} ++ ++/********************************************************************** ++* 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"); ++#ifdef ORDERITE_REV4 ++ //FJBgpioa->dr &= ~(SSPFRM_GPIO_BIT); /* LOW == Enabled */ ++ gpioa->dr &= ~(SSPEN_GPIO_BIT); /* LOW == Enabled */ ++#else ++ gpioa->dr &= ~(SSPFRM_GPIO_BIT); /* LOW == Enabled */ ++#endif ++ return; ++} ++ ++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"); ++#ifdef ORDERITE_REV4 ++ //FJBgpioa->dr |= SSPFRM_GPIO_BIT; /* HIGH == Disabled */ ++ gpioa->dr |= SSPEN_GPIO_BIT; /* HIGH == Disabled */ ++#else ++ gpioa->dr |= SSPFRM_GPIO_BIT; /* HIGH == Disabled */ ++#endif ++ return; ++} ++ ++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 */ ++#ifdef ORDERITE_REV4 ++ //FJBgpioa->ddr |= SSPFRM_GPIO_BIT; /* Make GPIO an output */ ++ gpioa->ddr |= SSPEN_GPIO_BIT; /* Make GPIO an output */ ++ //FJBiocon->SSIMux &= ~SSIMUX_SSPFRM; ++ iocon->SSIMux &= ~SSIMUX_SSPENB; ++#else ++ gpioa->ddr |= SSPFRM_GPIO_BIT; /* Make GPIO an output */ ++ iocon->SSIMux &= ~SSIMUX_SSPFRM; ++#endif ++ ssp_chipselect_disable(); ++ return; ++} ++ ++static void ssp_chipselect_automatic(void) ++{ ++ /* First, disable the ChipSelect */ ++ ssp_chipselect_disable(); ++#ifdef ORDERITE_REV4 ++ /* Set up muxing so the SSP automatically controls the ChipSelect pin */ ++ //FJBiocon->SSIMux |= SSIMUX_SSPFRM; ++ iocon->SSIMux |= SSIMUX_SSPENB; ++#else ++ iocon->SSIMux |= SSIMUX_SSPFRM; ++#endif ++ return; ++} ++ ++/********************************************************************** ++* 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); ++} ++ ++#if OLDWAY ++/********************************************************************** ++* Function: ssp_lh7x_get_hclk_freq ++* ++* Purpose: ++* Get the HCLK (bus clock) frequency in Hz ++**********************************************************************/ ++static unsigned int ssp_lh7x_get_hclk_freq(void) ++{ ++#define XTAL_IN 14745600 /* 14.7456 MHz crystal */ ++#define PLL_CLOCK (XTAL_IN * 21) /* 309 MHz PLL clock */ ++ int divider; ++ unsigned int _hclk_freq; ++ ++ vdprintk("ENTER: ssp_lh7x_get_hclk_freq()\n"); ++ divider = rcpc->HCLKPrescale * 2; /* HCLK prescale value */ ++ if( divider == 0) /* No prescalar == divide by 1 */ ++ divider = 1; ++ _hclk_freq = PLL_CLOCK / divider; ++ vdprintk("LEAVE: ssp_lh7x_get_hclk_freq(%u)\n", _hclk_freq); ++ ++ return(_hclk_freq); ++} ++#endif ++ ++ ++/********************************************************************** ++* Function: ssp_lh7x_get_speed ++* ++* Purpose: ++* Get the SSP speed in bits per second ++**********************************************************************/ ++static int ssp_lh7x_get_speed(void) ++{ ++ int bps; ++ int rcpc_prescale; ++ int ssp_prescale; ++ int ssp_divider; ++ ++ vdprintk("ENTER: ssp_lh7x_get_speed()\n"); ++ 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) ); ++ vdprintk("LEAVE: ssp_lh7x_get_speed(%d bps)\n", bps); ++ ++ return(bps); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_set_speed ++* ++* Purpose: ++* Set the SSP speed in bits per second ++* ++* Processing: ++* If the requested_bits_per_second is negaitve, return 0 ++* If the requested_bits_per_second is too fast, set the bit rate ++* as fast as possible. ++* If the requested_bits_per_second is too slow, set the bit rate as ++* slow as possible. ++* If the requested_bits_per_second is in range, set the RCPC ++* SSP clock prescaler register, SSP prescaler, and SSP divider ++* to obtain the clock as close as possible. ++* ++* Parameters: ++* bps: The desired bits per second ++* ++* Returns: ++* The actual bps obtained or 0 if the requested bps is not obtainable. ++* ++* Notes: ++* The mode (SPI/uWire/TI) must be set first for this function to work! ++* ++**********************************************************************/ ++static int ssp_lh7x_set_speed(int bps) ++{ ++ int rcpcLockState; ++ int32_t ssp_prescale; ++ int32_t ssp_divider; ++ int32_t rcpc_prescale; ++ int32_t new_prescale; ++ int32_t new_divider; ++ int32_t quotient; ++ int32_t delta1; ++ int32_t delta2; ++ int32_t min_error; ++ int32_t new_error; ++# define MAX_SSP_FREQ (hclk_freq / SSP_PRESCALE_MIN) ++ ++ vdprintk("ENTER: ssp_lh7x_set_speed(%d bps)\n", bps); ++ ++ /* Ensure we are dealing with a legal BPS */ ++ if (bps <= 0) { ++ printk("%s: requested ssp speed (%d bps) is to slow\n", DRVNAME, bps); ++ printk("%s: making ssp speed as slow as possible\n", DRVNAME); ++ /* The request bps is slower than the minimum possible */ ++ /* ... make it as slow as possible */ ++ /* Don't bother calculating the divider values as we know them */ ++ rcpc_prescale = RCPC_SSP_PRESCALE_MAX; ++ ssp_prescale = SSP_PRESCALE_MAX; ++ ssp_divider = SSP_DIVIDER_MAX; ++ } else if (bps >= MAX_SSP_FREQ) { ++ printk("%s: requested ssp speed (%d bps) is to fast\n", DRVNAME, bps); ++ printk("%s: making ssp speed as fast as possible\n", DRVNAME); ++ /* Don't bother calculating the divider values as we know them */ ++ bps = MAX_SSP_FREQ; ++ ssp_prescale = SSP_PRESCALE_MIN; ++ ssp_divider = 1; ++ rcpc_prescale = 1; ++ } else { ++ /* Calculate the divider values as close as we can */ ++ quotient = hclk_freq / bps; ++ if (quotient <= 0) ++ quotient = 1; ++ /* round the quotient */ ++ delta1 = bps - (hclk_freq / quotient ); ++ if (delta1 < 0) ++ delta1 = -delta1; ++ delta2 = bps - (hclk_freq / (quotient + 1)); ++ if (delta2 < 0) ++ delta2 = -delta2; ++ if (delta1 > delta2) ++ quotient++; ++ if (quotient >= ++ (SSP_PRESCALE_MAX * RCPC_SSP_PRESCALE_MAX * SSP_DIVIDER_MAX)) ++ { ++ printk("%s: requested ssp speed (%d bps) is to slow\n", ++ DRVNAME, bps); ++ printk("%s: making ssp speed as slow as possible\n", DRVNAME); ++ /* The request bps is slower than the minimum possible */ ++ /* ... make it as slow as possible */ ++ /* Don't bother calculating the divider values as we know them */ ++ rcpc_prescale = RCPC_SSP_PRESCALE_MAX; ++ 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. ++ */ ++ rcpc_prescale = 1; ++ /* ++ * Try to reduce power by using RCPC prescaler. ++ * Note that the ssp prescaler minimum is two ++ * so can only prescale and maintain accuracy ++ * if quotient is divisible by 4. ++ */ ++ while ( ((quotient & 0x3) == 0) ++ && (rcpc_prescale < RCPC_SSP_PRESCALE_MAX) ) ++ { ++ quotient >>= 1; ++ rcpc_prescale <<= 1; ++ } ++ /* ++ * Make sure the requested frequency is within range ++ * of the SPP's prescaler and divider. ++ * Hopefully, this loop never executes. ++ * If it does, accuracy suffers. ++ */ ++ while (quotient > (SSP_PRESCALE_MAX * SSP_DIVIDER_MAX) ) { ++ rcpc_prescale <<= 1; ++ quotient >>= 1; ++ } ++ /* ++ * Factor the quotient into the divider and prescaler combo ++ * that minimizes the error in the quotient by exhaustively ++ * searching all legal ssp prescaler values. ++ */ ++ ssp_prescale = SSP_PRESCALE_MIN; ++ ssp_divider = (quotient / ssp_prescale); ++ ssp_divider = (ssp_divider > SSP_DIVIDER_MAX) ++ ? SSP_DIVIDER_MAX : ssp_divider; ++ min_error = quotient - (ssp_divider * ssp_prescale); ++ min_error = (min_error < 0) ? -min_error : min_error; ++ for (new_prescale = SSP_PRESCALE_MIN + 2; ++ new_prescale < SSP_PRESCALE_MAX; ++ new_prescale += 2) ++ { ++ new_divider = (quotient / new_prescale); ++ new_divider = (new_divider > SSP_DIVIDER_MAX) ++ ? SSP_DIVIDER_MAX : new_divider; ++ new_error = quotient - (new_divider * new_prescale); ++ new_error = (new_error < 0) ? -new_error : new_error; ++ if (new_error < min_error) { ++ min_error = new_error; ++ ssp_prescale = new_prescale; ++ ssp_divider = new_divider; ++ } ++ } ++ } ++ } ++ /* Set up the necessary registers to get the desired BSP */ ++ rcpcLockState = rcpc_lh7x_lock(RCPC_UNLOCK); ++ rcpc->rcpc_sspClkPrescale = rcpc_prescale >> 1; ++ (void) rcpc_lh7x_lock(rcpcLockState); ++ ssp->cpsr = ssp_prescale; ++ ssp->cr0 &= 0xff; /* clear old divider value */ ++ ssp->cr0 |= SSP_CR0_SCR(ssp_divider - 1); ++ ++ vdprintk("LEAVE: ssp_lh7x_set_speed(%d bps)\n", bps); ++ ++ return(ssp_lh7x_get_speed()); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_write16 ++* ++* Purpose: ++* Write the LH7x SSP data register ++**********************************************************************/ ++static void ssp_lh7x_write16(sspContext_t *sspContext, ++ unsigned int data) ++{ ++ int i; ++ ++ //if (sspContext->ssp_dev_sel == SSP_EEPROM) { //JMG ++ //printk("ENTER: ssp_lh7x_write16(0x%04X)\n", (uint16_t)data); ++ //} ++ for (i=sspContext->ts_txTimeout; ((i>0) && ((ssp->sr&SSP_SR_TNF) == 0)); i--) { ++ barrier(); ++ } ++ if (ssp->sr & SSP_SR_TNF) { ++ ssp->dr = (uint16_t)data; ++ } else { ++ printk("%s: write timout\n", DRVNAME); ++ } ++ //vdprintk("LEAVE: ssp_lh7x_write16(0x%04X)\n", (uint16_t)data); ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_read16 ++* ++* Purpose: ++* Read the LH7x SSP data register ++**********************************************************************/ ++static unsigned int ssp_lh7x_read16(sspContext_t *sspContext) ++{ ++ int i; ++ unsigned int data = -1; ++ ++ //vdprintk("ENTER: ssp_lh7x_read16()\n"); ++ for (i=sspContext->ts_txTimeout; ((i>0) && ((ssp->sr&SSP_SR_RNE) == 0)); i--) { ++ barrier(); ++ } ++ if (ssp->sr & SSP_SR_RNE) { ++ if (sspContext->ssp_dev_sel == SSP_EEPROM) { ++ data = (unsigned int)ssp->dr; /* EEPROM */ ++ //printk("LEAVE: ssp_lh7x_read16(ee: 0x%04X)\n", data); ++ } else { ++ data = (((unsigned int)ssp->dr) >> 4) & 0x0FFF; /* TOUCHSCREEN */ ++ //printk("LEAVE: ssp_lh7x_read16(ts: 0x%04X)\n", data); ++ } ++ } else { ++ //printk("%s: read timout\n", DRVNAME); ++ } ++ ++ return(data); ++} ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down(sspContext_t *sspContext) ++{ ++ ++ //int pen_down = vic->IRQStatus & 0x01; //look for IRQ0 ++ int pen_down = vic->RawIntr & 0x01; //look for IRQ0 ++ dprintk("ssp_lh7x_ts_pen_down(%d)\n", pen_down); ++ return (pen_down); ++} ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down_irq_enable ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down_irq_enable(sspContext_t *sspContext) ++{ ++ int lastState = vic->IntEnable & 1; ++ dprintk("ssp_lh7x_ts_pen_down_irq_enable\n"); ++ //vic->IntEnable = 1; ++ enable_irq(0); ++ sspContext->irq_state = 1; ++ return(lastState); ++} ++ ++/********************************************************************** ++* Macro: ssp_lh7x_ts_pen_down_irq_disable ++**********************************************************************/ ++static int ssp_lh7x_ts_pen_down_irq_disable( ++ sspContext_t *sspContext) ++{ ++ int lastState = vic->IntEnable & 1; ++ dprintk("ssp_lh7x_ts_pen_down_irq_disable\n"); ++ //vic->IntEnClear = 1; ++ disable_irq(0); ++ sspContext->irq_state = 0; ++ return(lastState); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_ts_pen_down_irq ++* ++* We only detect touch screen _touches_ (pen down) with this interrupt ++* handler, and even then we just schedule our task. ++* ++* Note: It has already been determined that this is our interrupt ++* before we ever get it here so checking is minimal to non-existant. ++**********************************************************************/ ++static void ssp_lh7x_ts_pen_down_irq(int irq, sspContext_t *sspContext, ++ struct pt_regs * regs) ++{ ++ /* ++ * Disable the touchscreen interrupts ++ * by disabling the touchscreen IRQ ++ * --- AND --- ++ * Enable regular polling of the touchscreen device ++ * (The touchscreen IRQ will be re-enabled and polling ++ * will be disabled when it is detected that the ++ * pen is no longer down.) ++ */ ++ /* Disable touch screen IRQ */ ++ dprintk("ENTER: ssp_lh7x_ts_pen_down_irq()\n"); ++ ssp_lh7x_ts_pen_down_irq_disable(sspContext); ++ dprintk("ENTER: wake_up()\n"); ++ wake_up(sspContext->irq_wait_ptr); ++ vdprintk("LEAVE: ssp_lh7x_ts_pen_down_irq()\n"); ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_irq_handler ++* ++* This interrupt handler only directs traffic for the interrupts ++* by forwarding on the call to the appropriate interrupt handler. ++**********************************************************************/ ++static void ssp_lh7x_irq_handler(int irq, void *_sspContext, ++ struct pt_regs * regs) ++{ ++ sspContext_t *sspContext = _sspContext; ++ if ((sspContext) && (sspContext->irq_wait_ptr)) { ++ //if (ssp_lh7x_ts_pen_down(sspContext)) { ++ if (1) { ++ ssp_lh7x_ts_pen_down_irq(irq, sspContext, regs); ++ } ++#if defined(VERBOSE) && defined(DEBUG) ++ else { ++ vdprintk("ssp_lh7x_irq_handler() --- Not our interrupt\n"); ++ } ++#endif ++ } ++#if defined(VERBOSE) && defined(DEBUG) ++ else { ++ vdprintk("ssp_lh7x_irq_handler( NO ACTION )\n"); ++ } ++#endif ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_lock ++* Function: ssp_lh7x_unlock ++* ++* Purpose: ++* Lock/UnLock the SSP for a particular device (ts/ee) ++**********************************************************************/ ++static int ssp_lh7x_lock(sspContext_t *sspContext, int device) ++{ ++ int sts = -1; ++ int cr0; ++ ++ spin_lock_irq(&sspContext->sspLock); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ /* Select the touchscreen */ ++ sspContext->ssp_dev_sel = SSP_TOUCHSCREEN; ++ cr0 = ssp->cr0; ++ cr0 &= ~0x00F0; ++ /* National Microwire frame format --- SPI Polarity High */ ++ /* Don't mess with data size or clock rate */ ++ cr0 |= (SSP_CR0_FRF_NS | SSP_CR0_SPH); ++ ssp->cr0 = cr0; ++ vdprintk("ssp_lh7x_lock(SSP_DEV_TOUCHSCREEN)\n"); ++ // sts = 0; ++ } else if (device == SSP_DEV_EEPROM) { ++ /* Select the eeprom */ ++ sspContext->ssp_dev_sel = SSP_EEPROM; ++ cr0 = ssp->cr0; ++ cr0 &= ~0x00F0; ++ /* Motorola SPI frame --- w/SPH & w/SPO */ ++ /* Don't mess with data size or clock rate */ ++ cr0 |= (SSP_CR0_FRF_MOT | SSP_CR0_SPH | SSP_CR0_SPO); ++ ssp->cr0 = cr0; ++ vdprintk("ssp_lh7x_lock(SSP_DEV_EEPROM)\n"); ++ // sts = 0; ++ } ++ //cpld->ssp_dev_sel = sspContext->ssp_dev_sel; ++ ++ return(sts); ++} ++ ++static int ssp_lh7x_unlock(sspContext_t *sspContext, int device) ++{ ++ int sts = -1; ++// #define SSP_DEFAULT_DEVICE SSP_TOUCHSCREEN ++#define SSP_DEFAULT_DEVICE SSP_INVALID_DEVICE ++ ++ spin_unlock_irq(&sspContext->sspLock); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ /* Select the default device */ ++ sspContext->ssp_dev_sel = SSP_DEFAULT_DEVICE; ++ vdprintk("ssp_lh7x_unlock(SSP_DEV_TOUCHSCREEN)\n"); ++ // sts = 0; ++ } else if (device == SSP_DEV_EEPROM) { ++ /* Select the default device */ ++ sspContext->ssp_dev_sel = SSP_DEFAULT_DEVICE; ++ vdprintk("ssp_lh7x_unlock(SSP_DEV_EEPROM)\n"); ++ // sts = 0; ++ } ++ //cpld->ssp_dev_sel = sspContext->ssp_dev_sel; ++ ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_disable ++* ++* Purpose: ++* Disconnect I/O pins from the SSP module ++* and disable the SSP peripheral and its clocks. ++**********************************************************************/ ++static void ssp_lh7x_disable(void) ++{ ++ int rcpcLockState; ++ ++ vdprintk("ENTER: ssp_lh7x_disable()\n"); ++ ++ /* Switch all muxed I/O away from the SSP */ ++ iocon->SSIMux &= ~( ++ SSIMUX_SSPIN | ++ SSIMUX_SSPOUT | ++ SSIMUX_SSPCLK | ++ SSIMUX_SSPENB | ++ SSIMUX_SSPFRM ++ ); ++ ++ /* Disable ssp clock */ ++ rcpcLockState = rcpc_lh7x_lock(RCPC_UNLOCK); ++ rcpc->rcpc_sspClkControl |= RCPC_SCLKSEL_SSPCLK; ++ (void) rcpc_lh7x_lock(rcpcLockState); ++ ++ /* Set control register to their reset defaults */ ++ ssp->cr0 = 0; ++ ssp->cr1 = 0; ++ ++ /* clear any receive overruns */ ++ ssp->u.icr = SSP_IIR_RORIS; ++ ++ //JMG /* disable the ssp DMA streams */ ++ //JMG dmac->stream0.max = 0; ++ //JMG dmac->stream0.ctrl = 0; ++ //JMG dmac->stream1.max = 0; ++ //JMG dmac->stream1.ctrl = 0; ++ //JMG /* clear any previous SSP DMA completions */ ++ //JMG dmac->clear = DMAC_EOT0 | DMAC_EOT1; ++ ++ vdprintk("LEAVE: ssp_lh7x_disable()\n"); ++ ++ return; ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_enable ++* ++* Purpose: ++* Disconnect I/O pins from the SSP module ++* and disable the SSP peripheral and its clocks. ++**********************************************************************/ ++static void ssp_lh7x_enable(void) ++{ ++ ++ vdprintk("ENTER: ssp_lh7x_enable()\n"); ++ ++ /* Enable the SSP */ ++ ssp->cr1 |= SSP_CR1_SSE; /* Synchronous serial port enable */ ++ ++ /* Switch all muxed I/O to the SSP */ ++ /* Note that SSPENB is not required for spi */ ++ iocon->SSIMux = ( ++ SSIMUX_SSPIN | ++ SSIMUX_SSPOUT | ++ SSIMUX_SSPCLK | ++ //SSIMUX_SSPENB | ++ SSIMUX_SSPFRM ++ ); ++ ++ ++ vdprintk("LEAVE: ssp_lh7x_enable()\n"); ++ ++ return; ++} ++ ++/********************************************************************** ++* Fill in our context structures ++**********************************************************************/ ++ ++static sspContext_t sspContext_l = { ++ ts_txTimeout: 10000, ++ ts_rxTimeout: 10000, ++ ee_txTimeout: 10000, ++ ee_rxTimeout: 10000, ++ haveIrq: 0, ++}; ++ ++/********************************************************************** ++* Function: ssp_request_pointer ++* Function: ssp_provide_pointer ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++void *ssp_request_pointer(int device, char *request) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ void *vp = NULL; ++ ++ dprintk("ENTER: ssp_request_pointer(\"%d\":\"%s\")\n", device, request); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ if (strcmp(request, "write") == 0) { ++ vp = ssp_lh7x_write16; ++ } else if (strcmp(request, "read") == 0) { ++ vp = ssp_lh7x_read16; ++ } else if (strcmp(request, "enable_pen_down_irq") == 0) { ++ vp = ssp_lh7x_ts_pen_down_irq_enable; ++ } else if (strcmp(request, "disable_pen_down_irq") == 0) { ++ vp = ssp_lh7x_ts_pen_down_irq_disable; ++ } else if (strcmp(request, "is_pen_down") == 0) { ++ vp = ssp_lh7x_ts_pen_down; ++ } else if (strcmp(request, "lock") == 0) { ++ vp = ssp_lh7x_lock; ++ } else if (strcmp(request, "unlock") == 0) { ++ vp = ssp_lh7x_unlock; ++ } else if (strcmp(request, "sspContext") == 0) { ++ vp = sspContext; ++ } else if (strcmp(request, "flush_tx_fifo") == 0) { ++ vp = ssp_flush_tx_fifo; ++ } else if (strcmp(request, "flush_rx_fifo") == 0) { ++ vp = ssp_flush_rx_fifo; ++ } else if (strcmp(request, "ssp_busy_wait") == 0) { ++ vp = ssp_busy_wait; ++ } else if (strcmp(request, "chipselect_enable") == 0) { ++ vp = ssp_chipselect_enable; ++ } else if (strcmp(request, "chipselect_disable") == 0) { ++ vp = ssp_chipselect_disable; ++ } else if (strcmp(request, "chipselect_manual") == 0) { ++ vp = ssp_chipselect_manual; ++ } ++ } else if (device == SSP_DEV_EEPROM) { ++ if (strcmp(request, "write") == 0) { ++ vp = ssp_lh7x_write16; ++ } else if (strcmp(request, "read") == 0) { ++ vp = ssp_lh7x_read16; ++ } else if (strcmp(request, "lock") == 0) { ++ vp = ssp_lh7x_lock; ++ } else if (strcmp(request, "unlock") == 0) { ++ vp = ssp_lh7x_unlock; ++ } else if (strcmp(request, "sspContext") == 0) { ++ vp = sspContext; ++ } else if (strcmp(request, "chipselect_enable") == 0) { ++ vp = ssp_chipselect_enable; ++ } else if (strcmp(request, "chipselect_disable") == 0) { ++ vp = ssp_chipselect_disable; ++ } else if (strcmp(request, "chipselect_manual") == 0) { ++ vp = ssp_chipselect_manual; ++ } else if (strcmp(request, "chipselect_automatic") == 0) { ++ vp = ssp_chipselect_automatic; ++ } else if (strcmp(request, "flush_tx_fifo") == 0) { ++ vp = ssp_flush_tx_fifo; ++ } else if (strcmp(request, "flush_rx_fifo") == 0) { ++ vp = ssp_flush_rx_fifo; ++ } else if (strcmp(request, "ssp_busy_wait") == 0) { ++ vp = ssp_busy_wait; ++ } ++ } ++ dprintk("LEAVE: ssp_request_pointer(0x%08X)\n", (unsigned int)vp); ++ ++ return(vp); ++} ++ ++void *ssp_provide_pointer(int device, char *request, void *vp) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ ++ dprintk("ENTER: ssp_provide_pointer(\"%d\":\"%s\":0x%08X)\n", ++ device, request, (unsigned int)vp); ++ if (device == SSP_DEV_TOUCHSCREEN) { ++ if (strcmp(request, "irq_wait_ptr") == 0) { ++ sspContext->irq_wait_ptr = vp; ++ } else { ++ vp = NULL; ++ } ++ } else if (device == SSP_DEV_EEPROM) { ++ vp = NULL; ++ } else { ++ vp = NULL; ++ } ++ dprintk("LEAVE: ssp_provide_pointer(0x%08X)\n", (unsigned int)vp); ++ ++ return(vp); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_init ++* ++* Purpose: ++* Register & Initialize the module ++**********************************************************************/ ++static int __init ssp_lh7x_init(void) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ int sts = 0; ++ int rcpcLockState; ++ int result; ++ ++ vdprintk("ENTER: ssp_lh7x_init()\n"); ++ ++ vdprintk("ssp = 0x%08X\n", (unsigned int)ssp); ++ ++ /* Determine the HCLK (bus clock) frequency in Hz */ ++#ifdef OLDWAY ++ hclk_freq = ssp_lh7x_get_hclk_freq(); ++#else ++ hclk_freq = hclkfreq_get(); ++#endif ++ ++ /* ++ * Disconnect I/O pins from the SSP module ++ * and disable the SSP peripheral and its clocks. ++ */ ++ ssp_lh7x_disable(); ++ ++ /* Initialize the RCPC SSP clock & prescaler */ ++ rcpcLockState = rcpc_lh7x_lock(RCPC_UNLOCK); ++ rcpc->rcpc_sspClkPrescale = 0; /* As fast as possible */ ++ rcpc->rcpc_sspClkControl &= ~RCPC_SCLKSEL_SSPCLK; /* Enable SSP clock */ ++ (void) rcpc_lh7x_lock(rcpcLockState); ++ ++ ssp->cpsr = SSP_CPSR_CPDVSR(SSP_PRESCALE_MIN); ++ ++ /* Initialize CR0 */ ++ ssp->cr0 = ( ++ SSP_CR0_DSS(16) /* 16-bit data */ ++ | SSP_CR0_FRF_NS /* National Microwire frame format */ ++ | SSP_CR0_SPH /* SPI Polarity */ ++ | SSP_CR0_SCR(1) /* Serial clock rate (~922kbps) */ ++ ); ++ ++ /* Initialize CR1 */ ++ ssp->cr1 = ( ++ SSP_CR1_SSE /* Synchronous serial port enable */ ++ ); ++ ++ /* Set the SSP speed in bits per second */ ++ /* Note this MUST be done after the SSP_CR0_FRF_xxx mode is set */ ++ (void) ssp_lh7x_set_speed(LH7x_TS_BPS); ++ ++ /* Select the touchscreen */ ++ sspContext->ssp_dev_sel = SSP_TOUCHSCREEN; ++ //cpld->ssp_dev_sel = sspContext->ssp_dev_sel; ++ ++ /* Flush the transmit FIFO */ ++ ssp_flush_tx_fifo(sspContext); ++ ++ /* Flush the receive FIFO */ ++ ssp_flush_rx_fifo(sspContext); ++ ++ /* clear any receive overruns */ ++ ssp->u.icr = SSP_IIR_RORIS; ++ ++ //printk("ssp->cr0 = 0x%04X\n", ssp->cr0); ++ //printk("ssp->cr1 = 0x%04X\n", ssp->cr1); ++ //printk("ssp->sr = 0x%04X\n", ssp->sr); ++ //printk("ssp->cpsr = 0x%04X\n", ssp->cpsr); ++ //printk("ssp->u.icr | u.iir = 0x%04X\n", ssp->u.icr); ++ ++ ssp_chipselect_automatic(); ++ /* ++ * Connect I/O pins from the SSP module ++ * and enable the SSP peripheral and its clocks. ++ */ ++ ssp_lh7x_enable(); ++ ++ /* ++ * Request IRQ2 and attach it to the touchscreen pen_down line and enable it ++ */ ++ sspContext->haveIrq = 0; ++ result = request_irq(0, ssp_lh7x_irq_handler, ++ SA_SAMPLE_RANDOM, DRVNAME, sspContext); ++ if (result < 0) { ++ printk("%s: cannot get requested IRQ(0)\n", DRVNAME); ++ } else { ++ sspContext->haveIrq = 1; ++ dprintk("%s: got requested IRQ(0)\n", DRVNAME); ++ } ++ ssp_lh7x_ts_pen_down_irq_enable(sspContext); ++ ++ vdprintk("LEAVE: ssp_lh7x_init()\n"); ++ return(sts); ++} ++ ++/********************************************************************** ++* Function: ssp_lh7x_exit ++* ++* Purpose: ++* Un-Register & Cleanup the module ++**********************************************************************/ ++static void ssp_lh7x_exit(void) ++{ ++ sspContext_t *sspContext = &sspContext_l; ++ int rcpcLockState; ++ ++ vdprintk("ENTER: ssp_lh7x_exit()\n"); ++ ++ //printk("ssp->cr0 = 0x%04X\n", ssp->cr0); ++ //printk("ssp->cr1 = 0x%04X\n", ssp->cr1); ++ //printk("ssp->sr = 0x%04X\n", ssp->sr); ++ //printk("ssp->cpsr = 0x%04X\n", ssp->cpsr); ++ //printk("ssp->u.icr | u.iir = 0x%04X\n", ssp->u.icr); ++ ++ /* ++ * Disable & Return IRQ 2 ++ */ ++ lock_kernel(); ++ ssp_lh7x_ts_pen_down_irq_disable(sspContext); ++ if (sspContext->haveIrq) { ++ free_irq(0, sspContext); ++ sspContext->haveIrq = 0; ++ } ++ unlock_kernel(); ++ ++ ssp->cr0 = 0; ++ ssp->cr1 = 0; ++ ssp->u.icr = SSP_IIR_RORIS; /* clear any receive overruns */ ++ ssp->cpsr = SSP_CPSR_CPDVSR(SSP_PRESCALE_MIN); ++ ++ /* Turn off the RCPC SSP clock */ ++ rcpcLockState = rcpc_lh7x_lock(RCPC_UNLOCK); ++ rcpc->rcpc_sspClkControl |= RCPC_SCLKSEL_SSPCLK; /* Disable SSP clock */ ++ (void) rcpc_lh7x_lock(rcpcLockState); ++ ++ vdprintk("LEAVE: ssp_lh7x_exit()\n"); ++ return; ++} ++ ++module_init(ssp_lh7x_init); ++module_exit(ssp_lh7x_exit); ++ ++MODULE_AUTHOR("Jim Gleason / Lineo, Inc."); ++MODULE_DESCRIPTION("SSP Driver for Sharp LH7x EVB"); ++MODULE_LICENSE("Copyright (c) 2002 Lineo, Inc."); ++ +diff -urN linux-2.4.26/drivers/serial/amba_pl011.c linux-2.4.26-vrs1-lnode80/drivers/serial/amba_pl011.c +--- linux-2.4.26/drivers/serial/amba_pl011.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/serial/amba_pl011.c 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,854 @@ ++/* ++ * linux/drivers/char/serial_amba_pl011.c ++ * ++ * Driver for AMBA PrimeCell PL011 serial ports ++ * Copyright (C) 2002 Lineo, Inc. ++ * ++ * Based on drivers/char/serial_amba.c, which is: ++ * Copyright 1999 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/tty.h> ++#include <linux/ioport.h> ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/serial.h> ++#include <linux/console.h> ++#include <linux/sysrq.h> ++ ++#include <asm/io.h> ++#include <asm/irq.h> ++ ++#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++#define SUPPORT_SYSRQ ++#endif ++ ++#include <linux/serial_core.h> ++ ++#include <asm/hardware/serial_amba_pl011.h> ++ ++#ifdef CONFIG_ARCH_LH79520 ++#include <asm/arch/rcpc.h> ++#include <asm/arch/iocon.h> ++#include <asm/arch/gpio.h> ++#endif ++ ++#define UART_NR 3 ++ ++#define SERIAL_AMBA_MAJOR 204 ++#define SERIAL_AMBA_MINOR 16 ++#define SERIAL_AMBA_NR UART_NR ++ ++#define CALLOUT_AMBA_NAME "cuaam" ++#define CALLOUT_AMBA_MAJOR 205 ++#define CALLOUT_AMBA_MINOR 16 ++#define CALLOUT_AMBA_NR UART_NR ++ ++static struct tty_driver normal, callout; ++static struct tty_struct *amba11_table[UART_NR]; ++static struct termios *amba11_termios[UART_NR], *amba11_termios_locked[UART_NR]; ++#ifdef SUPPORT_SYSRQ ++static struct console amba11_console; ++#endif ++static void amba11uart_tx_chars(struct uart_port *port); ++ ++#define AMBA_ISR_PASS_LIMIT 256 ++ ++/* ++ * Access macros for the AMBA UARTs ++ */ ++#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR) ++#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR) ++#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR) ++#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR) ++#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H) ++#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H) ++ ++#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) ++#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) ++#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0) ++ ++#define UART_GET_INT_STATUS(p) readw((p)->membase + AMBA_UARTMIS) ++#define UART_GET_FR(p) readw((p)->membase + AMBA_UARTFR) ++#define UART_GET_CR(p) readl((p)->membase + AMBA_UARTCR) ++#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR) ++#define UART_GET_IMSC(p) readl((p)->membase + AMBA_UARTIMSC) ++#define UART_PUT_IMSC(p,c) writel((c), (p)->membase + AMBA_UARTIMSC) ++#define UART_GET_IBRD(p) readl((p)->membase + AMBA_UARTIBRD) ++#define UART_PUT_IBRD(p,c) writel((c), (p)->membase + AMBA_UARTIBRD) ++ ++ ++#define UART_DUMMY_RSR_RX 256 ++#define UART_PORT_SIZE 64 ++ ++/* ++ * Our private driver data mappings. ++ */ ++#define drv_old_status driver_priv ++ ++struct uart_amba11_port { ++ struct uart_port port; ++ unsigned int old_status; ++}; ++ ++static void amba11uart_stop_tx(struct uart_port *port, unsigned int tty_stop) ++{ ++ unsigned int mask; ++ ++ mask = UART_GET_IMSC( port); ++ mask &= ~AMBA_UARTIMSC_TXIM; ++ UART_PUT_IMSC( port, mask); /* disable Tx interrupts */ ++} ++ ++ ++static void amba11uart_start_tx(struct uart_port *port, unsigned int tty_start) ++{ ++ unsigned int mask; ++ ++ mask = UART_GET_IMSC(port); ++ if( (mask & AMBA_UARTIMSC_TXIM) == 0) { /* not already enabled */ ++ mask |= AMBA_UARTIMSC_TXIM; /* enable Tx interrupts */ ++ UART_PUT_IMSC(port, mask); ++ ++ amba11uart_tx_chars(port); /* start transmiting */ ++ } ++ ++} ++ ++ ++static void amba11uart_stop_rx(struct uart_port *port) ++{ ++ unsigned int mask; ++ ++ mask = UART_GET_IMSC(port); ++ mask &= ~(AMBA_UARTIMSC_RXIM | AMBA_UARTIMSC_RTIM); ++ UART_PUT_IMSC(port, mask); /* disable Rx interrupts */ ++} ++ ++ ++static void amba11uart_enable_ms(struct uart_port *port) ++{ ++ unsigned int mask; ++ ++ mask = UART_GET_IMSC( port); ++ mask |= AMBA_UARTIMSC_Modem; ++ UART_PUT_IMSC(port, mask); /* Disable modem interrupts */ ++} ++ ++static void ++#ifdef SUPPORT_SYSRQ ++amba11uart_rx_chars(struct uart_port *port, struct pt_regs *regs) ++#else ++amba11uart_rx_chars(struct uart_port *port) ++#endif ++{ ++ struct tty_struct *tty = port->info->tty; ++ unsigned int status, ch, rsr, max_count = 256; ++ ++ status = UART_GET_FR(port); ++ while (UART_RX_DATA(status) && max_count--) { ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ tty->flip.tqueue.routine((void *)tty); ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ printk(KERN_WARNING "TTY_DONT_FLIP set\n"); ++ return; ++ } ++ } ++ ++ ch = UART_GET_CHAR(port); ++ ++ *tty->flip.char_buf_ptr = ch; ++ *tty->flip.flag_buf_ptr = TTY_NORMAL; ++ port->icount.rx++; ++ ++ /* ++ * Note that the error handling code is ++ * out of the main execution path ++ */ ++ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; ++ if (rsr & AMBA_UARTRSR_ANY) { ++ if (rsr & AMBA_UARTRSR_BE) { ++ rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE); ++ port->icount.brk++; ++ if (uart_handle_sysrq_char(port, ch, regs)) ++ goto ignore_char; ++ } else if (rsr & AMBA_UARTRSR_PE) ++ port->icount.parity++; ++ else if (rsr & AMBA_UARTRSR_FE) ++ port->icount.frame++; ++ if (rsr & AMBA_UARTRSR_OE) ++ port->icount.overrun++; ++ ++ rsr &= port->read_status_mask; ++ ++ if (rsr & AMBA_UARTRSR_BE) ++ *tty->flip.flag_buf_ptr = TTY_BREAK; ++ else if (rsr & AMBA_UARTRSR_PE) ++ *tty->flip.flag_buf_ptr = TTY_PARITY; ++ else if (rsr & AMBA_UARTRSR_FE) ++ *tty->flip.flag_buf_ptr = TTY_FRAME; ++ } ++ ++ if (uart_handle_sysrq_char(port, ch, regs)) ++ goto ignore_char; ++ ++ if ((rsr & port->ignore_status_mask) == 0) { ++ tty->flip.flag_buf_ptr++; ++ tty->flip.char_buf_ptr++; ++ tty->flip.count++; ++ } ++ if ((rsr & AMBA_UARTRSR_OE) && ++ tty->flip.count < TTY_FLIPBUF_SIZE) { ++ /* ++ * Overrun is special, since it's reported ++ * immediately, and doesn't affect the current ++ * character ++ */ ++ *tty->flip.char_buf_ptr++ = 0; ++ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; ++ tty->flip.count++; ++ } ++ ignore_char: ++ status = UART_GET_FR(port); ++ } ++ tty_flip_buffer_push(tty); ++ return; ++} ++ ++static void amba11uart_tx_chars(struct uart_port *port) ++{ ++ struct circ_buf *xmit = &port->info->xmit; ++ int count; ++ int status; ++ ++ if (port->x_char) { ++ UART_PUT_CHAR(port, port->x_char); ++ port->icount.tx++; ++ port->x_char = 0; ++ return; ++ } ++ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { ++ amba11uart_stop_tx(port, 0); ++ return; ++ } ++ ++ count = port->fifosize >> 1; ++ do { ++ UART_PUT_CHAR(port, xmit->buf[xmit->tail]); ++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ++ port->icount.tx++; ++ if (uart_circ_empty(xmit)) ++ break; ++ status = UART_GET_FR(port); ++ } while (UART_TX_READY(status)); ++ //FJBwhile (--count > 0); ++ ++ if (uart_circ_chars_pending(xmit) < ++ WAKEUP_CHARS) ++ uart_write_wakeup(port); ++ ++ if (uart_circ_empty(xmit)) ++ amba11uart_stop_tx(port, 0); ++} ++ ++static void amba11uart_modem_status(struct uart_port *port) ++{ ++ struct uart_amba11_port *uap = (struct uart_amba11_port *) port; ++ unsigned int status, delta; ++ ++ UART_PUT_ICR(&uap->port, 0x3ff); ++ ++ status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY; ++ //FJB - check CTS on modem port only (port 1) ++ if(port == (struct uart_port *)UART1_PHYS) ++ { ++ if(GPIOG->dr & 0x01) ++ { ++ //CTS is high meaning STOP SENDING ++ status |= AMBA_UARTFR_CTS; ++ } ++ } ++ ++ delta = status ^ uap->old_status; ++ uap->old_status = status; ++ ++ if (!delta) ++ return; ++ ++ if (delta & AMBA_UARTFR_DCD) ++ uart_handle_dcd_change(&uap->port, (status & AMBA_UARTFR_DCD) == 0); ++ ++ if ((delta & AMBA_UARTFR_DSR) == 0) ++ uap->port.icount.dsr++; ++ ++ if (delta & AMBA_UARTFR_CTS) ++ uart_handle_cts_change(&uap->port, (status & AMBA_UARTFR_CTS) == 0); ++ ++ wake_up_interruptible(&uap->port.info->delta_msr_wait); ++} ++ ++static void amba11uart_int(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; ++ ++ status = UART_GET_INT_STATUS(port); ++ do { ++ if (status & (AMBA_UART_IS_RT | AMBA_UART_IS_RX)) ++ ++#ifdef SUPPORT_SYSRQ ++ amba11uart_rx_chars(port, regs); ++#else ++ amba11uart_rx_chars(port); ++#endif ++ ++ if (status & AMBA_UART_IS_TX) ++ amba11uart_tx_chars(port); ++ ++ ++ if (status & AMBA_UART_IS_MI) ++ amba11uart_modem_status(port); ++ ++ if (pass_counter-- == 0) ++ break; ++ ++ status = UART_GET_INT_STATUS(port); ++ } while (status & (AMBA_UART_IS_RT | AMBA_UART_IS_RX | ++ AMBA_UART_IS_TX)); ++} ++ ++static unsigned int amba11uart_tx_empty(struct uart_port *port) ++{ ++ return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT; ++} ++ ++static unsigned int amba11uart_get_mctrl(struct uart_port *port) ++{ ++ unsigned int result = 0; ++ unsigned int status; ++ ++ status = UART_GET_FR(port); ++ if ((status & AMBA_UARTFR_DCD) == 0) ++ result |= TIOCM_CAR; ++ if ((status & AMBA_UARTFR_DSR) == 0) ++ result |= TIOCM_DSR; ++ if ((status & AMBA_UARTFR_CTS) == 0) ++ result |= TIOCM_CTS; ++ ++ return result; ++} ++ ++static void amba11uart_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ u_int cr; ++ ++ cr = UART_GET_CR( port); ++ ++ if (mctrl & TIOCM_RTS) ++ cr &= ~AMBA_UARTCR_RTS; ++ else ++ cr |= AMBA_UARTCR_RTS; ++ ++ if (mctrl & TIOCM_DTR) ++ cr &= ~AMBA_UARTCR_DTR; ++ else ++ cr |= AMBA_UARTCR_DTR; ++ ++ UART_PUT_CR( port, cr); ++} ++ ++ ++static void amba11uart_break_ctl(struct uart_port *port, int break_state) ++{ ++ unsigned int lcr_h; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ lcr_h = UART_GET_LCRH(port); ++ if (break_state == -1) ++ lcr_h |= AMBA_UARTLCR_H_BRK; ++ else ++ lcr_h &= ~AMBA_UARTLCR_H_BRK; ++ UART_PUT_LCRH(port, lcr_h); ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++static int amba11uart_startup(struct uart_port *port) ++{ ++ int retval; ++ struct uart_amba11_port *uap = (struct uart_amba11_port *)port; ++ ++ /* ++ * Allocate the IRQ ++ */ ++ retval = request_irq(port->irq, amba11uart_int, 0, "amba", port); ++ if (retval) ++ return retval; ++ ++ /* ++ * initialise the old status of the modem signals ++ */ ++ uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY; ++ ++ /* ++ * Finally, enable interrupts ++ */ ++#ifdef CONFIG_ARCH_LH79520 ++ { ++ /* ++ * enable the clock to the serial ports ++ */ ++ rcpcRegs_t *rcpc = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ ioconRegs_t *iocon = (ioconRegs_t *)IO_ADDRESS( IOCON_PHYS); ++ ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; /* unlock RCPC registers */ ++ barrier(); ++ ++ rcpc->periphClkCtrl &= ~(RCPC_CLKCTRL_U0_DISABLE | RCPC_CLKCTRL_U1_DISABLE | RCPC_CLKCTRL_U2_DISABLE) ; ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; /* lock RCPC registers */ ++ ++ /* set multiplexed pins for UART0 use */ ++ iocon->UARTMux |= (UARTMUX_UT0TXD | UARTMUX_UT0RXD); ++ } ++#endif /* CONFIG_ARCH_LH79520 */ ++ ++ /* ++ * Use iobase to store a pointer to info. We need this to start a ++ * transmission as the tranmittr interrupt is only generated on ++ * the transition to the idle state ++ */ ++ ++ UART_PUT_IMSC( port, (AMBA_UARTIMSC_RXIM | AMBA_UARTIMSC_RTIM) ); ++ UART_PUT_CR( port, (AMBA_UARTCR_UARTEN | AMBA_UARTCR_RXE | AMBA_UARTCR_TXE)); ++ ++ return 0; ++} ++ ++static void amba11uart_shutdown(struct uart_port *port) ++{ ++ /* ++ * Free the interrupt ++ */ ++ free_irq(port->irq, port); ++ ++ /* ++ * disable all interrupts, disable the port ++ */ ++ UART_PUT_CR(port, 0); ++ ++ /* disable break condition and fifos */ ++ UART_PUT_LCRH(port, UART_GET_LCRH(port) & ++ ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN)); ++} ++ ++static void amba11uart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot) ++{ ++ unsigned int lcr_h, old_cr; ++ unsigned long flags; ++ unsigned long old_imsc; ++ ++#if DEBUG ++ printk("amba11uart_set_cflag(0x%x) called\n", cflag); ++#endif ++ /* byte size and parity */ ++ switch (cflag & CSIZE) { ++ case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; break; ++ case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; break; ++ case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; break; ++ default: lcr_h = AMBA_UARTLCR_H_WLEN_8; break; // CS8 ++ } ++ if (cflag & CSTOPB) ++ lcr_h |= AMBA_UARTLCR_H_STP2; ++ if (cflag & PARENB) { ++ lcr_h |= AMBA_UARTLCR_H_PEN; ++ if (!(cflag & PARODD)) ++ lcr_h |= AMBA_UARTLCR_H_EPS; ++ } ++ if (port->fifosize > 1) ++ lcr_h |= AMBA_UARTLCR_H_FEN; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ ++ port->read_status_mask = AMBA_UARTRSR_OE; ++ if (iflag & INPCK) ++ port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; ++ if (iflag & (BRKINT | PARMRK)) ++ port->read_status_mask |= AMBA_UARTRSR_BE; ++ ++ /* ++ * Characters to ignore ++ */ ++ port->ignore_status_mask = 0; ++ if (iflag & IGNPAR) ++ port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; ++ if (iflag & IGNBRK) { ++ port->ignore_status_mask |= AMBA_UARTRSR_BE; ++ /* ++ * If we're ignoring parity and break indicators, ++ * ignore overruns too (for real raw support). ++ */ ++ if (iflag & IGNPAR) ++ port->ignore_status_mask |= AMBA_UARTRSR_OE; ++ } ++ ++ /* ++ * Ignore all characters if CREAD is not set. ++ */ ++ if ((cflag & CREAD) == 0) ++ port->ignore_status_mask |= UART_DUMMY_RSR_RX; ++ ++ old_cr = UART_GET_CR( port); ++ old_imsc = UART_GET_IMSC( port) & ~AMBA_UARTIMSC_Modem; ++ ++ if (UART_ENABLE_MS(port, cflag)) ++ old_imsc |= AMBA_UARTIMSC_Modem; ++ ++ /* Set baud rate */ ++ UART_PUT_IBRD( port, quot); ++ ++ /* ++ * ----------v----------v----------v----------v----- ++ * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L ++ * ----------^----------^----------^----------^----- ++ */ ++ UART_PUT_LCRH(port, lcr_h); ++ UART_PUT_IMSC( port, old_imsc); ++ UART_PUT_CR(port, old_cr); ++ ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++static const char *amba11uart_type(struct uart_port *port) ++{ ++ return port->type == PORT_AMBA_PL011 ? "AMBA PrimeCell PL011" : NULL; ++} ++ ++/* ++ * Release the memory region(s) being used by 'port' ++ */ ++static void amba11uart_release_port(struct uart_port *port) ++{ ++ release_mem_region(port->mapbase, UART_PORT_SIZE); ++} ++ ++/* ++ * Request the memory region(s) being used by 'port' ++ */ ++static int amba11uart_request_port(struct uart_port *port) ++{ ++ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba") ++ != NULL ? 0 : -EBUSY; ++} ++ ++/* ++ * Configure/autoconfigure the port. ++ */ ++static void amba11uart_config_port(struct uart_port *port, int flags) ++{ ++ if (flags & UART_CONFIG_TYPE) { ++ port->type = PORT_AMBA_PL011; ++ amba11uart_request_port(port); ++ } ++} ++ ++/* ++ * verify the new serial_struct (for TIOCSSERIAL). ++ */ ++static int amba11uart_verify_port(struct uart_port *port, struct serial_struct *ser) ++{ ++ int ret = 0; ++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA_PL011) ++ ret = -EINVAL; ++ if (ser->irq < 0 || ser->irq >= NR_IRQS) ++ ret = -EINVAL; ++ if (ser->baud_base < 9600) ++ ret = -EINVAL; ++ return ret; ++} ++ ++static struct uart_ops amba11_pops = { ++ tx_empty: amba11uart_tx_empty, ++ set_mctrl: amba11uart_set_mctrl, ++ get_mctrl: amba11uart_get_mctrl, ++ stop_tx: amba11uart_stop_tx, ++ start_tx: amba11uart_start_tx, ++ stop_rx: amba11uart_stop_rx, ++ enable_ms: amba11uart_enable_ms, ++ break_ctl: amba11uart_break_ctl, ++ startup: amba11uart_startup, ++ shutdown: amba11uart_shutdown, ++ change_speed: amba11uart_change_speed, ++ type: amba11uart_type, ++ release_port: amba11uart_release_port, ++ request_port: amba11uart_request_port, ++ config_port: amba11uart_config_port, ++ verify_port: amba11uart_verify_port, ++}; ++ ++static struct uart_amba11_port amba11_ports[UART_NR] = { ++ { ++ .port = { ++ .membase= (void *)IO_ADDRESS(UART0_PHYS), // VA ++ .mapbase= UART0_PHYS, ++ .iotype= SERIAL_IO_MEM, ++ .irq= IRQ_UART0, ++ .uartclk= 14745600, ++ .fifosize= 16, ++ .ops= &amba11_pops, ++ .flags= ASYNC_BOOT_AUTOCONF, ++ .line= 0, ++ }, ++ }, ++ { ++ .port = { ++ .membase= (void *)IO_ADDRESS(UART1_PHYS), ++ .mapbase= UART1_PHYS, ++ .iotype= SERIAL_IO_MEM, ++ .irq= IRQ_UART1, ++ .uartclk= 14745600, ++ .fifosize= 16, ++ .ops= &amba11_pops, ++ .flags= ASYNC_BOOT_AUTOCONF, ++ .line= 1, ++ }, ++ }, ++ { ++ .port = { ++ .membase= (void *)IO_ADDRESS(UART2_PHYS), ++ .mapbase= UART2_PHYS, ++ .iotype= SERIAL_IO_MEM, ++ .irq= IRQ_UART2, ++ .uartclk= 14745600, ++ .fifosize= 16, ++ .ops= &amba11_pops, ++ .flags= ASYNC_BOOT_AUTOCONF, ++ .line= 2, ++ }, ++ }, ++}; ++ ++ ++#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE ++#ifdef used_and_not_const_char_pointer ++static int amba11uart_console_read(struct uart_port *port, char *s, u_int count) ++{ ++ unsigned int status; ++ int c; ++#if DEBUG ++ printk("amba11uart_console_read() called\n"); ++#endif ++ ++ c = 0; ++ while (c < count) { ++ status = UART_GET_FR(port); ++ if (UART_RX_DATA(status)) { ++ *s++ = UART_GET_CHAR(port); ++ c++; ++ } else { ++ // nothing more to get, return ++ return c; ++ } ++ } ++ // return the count ++ return c; ++} ++#endif ++ ++static void amba11uart_console_write(struct console *co, const char *s, u_int count) ++{ ++ struct uart_port *port = &amba11_ports[co->index].port; ++ unsigned int status; ++ int i; ++ ++ /* ++ * First save the CR then disable the interrupts ++ */ ++ unsigned int old_imsc; ++ old_imsc = UART_GET_IMSC( port); ++ UART_PUT_IMSC( port, 0); ++ ++ /* ++ * Now, do each character ++ */ ++ for (i = 0; i < count; i++) { ++ do { ++ status = UART_GET_FR(port); ++ } while (!UART_TX_READY(status)); ++ UART_PUT_CHAR(port, s[i]); ++ if (s[i] == '\n') { ++ do { ++ status = UART_GET_FR(port); ++ } while (!UART_TX_READY(status)); ++ UART_PUT_CHAR(port, '\r'); ++ } ++ } ++ ++ /* ++ * Finally, wait for transmitter to become empty ++ * and restore the TCR ++ */ ++ do { ++ status = UART_GET_FR(port); ++ } while (status & AMBA_UARTFR_BUSY); ++ UART_PUT_IMSC( port, old_imsc); ++} ++ ++static kdev_t amba11uart_console_device(struct console *co) ++{ ++ return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index); ++} ++ ++static int amba11uart_console_wait_key(struct console *co) ++{ ++ struct uart_port *port = &amba11_ports[co->index].port; ++ unsigned int status; ++ ++ do { ++ status = UART_GET_FR(port); ++ } while (!UART_RX_DATA(status)); ++ return UART_GET_CHAR(port); ++} ++ ++static void __init ++amba11uart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) ++{ ++ if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) { ++ unsigned int lcr_h, quot; ++ lcr_h = UART_GET_LCRH(port); ++ ++ *parity = 'n'; ++ if (lcr_h & AMBA_UARTLCR_H_PEN) { ++ if (lcr_h & AMBA_UARTLCR_H_EPS) ++ *parity = 'e'; ++ else ++ *parity = 'o'; ++ } ++ ++ if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7) ++ *bits = 7; ++ else ++ *bits = 8; ++ ++ quot = UART_GET_IBRD(port); ++ *baud = port->uartclk / (16 * quot ); ++ } ++} ++ ++static int __init amba11uart_console_setup(struct console *co, char *options) ++{ ++ struct uart_port *port; ++ int baud = 38400; ++ int bits = 8; ++ int parity = 'n'; ++ int flow = 'n'; ++ ++ /* ++ * Check whether an invalid uart number has been specified, and ++ * if so, search for the first available port that does have ++ * console support. ++ */ ++ if (co->index >= UART_NR) ++ co->index = 0; ++ port = &amba11_ports[co->index].port; ++ ++ if (options) ++ uart_parse_options(options, &baud, &parity, &bits, &flow); ++ else ++ amba11uart_console_get_options(port, &baud, &parity, &bits); ++ ++ return uart_set_options(port, co, baud, parity, bits, flow); ++} ++ ++static struct console amba11_console = { ++ name: "ttyAM", ++ write: amba11uart_console_write, ++#ifdef used_and_not_const_char_pointer ++ read: amba11uart_console_read, ++#endif ++ device: amba11uart_console_device, ++ setup: amba11uart_console_setup, ++ flags: CON_PRINTBUFFER, ++ index: -1, ++}; ++ ++void __init amba11uart_console_init(void) ++{ ++ register_console(&amba11_console); ++} ++ ++#define AMBA_CONSOLE &amba11_console ++#else ++#define AMBA_CONSOLE NULL ++#endif ++ ++static struct uart_driver amba11_reg = { ++ owner: THIS_MODULE, ++ normal_major: SERIAL_AMBA_MAJOR, ++#ifdef CONFIG_DEVFS_FS ++ normal_name: "ttyAM%d", ++ callout_name: "cuaam%d", ++#else ++ normal_name: "ttyAM", ++ callout_name: "cuaam", ++#endif ++ normal_driver: &normal, ++ callout_major: CALLOUT_AMBA_MAJOR, ++ callout_driver: &callout, ++ table: amba11_table, ++ termios: amba11_termios, ++ termios_locked: amba11_termios_locked, ++ minor: SERIAL_AMBA_MINOR, ++ nr: UART_NR, ++ cons: AMBA_CONSOLE, ++}; ++ ++static int __init amba11uart_init(void) ++{ ++ int ret; ++ ++ ret = uart_register_driver(&amba11_reg); ++ if (ret == 0) { ++ int i; ++ ++ for (i = 0; i < UART_NR; i++) ++ uart_add_one_port(&amba11_reg, &amba11_ports[i].port); ++ } ++ return ret; ++}; ++ ++static void __exit amba11uart_exit(void) ++{ ++ int i; ++ ++ for (i = 0; i < UART_NR; i++) ++ uart_remove_one_port(&amba11_reg, &amba11_ports[i].port); ++ ++ uart_unregister_driver(&amba11_reg); ++}; ++ ++module_init(amba11uart_init); ++module_exit(amba11uart_exit); ++ ++EXPORT_NO_SYMBOLS; ++ ++MODULE_AUTHOR("Lineo, Inc."); ++MODULE_DESCRIPTION("ARM AMBA PrimeCell PL011 serial port driver"); ++MODULE_LICENSE("GPL"); ++ +diff -urN linux-2.4.26/drivers/serial/Config.in linux-2.4.26-vrs1-lnode80/drivers/serial/Config.in +--- linux-2.4.26/drivers/serial/Config.in 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/serial/Config.in 2005-11-02 17:37:31.000000000 -0400 +@@ -20,6 +20,22 @@ + define_bool CONFIG_SERIAL_INTEGRATOR y + fi + ++ dep_tristate 'ARM PL011 PrimeCell serial port support' CONFIG_SERIAL_AMBA_PL011 $CONFIG_ARCH_LH79520 ++ ++ if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then ++ bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE ++ fi ++ ++ if [ "$CONFIG_SERIAL_AMBA_PL011" = "y" ]; then ++ bool ' Support for console on ARM PrimeCell PL011 serial port' CONFIG_SERIAL_AMBA_PL011_CONSOLE ++ fi ++ ++ dep_tristate 'Sharp LH7A400 serial port support' CONFIG_SERIAL_LH7A400 $CONFIG_ARCH_LH7A400 ++ ++ if [ "$CONFIG_SERIAL_LH7A400" = "y" ]; then ++ bool ' Support for console on LH7A400 serial port' CONFIG_SERIAL_LH7A400_CONSOLE ++ fi ++ + dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X + dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X + +@@ -57,6 +73,8 @@ + dep_bool ' Support Bell Technologies HUB6 card' CONFIG_SERIAL_8250_HUB6 $CONFIG_SERIAL_8250_EXTENDED + + if [ "$CONFIG_SERIAL_AMBA" = "y" -o \ ++ "$CONFIG_SERIAL_AMBA_PL011" = "y" -o \ ++ "$CONFIG_SERIAL_LH7A400" = "y" -o \ + "$CONFIG_SERIAL_CLPS711X" = "y" -o \ + "$CONFIG_SERIAL_SA1100" = "y" -o \ + "$CONFIG_SERIAL_ANAKIN" = "y" -o \ +@@ -67,6 +85,8 @@ + define_bool CONFIG_SERIAL_CORE y + else + if [ "$CONFIG_SERIAL_AMBA" = "m" -o \ ++ "$CONFIG_SERIAL_AMBA_PL011" = "m" -o \ ++ "$CONFIG_SERIAL_LH7A400" = "m" -o \ + "$CONFIG_SERIAL_CLPS711X" = "m" -o \ + "$CONFIG_SERIAL_SA1100" = "m" -o \ + "$CONFIG_SERIAL_ANAKIN" = "m" -o \ +@@ -78,6 +98,8 @@ + fi + fi + if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \ ++ "$CONFIG_SERIAL_AMBA_PL011_CONSOLE" = "y" -o \ ++ "$CONFIG_SERIAL_LH7A400_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \ +diff -urN linux-2.4.26/drivers/serial/core.c linux-2.4.26-vrs1-lnode80/drivers/serial/core.c +--- linux-2.4.26/drivers/serial/core.c 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/serial/core.c 2005-11-02 17:37:32.000000000 -0400 +@@ -1938,6 +1938,7 @@ + } + + extern void ambauart_console_init(void); ++extern void amba11uart_console_init(void); + extern void anakin_console_init(void); + extern void clps711xuart_console_init(void); + extern void sa1100_rs_console_init(void); +@@ -1970,6 +1971,12 @@ + #ifdef CONFIG_SERIAL_UART00_CONSOLE + uart00_console_init(); + #endif ++#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE ++ amba11uart_console_init(); ++#endif ++#ifdef CONFIG_SERIAL_LH7A400_CONSOLE ++ lh7a400uart_console_init(); ++#endif + } + #endif /* CONFIG_SERIAL_CORE_CONSOLE */ + +diff -urN linux-2.4.26/drivers/serial/Makefile linux-2.4.26-vrs1-lnode80/drivers/serial/Makefile +--- linux-2.4.26/drivers/serial/Makefile 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/serial/Makefile 2005-11-02 17:37:31.000000000 -0400 +@@ -27,6 +27,8 @@ + obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) + obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o + obj-$(CONFIG_SERIAL_AMBA) += amba.o ++obj-$(CONFIG_SERIAL_AMBA_PL011) += amba_pl011.o ++obj-$(CONFIG_SERIAL_LH7A400) += serial_lh7a400.o + obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o + obj-$(CONFIG_SERIAL_SA1100) += sa1100.o + obj-$(CONFIG_SERIAL_UART00) += uart00.o +diff -urN linux-2.4.26/drivers/video/Config.in linux-2.4.26-vrs1-lnode80/drivers/video/Config.in +--- linux-2.4.26/drivers/video/Config.in 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/Config.in 2005-11-02 17:37:32.000000000 -0400 +@@ -40,6 +40,11 @@ + dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X + dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100 + dep_bool ' MX1ADS LCD support' CONFIG_FB_DBMX1 $CONFIG_ARCH_MX1ADS ++ if [ "$CONFIG_ARCH_LH79520" = "y" -o \ ++ "$CONFIG_ARCH_LH7A400" = "y" ];then ++ bool ' ARM PL110 LCD support' CONFIG_FB_PL110 ++ fi ++ + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then + choice 'CerfBoard LCD Display Size' \ + "3.8_Color CONFIG_CERF_LCD_38_A \ +@@ -50,6 +55,15 @@ + if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then + bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT + fi ++ if [ "$CONFIG_FB_PL110" = "y" ]; then ++ choice 'LCD Display panel' \ ++ "Panasonic CONFIG_PL110_PAN78 \ ++ Sharp_LQ039Q2DS53-HR-TFT CONFIG_PL110_LQ39 \ ++ Sharp_LM057QCTT03-QVGA-STN CONFIG_PL110_LM57 \ ++ Sharp_LQ057Q3DC02-VGA/QVGA-TFT CONFIG_PL110_LQ57 \ ++ Sharp_LQ121S1DG31-800x600-TFT CONFIG_PL110_LQ121 \ ++ Sharp_LQ104V1DG11-640x480-TFT CONFIG_PL110_LQ104" Sharp_LQ039Q2DS53-HR-TFT ++ fi + fi + dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI + if [ "$CONFIG_APOLLO" = "y" ]; then +@@ -280,7 +294,8 @@ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ + "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ +- "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" ]; then ++ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ ++ "$CONFIG_FB_PL110" = "y" ]; then + define_tristate CONFIG_FBCON_MFB y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ +@@ -288,20 +303,22 @@ + "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ + "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ +- "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then ++ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" -o \ ++ "$CONFIG_FB_PL110" = "m" ]; then + define_tristate CONFIG_FBCON_MFB m + fi + fi + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ +- "$CONFIG_FB_DBMX1" = "y" ]; then ++ "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PL110" = "y"]; then + define_tristate CONFIG_FBCON_CFB2 y + define_tristate CONFIG_FBCON_CFB4 y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ +- "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then ++ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" -o \ ++ "$CONFIG_FB_PL110" = "m" ]; then + define_tristate CONFIG_FBCON_CFB2 m + define_tristate CONFIG_FBCON_CFB4 m + fi +@@ -329,6 +346,7 @@ + "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \ + "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \ + "$CONFIG_FB_INTEL" = "y" -o \ ++ "$CONFIG_FB_PL110" = "y" -o \ + "$CONFIG_FB_DBMX1" = "y" ]; then + define_tristate CONFIG_FBCON_CFB8 y + else +@@ -352,6 +370,7 @@ + "$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_INTEL" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ + "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" -o \ ++ "$CONFIG_FB_PL110" = "m" -o \ + "$CONFIG_FB_STI" = "m" -o "$CONFIG_FB_INTEL" = "m" ]; then + define_tristate CONFIG_FBCON_CFB8 m + fi +@@ -373,6 +392,7 @@ + "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \ + "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \ + "$CONFIG_FB_ANAKIN" = "y" -o \ ++ "$CONFIG_FB_PL110" = "y" -o \ + "$CONFIG_FB_DBMX1" = "y" ]; then + define_tristate CONFIG_FBCON_CFB16 y + else +@@ -390,6 +410,7 @@ + "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ + "$CONFIG_FB_INTEL" = "m" -o \ ++ "$CONFIG_FB_PL110" = "m" -o \ + "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \ + "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_INTEL" = "m" ]; then + define_tristate CONFIG_FBCON_CFB16 m +diff -urN linux-2.4.26/drivers/video/fbcon.c linux-2.4.26-vrs1-lnode80/drivers/video/fbcon.c +--- linux-2.4.26/drivers/video/fbcon.c 2003-08-25 07:44:42.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/fbcon.c 2005-11-02 17:37:32.000000000 -0400 +@@ -2401,9 +2401,9 @@ + p->type == FB_TYPE_INTERLEAVED_PLANES)) { + + /* monochrome */ +- unsigned char inverse = p->inverse || p->visual == FB_VISUAL_MONO01 +- ? 0x00 : 0xff; +- ++ //FJBunsigned char inverse = p->inverse || p->visual == FB_VISUAL_MONO01 ++ //FJB ? 0x00 : 0xff; ++ unsigned char inverse = 0; + int is_hga = !strncmp(p->fb_info->modename, "HGA", 3); + /* can't use simply memcpy because need to apply inverse */ + for( y1 = 0; y1 < LOGO_H; y1++ ) { +diff -urN linux-2.4.26/drivers/video/fbmem.c linux-2.4.26-vrs1-lnode80/drivers/video/fbmem.c +--- linux-2.4.26/drivers/video/fbmem.c 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/fbmem.c 2005-11-02 17:37:32.000000000 -0400 +@@ -109,6 +109,7 @@ + extern int chips_init(void); + extern int g364fb_init(void); + extern int sa1100fb_init(void); ++extern int pl110fb_init(void); + extern int fm2fb_init(void); + extern int fm2fb_setup(char*); + extern int q40fb_init(void); +@@ -305,6 +306,9 @@ + #ifdef CONFIG_FB_SA1100 + { "sa1100", sa1100fb_init, NULL }, + #endif ++#ifdef CONFIG_FB_PL110 ++ { "pl110", pl110fb_init, NULL }, ++#endif + #ifdef CONFIG_FB_SUN3 + { "sun3", sun3fb_init, sun3fb_setup }, + #endif +diff -urN linux-2.4.26/drivers/video/Makefile linux-2.4.26-vrs1-lnode80/drivers/video/Makefile +--- linux-2.4.26/drivers/video/Makefile 2005-11-02 16:54:25.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/Makefile 2005-11-02 17:37:32.000000000 -0400 +@@ -4,6 +4,14 @@ + + O_TARGET := video.o + ++# ++# The following is VERY IMPORTANT for the pl110; newer gccs won't compile the driver ++# properly and it will hang at "Console: switching to colour frame buffer device ..." ++# ++ifeq ($(CONFIG_FB_PL110),y) ++EXTRA_CFLAGS =-O1 ++endif ++ + mod-subdirs := matrox sti + + # All of the (potential) objects that export symbols. +@@ -15,7 +23,7 @@ + fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \ + fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \ + fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \ +- cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o ++ cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o pl110fb.o + + # Each configuration option enables a list of files. + +@@ -137,6 +145,7 @@ + obj-$(CONFIG_FB_PVR2) += pvr2fb.o + obj-$(CONFIG_FB_VOODOO1) += sstfb.o + obj-$(CONFIG_FB_ANAKIN) += anakinfb.o ++obj-$(CONFIG_FB_PL110) += pl110fb.o + + # Generic Low Level Drivers + +diff -urN linux-2.4.26/drivers/video/pl110fb.c linux-2.4.26-vrs1-lnode80/drivers/video/pl110fb.c +--- linux-2.4.26/drivers/video/pl110fb.c 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/pl110fb.c 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,1719 @@ ++/* ++ * linux/drivers/video/pl110fb.c ++ * ++ * ARM PrimeCell PL110 LCD Controller Frame Buffer Driver ++ * ++ * Copyright (C) 2002 Lineo, Inc. ++ * Based on sa1100fb.c, which is Copyright (C) Eric A. Thomas ++ * ++ * 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 <linux/config.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/errno.h> ++#include <linux/string.h> ++#include <linux/interrupt.h> ++#include <linux/slab.h> ++#include <linux/fb.h> ++#include <linux/delay.h> ++#include <linux/pm.h> ++#include <linux/init.h> ++#include <linux/cpufreq.h> ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/uaccess.h> ++ ++#include <video/fbcon.h> ++#include <video/fbcon-mfb.h> ++#include <video/fbcon-cfb4.h> ++#include <video/fbcon-cfb8.h> ++#include <video/fbcon-cfb16.h> ++ ++#ifdef CONFIG_ARCH_LH79520 ++#include <asm/arch/rcpc.h> ++#include <asm/arch/cpld.h> ++#include <asm/arch/iocon.h> ++#endif ++ ++#ifdef CONFIG_ARCH_LH7A400 ++#include <asm/arch/cpld.h> ++#include <asm/arch/gpio.h> ++#endif ++ ++/* ++ * debugging? ++ */ ++#define DEBUG 0 ++/* ++ * Complain if VAR is out of range. ++ */ ++#define DEBUG_VAR 1 ++#define BACKLIGHT _BIT(15) ++//#define GPOUT16 (*(volatile u16*)GPOUT16_BASE) ++ ++//#define GPOUT16 (*(volatile u16*)GPOUT16_BASE) ++ ++// global defined in marm-lh7x.c -- driver ++extern unsigned short marm_backlight; ++#define GPOUT16 marm_backlight ++ ++#include "pl110fb.h" ++ ++extern unsigned int hclkfreq_get( void); ++ ++void (*pl110fb_blank_helper)(int blank); ++EXPORT_SYMBOL(pl110fb_blank_helper); ++ ++ ++//#define _444 1 ++#define _555 1 ++ ++#if _444 ++static struct pl110fb_rgb rgb_8 = { ++ red: { offset: 0, length: 4, }, ++ green: { offset: 0, length: 4, }, ++ blue: { offset: 0, length: 4, }, ++ transp: { offset: 0, length: 0, }, ++}; ++#elif _555 ++static struct pl110fb_rgb rgb_8 = { ++ red: { offset: 0, length: 5, }, ++ green: { offset: 0, length: 5, }, ++ blue: { offset: 0, length: 5, }, ++ transp: { offset: 0, length: 0, }, ++}; ++#else ++#error define _444 or _555 ++#endif ++ ++ ++#if 0 // 5-6-5 ++static struct pl110fb_rgb def_rgb_16 = { ++ red: { offset: 11, length: 5, }, ++ green: { offset: 5, length: 6, }, ++ blue: { offset: 0, length: 5, }, ++ transp: { offset: 0, length: 0, }, ++}; ++#else // 5-5-5 ++static struct pl110fb_rgb def_rgb_16 = { ++ red: { offset: 10, length: 5, }, ++ green: { offset: 5, length: 5, }, ++ blue: { offset: 0, length: 5, }, ++ transp: { offset: 0, length: 0, }, ++}; ++#endif ++ ++ ++#define VERTICAL_REFRESH 70 /* optimum refresh rate, in Hz. */ ++ ++ ++#if defined(CONFIG_ARCH_LH79520) || defined(CONFIG_ARCH_LH7A400) ++static struct pl110fb_mach_info lh_info __initdata = { ++ ++#if defined(CONFIG_PL110_LQ39) ++ bpp: 8, ++ xres: 640, yres: 480, ++ hsync_len: 13, /* hsw */ vsync_len: 2, /* vsw */ ++ left_margin: 21, /* hbp */ upper_margin: 5, /* vbp */ ++ right_margin: 11, /* hfp */ lower_margin: 5, /* vfp */ ++ ++ sync: FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, ++ ++ LCDtiming2: 0, ++ ++ LCDtiming3: 0, ++ ++ LCDcontrol: LCD_CTRL_BW_COLOR | LCD_CTRL_WATERMARK , ++ ++ LCDICPcontrol: 0, //LCDICP_CONTROL_CLSEN | LCDICP_CONTROL_SPSEN, ++ ++ LCDICPsetup: LCDICP_SETUP_VERT_NORMAL | LCDICP_SETUP_HORIZ_NORMAL, ++ ++ LCDICPtiming1: LCDICP_TIMING1_PSDEL(9) | LCDICP_TIMING1_REVDEL(3) | LCDICP_TIMING1_LPDEL(14), ++ ++ LCDICPtiming2: LCDICP_TIMING2_PSDEL2(209) | LCDICP_TIMING2_SPLVALUE(34), ++ ++ /* ++ * The Sharp LQ039Q2DS53 panel takes an RGB666 signal, ++ * but we provide it with an RGB555 signal instead (def_rgb_16). ++ */ ++ ++ /* bpp set based on DIP switches on LCD board */ ++ ++// xres: 320, yres: 240, ++// hsync_len: 13, /* hsw */ vsync_len: 2, /* vsw */ ++// left_margin: 21, /* hbp */ upper_margin: 5, /* vbp */ ++// right_margin: 11, /* hfp */ lower_margin: 5, /* vfp */ ++ ++// sync: FB_SYNC_VERT_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, ++ ++// LCDtiming2: LCD_TIMING2_IPC, ++// ++// LCDtiming3: 0, ++// ++// LCDcontrol: LCD_CTRL_TFT | LCD_CTRL_BW_COLOR | LCD_CTRL_WATERMARK, ++// ++// LCDICPcontrol: LCDICP_CONTROL_CLSEN | LCDICP_CONTROL_SPSEN, ++// ++// LCDICPsetup: LCDICP_SETUP_MODE_HRTFT | LCDICP_SETUP_VERT_NORMAL | LCDICP_SETUP_HORIZ_NORMAL, ++// ++// LCDICPtiming1: LCDICP_TIMING1_PSDEL(9) | LCDICP_TIMING1_REVDEL(3) | LCDICP_TIMING1_LPDEL(14), ++// ++// LCDICPtiming2: LCDICP_TIMING2_PSDEL2(209) | LCDICP_TIMING2_SPLVALUE(34), ++ ++ ++#elif defined(CONFIG_PL110_PAN78) ++ bpp: 8, ++ xres: 640, yres: 480, ++ hsync_len: 13, /* hsw */ vsync_len: 2, /* vsw */ ++ left_margin: 21, /* hbp */ upper_margin: 5, /* vbp */ ++ right_margin: 11, /* hfp */ lower_margin: 5, /* vfp */ ++ ++ sync: FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, ++ ++ LCDtiming2: 0, ++ ++ LCDtiming3: 0, ++ ++ LCDcontrol: LCD_CTRL_BW_COLOR | LCD_CTRL_WATERMARK, ++ ++ LCDICPcontrol: 0, //LCDICP_CONTROL_CLSEN | LCDICP_CONTROL_SPSEN, ++ ++ LCDICPsetup: LCDICP_SETUP_VERT_NORMAL | LCDICP_SETUP_HORIZ_NORMAL, ++ ++ LCDICPtiming1: LCDICP_TIMING1_PSDEL(9) | LCDICP_TIMING1_REVDEL(3) | LCDICP_TIMING1_LPDEL(14), ++ ++ LCDICPtiming2: LCDICP_TIMING2_PSDEL2(209) | LCDICP_TIMING2_SPLVALUE(34), ++ ++#elif defined(CONFIG_PL110_LM57) ++ bpp: 8, ++ xres: 320, yres: 240, ++#elif defined(CONFIG_PL110_LQ57) ++ bpp: 8, ++ xres: 240, yres: 320, ++#elif defined(CONFIG_PL110_LQ121) ++ bpp: 4, ++ xres: 320, yres: 240, ++#elif defined(CONFIG_PL110_LQ101) ++#else ++#error "You must have an LCD panel configured" ++#endif ++}; ++#endif // CONFIG_ARCH_LH79520 || CONFIG_ARCH_LH7A400 ++ ++ ++ ++static struct pl110fb_mach_info * __init ++pl110fb_get_machine_info(struct pl110fb_info *fbi) ++{ ++ struct pl110fb_mach_info *inf = NULL; ++ ++#if defined(CONFIG_ARCH_LH79520) ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ u8 dipSw = (u8)~(cpld->display_dip_sw & 0xff); ++ ++ if( machine_is_lh79520evb()) { ++ inf = &lh_info; ++ ++ /* set bpp based on LCD board dip switch 0 */ ++ inf->bpp = 8; //(dipSw & 1 ? 8 : 16); ++ } ++#endif ++#if defined(CONFIG_ARCH_LH7A400) ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ u8 dipSw = (u8)~(cpld->u3.dispDipSw & 0xff); ++ ++ if( machine_is_lh7a400evb()) { ++ inf = &lh_info; ++ ++ /* set bpp based on LCD board dip switch 0 */ ++ inf->bpp = (dipSw & 1 ? 8 : 16); ++ } ++#endif ++ return inf; ++} ++ ++ ++static int pl110fb_activate_var(struct fb_var_screeninfo *var, struct pl110fb_info *); ++static void set_ctrlr_state(struct pl110fb_info *fbi, u_int state); ++ ++ ++static inline void ++pl110fb_schedule_task(struct pl110fb_info *fbi, u_int state) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ /* ++ * We need to handle two requests being made at the same time. ++ * There are two important cases: ++ * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) ++ * We must perform the unblanking, which will do our REENABLE for us. ++ * 2. When we are blanking, but immediately unblank before we have ++ * blanked. We do the "REENABLE" thing here as well, just to be sure. ++ */ ++ if (fbi->task_state == C_ENABLE && state == C_REENABLE) ++ state = (u_int) -1; ++ if (fbi->task_state == C_DISABLE && state == C_ENABLE) ++ state = C_REENABLE; ++ ++ if (state != (u_int)-1) { ++ fbi->task_state = state; ++ schedule_task(&fbi->task); ++ } ++ local_irq_restore(flags); ++} ++ ++/* ++ * Get the VAR structure pointer for the specified console ++ */ ++static inline struct fb_var_screeninfo * ++get_con_var(struct fb_info *info, int con) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var; ++} ++ ++/* ++ * Get the DISPLAY structure pointer for the specified console ++ */ ++static inline struct display * ++get_con_display(struct fb_info *info, int con) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ return (con < 0) ? fbi->fb.disp : &fb_display[con]; ++} ++ ++/* ++ * Get the CMAP pointer for the specified console ++ */ ++static inline struct fb_cmap * ++get_con_cmap(struct fb_info *info, int con) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ ++ return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap; ++} ++ ++static inline u_int ++chan_to_field(u_int chan, struct fb_bitfield *bf) ++{ ++ chan &= 0xffff; ++ chan >>= 16 - bf->length; ++ return chan << bf->offset; ++} ++ ++ ++static int ++pl110fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, ++ u_int trans, struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ u_int val, ret = 1; ++ lcdRegs_t *LCD = (lcdRegs_t *)IO_ADDRESS(LCD_PHYS); ++ ++ if (regno < fbi->palette_size) { ++ ++#if _444 // 4:4:4 ++ val = ((red >> 4) & 0x0F00) >> 7; // bits 4:0 ++ val |= ((green >> 8) & 0x00F0) << 2; // bits 9:5 ++ val |= ((blue >> 12) & 0x000F) << 11; // bits 14:10 ++#else // 5:5:5 ++ val = (red & 0xF800) >> 11; // bits 4:0 ++ val |= (green & 0xF800) >> 6; // bits 9:5 ++ val |= (blue & 0xF800) >> 1; // bits 14:10 ++ val |= 0x8000; // always set intensity bit ++#endif ++ ++ if( regno & 1) /* setting higher number entry */ ++ LCD->palette[regno >> 1] = (LCD->palette[regno >> 1] & 0x0000ffff) | (val << 16); ++ else /* setting lower number entry */ ++ LCD->palette[regno >> 1] = (LCD->palette[regno >> 1] & 0xffff0000) | val; ++ ++ /* */ ++// DPRINTK( "reg=%x r=%x g=%x b=%x t=%x addr=%x val=%x entry=%x\n", ++// regno, red, green, blue, trans, &LCD->palette[regno >> 1], val, ++// LCD->palette[regno >> 1]); ++ /* */ ++ ++ ret = 0; ++ } ++ return ret; ++} ++ ++static int ++pl110fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ++ u_int trans, struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ struct display *disp = get_con_display(info, fbi->currcon); ++ u_int val; ++ int ret = 1; ++ ++ /* ++ * If inverse mode was selected, invert all the colours ++ * rather than the register number. The register number ++ * is what you poke into the framebuffer to produce the ++ * colour you requested. ++ */ ++ if (disp->inverse) { ++ red = 0xffff - red; ++ green = 0xffff - green; ++ blue = 0xffff - blue; ++ } ++ ++ /* ++ * If greyscale is true, then we convert the RGB value ++ * to greyscale no mater what visual we are using. ++ */ ++ if (fbi->fb.var.grayscale) ++ red = green = blue = (19595 * red + 38470 * green + ++ 7471 * blue) >> 16; ++ ++ switch (fbi->fb.disp->visual) { ++ case FB_VISUAL_TRUECOLOR: ++ /* ++ * 12 or 16-bit True Colour. We encode the RGB value ++ * according to the RGB bitfield information. ++ */ ++ if (regno < 16) { ++ u16 *pal = fbi->fb.pseudo_palette; ++ ++ val = chan_to_field(red, &fbi->fb.var.red); ++ val |= chan_to_field(green, &fbi->fb.var.green); ++ val |= chan_to_field(blue, &fbi->fb.var.blue); ++ ++ pal[regno] = val; ++ ret = 0; ++ } ++ break; ++ ++ case FB_VISUAL_STATIC_PSEUDOCOLOR: ++ case FB_VISUAL_PSEUDOCOLOR: ++ ret = pl110fb_setpalettereg(regno, red, green, blue, trans, info); ++ break; ++ } ++ ++ return ret; ++} ++ ++/* ++ * pl110fb_display_dma_period() ++ * Calculate the minimum period (in picoseconds) between two DMA ++ * requests for the LCD controller. ++ */ ++static unsigned int ++pl110fb_display_dma_period(struct fb_var_screeninfo *var) ++{ ++ unsigned int mem_bits_per_pixel; ++ ++ mem_bits_per_pixel = var->bits_per_pixel; ++ if (mem_bits_per_pixel == 12) ++ mem_bits_per_pixel = 16; ++ ++ /* ++ * Period = pixclock * bits_per_byte * bytes_per_transfer ++ * / memory_bits_per_pixel; ++ */ ++ return var->pixclock * 8 * 16 / mem_bits_per_pixel; ++} ++ ++/* ++ * pl110fb_decode_var(): ++ * Get the video params out of 'var'. If a value doesn't fit, round it up, ++ * if it's too big, return -EINVAL. ++ * ++ * Suggestion: Round up in the following order: bits_per_pixel, xres, ++ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, ++ * bitfields, horizontal timing, vertical timing. ++ */ ++static int ++pl110fb_validate_var(struct fb_var_screeninfo *var, ++ struct pl110fb_info *fbi) ++{ ++ int ret = -EINVAL; ++ ++ if (var->xres < MIN_XRES) ++ var->xres = MIN_XRES; ++ if (var->yres < MIN_YRES) ++ var->yres = MIN_YRES; ++ if (var->xres > fbi->max_xres) ++ var->xres = fbi->max_xres; ++ if (var->yres > fbi->max_yres) ++ var->yres = fbi->max_yres; ++ var->xres_virtual = ++ var->xres_virtual < var->xres ? var->xres : var->xres_virtual; ++ var->yres_virtual = ++ var->yres_virtual < var->yres ? var->yres : var->yres_virtual; ++ ++ DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); ++ switch (var->bits_per_pixel) { ++#ifdef FBCON_HAS_CFB4 ++ case 4: ret = 0; break; ++#endif ++#ifdef FBCON_HAS_CFB8 ++ case 8: ret = 0; break; ++#endif ++#ifdef FBCON_HAS_CFB16 ++ case 16: ret = 0; break; ++#endif ++ default: ++ break; ++ } ++ ++#ifdef CONFIG_CPU_FREQ ++ printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", ++ pl110fb_display_dma_period(var), ++ cpufreq_get(smp_processor_id())); ++#endif ++ ++ return ret; ++} ++ ++ ++static void ++pl110fb_hw_set_var(struct fb_var_screeninfo *var, struct pl110fb_info *fbi) ++{ ++ u_long palette_mem_size; ++ ++ fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; ++ ++ palette_mem_size = fbi->palette_size * sizeof(u16); ++ ++ DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); ++ ++ fb_set_cmap(&fbi->fb.cmap, 1, pl110fb_setcolreg, &fbi->fb); ++ ++ pl110fb_activate_var(var, fbi); ++} ++ ++/* ++ * pl110fb_set_var(): ++ * Set the user defined part of the display for the specified console ++ */ ++static int ++pl110fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con); ++ struct display *display = get_con_display(&fbi->fb, con); ++ int err, chgvar = 0, rgbidx; ++ ++ DPRINTK("called\n"); ++ ++ /* ++ * Decode var contents into a par structure, adjusting any ++ * out of range values. ++ */ ++ err = pl110fb_validate_var(var, fbi); ++ if (err) { ++ DPRINTK( "pl110fb_validate_var returned err=%d\n", err); ++ return err; ++ } ++ ++ if (var->activate & FB_ACTIVATE_TEST) ++ return 0; ++ ++ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) ++ return -EINVAL; ++ ++ if (dvar->xres != var->xres) ++ chgvar = 1; ++ if (dvar->yres != var->yres) ++ chgvar = 1; ++ if (dvar->xres_virtual != var->xres_virtual) ++ chgvar = 1; ++ if (dvar->yres_virtual != var->yres_virtual) ++ chgvar = 1; ++ if (dvar->bits_per_pixel != var->bits_per_pixel) ++ chgvar = 1; ++ if (con < 0) ++ chgvar = 0; ++ ++ switch (var->bits_per_pixel) { ++#ifdef FBCON_HAS_CFB4 ++ case 4: ++ if (fbi->cmap_static) ++ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; ++ else ++ display->visual = FB_VISUAL_PSEUDOCOLOR; ++ display->line_length = var->xres / 2; ++ display->dispsw = &fbcon_cfb4; ++ rgbidx = RGB_8; ++ break; ++#endif ++#ifdef FBCON_HAS_CFB8 ++ case 8: ++ if (fbi->cmap_static) ++ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; ++ else ++ display->visual = FB_VISUAL_PSEUDOCOLOR; ++ display->line_length = var->xres; ++ display->dispsw = &fbcon_cfb8; ++ rgbidx = RGB_8; ++ break; ++#endif ++#ifdef FBCON_HAS_CFB16 ++ case 16: ++ display->visual = FB_VISUAL_TRUECOLOR; ++ display->line_length = var->xres * 2; ++ display->dispsw = &fbcon_cfb16; ++ display->dispsw_data = fbi->fb.pseudo_palette; ++ rgbidx = RGB_16; ++ break; ++#endif ++ default: ++ rgbidx = 0; ++ display->dispsw = &fbcon_dummy; ++ break; ++ } ++ ++ display->screen_base = fbi->screen_cpu; ++ display->next_line = display->line_length; ++ display->type = fbi->fb.fix.type; ++ display->type_aux = fbi->fb.fix.type_aux; ++ display->ypanstep = fbi->fb.fix.ypanstep; ++ display->ywrapstep = fbi->fb.fix.ywrapstep; ++ display->can_soft_blank = 1; ++ display->inverse = fbi->cmap_inverse; ++ ++ *dvar = *var; ++ dvar->activate &= ~FB_ACTIVATE_ALL; ++ ++ /* ++ * Copy the RGB parameters for this display ++ * from the machine specific parameters. ++ */ ++ dvar->red = fbi->rgb[rgbidx]->red; ++ dvar->green = fbi->rgb[rgbidx]->green; ++ dvar->blue = fbi->rgb[rgbidx]->blue; ++ dvar->transp = fbi->rgb[rgbidx]->transp; ++ ++ DPRINTK("RGBT length = %d:%d:%d:%d\n", ++ dvar->red.length, dvar->green.length, dvar->blue.length, ++ dvar->transp.length); ++ ++ DPRINTK("RGBT offset = %d:%d:%d:%d\n", ++ dvar->red.offset, dvar->green.offset, dvar->blue.offset, ++ dvar->transp.offset); ++ ++ /* ++ * Update the old var. The fbcon drivers still use this. ++ * Once they are using fbi->fb.var, this can be dropped. ++ */ ++ display->var = *dvar; ++ ++ /* ++ * If we are setting all the virtual consoles, also set the ++ * defaults used to create new consoles. ++ */ ++ if (var->activate & FB_ACTIVATE_ALL) ++ fbi->fb.disp->var = *dvar; ++ ++ /* ++ * If the console has changed and the console has defined ++ * a changevar function, call that function. ++ */ ++ if (chgvar && info && fbi->fb.changevar) ++ fbi->fb.changevar(con); ++ ++ /* If the current console is selected, activate the new var. */ ++ if (con != fbi->currcon) ++ return 0; ++ ++ pl110fb_hw_set_var(dvar, fbi); ++ ++ return 0; ++} ++ ++static int ++__do_set_cmap(struct fb_cmap *cmap, int kspc, int con, ++ struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ struct fb_cmap *dcmap = get_con_cmap(info, con); ++ int err = 0; ++ ++ if (con == -1) ++ con = fbi->currcon; ++ ++ /* no colormap allocated? (we always have "this" colour map allocated) */ ++ if (con >= 0) ++ err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0); ++ ++ if (!err && con == fbi->currcon) ++ err = fb_set_cmap(cmap, kspc, pl110fb_setcolreg, info); ++ ++ if (!err) ++ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); ++ ++ return err; ++} ++ ++static int ++pl110fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, ++ struct fb_info *info) ++{ ++ struct display *disp = get_con_display(info, con); ++ ++ if (disp->visual == FB_VISUAL_TRUECOLOR || ++ disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) ++ return -EINVAL; ++ ++ return __do_set_cmap(cmap, kspc, con, info); ++} ++ ++static int ++pl110fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) ++{ ++ struct display *display = get_con_display(info, con); ++ ++ *fix = info->fix; ++ ++ fix->line_length = display->line_length; ++ fix->visual = display->visual; ++ return 0; ++} ++ ++static int ++pl110fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) ++{ ++ *var = *get_con_var(info, con); ++ return 0; ++} ++ ++static int ++pl110fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) ++{ ++ struct fb_cmap *dcmap = get_con_cmap(info, con); ++ fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2); ++ return 0; ++} ++ ++static struct fb_ops pl110fb_ops = { ++ owner: THIS_MODULE, ++ fb_get_fix: pl110fb_get_fix, ++ fb_get_var: pl110fb_get_var, ++ fb_set_var: pl110fb_set_var, ++ fb_get_cmap: pl110fb_get_cmap, ++ fb_set_cmap: pl110fb_set_cmap, ++}; ++ ++/* ++ * pl110fb_switch(): ++ * Change to the specified console. Palette and video mode ++ * are changed to the console's stored parameters. ++ * ++ * Uh oh, this can be called from a tasklet (IRQ) ++ */ ++static int ++pl110fb_switch(int con, struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ struct display *disp; ++ struct fb_cmap *cmap; ++ ++ DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename); ++ ++ if (con == fbi->currcon) ++ return 0; ++ ++ if (fbi->currcon >= 0) { ++ disp = fb_display + fbi->currcon; ++ ++ /* ++ * Save the old colormap and video mode. ++ */ ++ disp->var = fbi->fb.var; ++ ++ if (disp->cmap.len) ++ fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0); ++ } ++ ++ fbi->currcon = con; ++ disp = fb_display + con; ++ ++ /* ++ * Make sure that our colourmap contains 256 entries. ++ */ ++ fb_alloc_cmap(&fbi->fb.cmap, 256, 0); ++ ++ if (disp->cmap.len) ++ cmap = &disp->cmap; ++ else ++ cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); ++ ++ fb_copy_cmap(cmap, &fbi->fb.cmap, 0); ++ ++ fbi->fb.var = disp->var; ++ fbi->fb.var.activate = FB_ACTIVATE_NOW; ++ ++ pl110fb_set_var(&fbi->fb.var, con, info); ++ return 0; ++} ++ ++/* ++ * Formal definition of the VESA spec: ++ * On ++ * This refers to the state of the display when it is in full operation ++ * Stand-By ++ * This defines an optional operating state of minimal power reduction with ++ * the shortest recovery time ++ * Suspend ++ * This refers to a level of power management in which substantial power ++ * reduction is achieved by the display. The display can have a longer ++ * recovery time from this state than from the Stand-by state ++ * Off ++ * This indicates that the display is consuming the lowest level of power ++ * and is non-operational. Recovery from this state may optionally require ++ * the user to manually power on the monitor ++ * ++ * Now, the fbdev driver adds an additional state, (blank), where they ++ * turn off the video (maybe by colormap tricks), but don't mess with the ++ * video itself: think of it semantically between on and Stand-By. ++ * ++ * So here's what we should do in our fbdev blank routine: ++ * ++ * VESA_NO_BLANKING (mode 0) Video on, front/back light on ++ * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off ++ * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off ++ * VESA_POWERDOWN (mode 3) Video off, front/back light off ++ * ++ * This will match the matrox implementation. ++ */ ++/* ++ * pl110fb_blank(): ++ * Blank the display by setting all palette values to zero. Note, the ++ * 12 and 16 bpp modes don't really use the palette, so this will not ++ * blank the display in all modes. ++ */ ++static void ++pl110fb_blank(int blank, struct fb_info *info) ++{ ++ struct pl110fb_info *fbi = (struct pl110fb_info *)info; ++ int i; ++ ++ DPRINTK("pl110fb_blank: blank=%d info->modename=%s\n", blank, ++ fbi->fb.modename); ++ ++ switch (blank) { ++ case VESA_POWERDOWN: ++ case VESA_VSYNC_SUSPEND: ++ case VESA_HSYNC_SUSPEND: ++ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR || ++ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) ++ for (i = 0; i < fbi->palette_size; i++) ++ pl110fb_setpalettereg(i, 0, 0, 0, 0, info); ++ pl110fb_schedule_task(fbi, C_DISABLE); ++ if (pl110fb_blank_helper) ++ pl110fb_blank_helper(blank); ++ break; ++ ++ case VESA_NO_BLANKING: ++ if (pl110fb_blank_helper) ++ pl110fb_blank_helper(blank); ++ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR || ++ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) ++ fb_set_cmap(&fbi->fb.cmap, 1, pl110fb_setcolreg, info); ++ pl110fb_schedule_task(fbi, C_ENABLE); ++ } ++} ++ ++static int ++pl110fb_updatevar(int con, struct fb_info *info) ++{ ++ DPRINTK("entered\n"); ++ return 0; ++} ++ ++/* ++ * Calculate the PCD value from the clock rate (in picoseconds). ++ * We take account of the PPCR clock setting. ++ */ ++static inline int ++get_pcd(unsigned int pixclock) ++{ ++ unsigned int pcd; ++ ++ if (pixclock) { ++ pcd = hclkfreq_get() / 100000; ++ pcd *= pixclock; ++ pcd /= 10000000; ++ pcd += 1; /* make up for integer math truncations */ ++ } else { ++ /* ++ * People seem to be missing this message. Make it big. ++ * Make it stand out. Make sure people see it. ++ */ ++ printk(KERN_WARNING "******************************************************\n"); ++ printk(KERN_WARNING "** ZERO PIXEL CLOCK DETECTED **\n"); ++ printk(KERN_WARNING "** You are using a zero pixclock. This means that **\n"); ++ printk(KERN_WARNING "** clock scaling will not be able to adjust your **\n"); ++ printk(KERN_WARNING "** your timing parameters appropriately, and the **\n"); ++ printk(KERN_WARNING "** bandwidth calculations will fail to work. This **\n"); ++ printk(KERN_WARNING "** will shortly become an error condition, which **\n"); ++ printk(KERN_WARNING "** will prevent your LCD display working. Please **\n"); ++ printk(KERN_WARNING "** send your patches in as soon as possible to shut **\n"); ++ printk(KERN_WARNING "** this message up. **\n"); ++ printk(KERN_WARNING "******************************************************\n"); ++ pcd = 0; ++ } ++ ++ DPRINTK( "pcd=%d\n", pcd); ++ ++ return pcd; ++} ++ ++/* ++ * pl110fb_activate_var(): ++ * Configures LCD Controller based on entries in var parameter. Settings are ++ * only written to the controller if changes were made. ++ */ ++static int ++pl110fb_activate_var(struct fb_var_screeninfo *var, struct pl110fb_info *fbi) ++{ ++ struct pl110fb_lcd_reg new_regs; ++ u_int half_screen_size, yres, pcd = get_pcd( var->pixclock); ++ u_long flags; ++ lcdRegs_t *LCD = (lcdRegs_t *)IO_ADDRESS(LCD_PHYS); ++ lcdicpRegs_t *LCDICP = (lcdicpRegs_t *)IO_ADDRESS(LCDICP_PHYS); ++ ++ DPRINTK("Configuring pl110 LCD\n"); ++ DPRINTK( "LCD=%p LCDICP=%p\n", LCD, LCDICP); ++ ++ DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", ++ var->xres, var->hsync_len, ++ var->left_margin, var->right_margin); ++ DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", ++ var->yres, var->vsync_len, ++ var->upper_margin, var->lower_margin); ++ ++#if DEBUG_VAR ++ if (var->xres < 16 || var->xres > 1024) ++ printk(KERN_ERR "%s: invalid xres %d\n", ++ fbi->fb.fix.id, var->xres); ++ if (var->hsync_len < 1 || var->hsync_len > 64) ++ printk(KERN_ERR "%s: invalid hsync_len %d\n", ++ fbi->fb.fix.id, var->hsync_len); ++ if (var->left_margin < 1 || var->left_margin > 255) ++ printk(KERN_ERR "%s: invalid left_margin %d\n", ++ fbi->fb.fix.id, var->left_margin); ++ if (var->right_margin < 1 || var->right_margin > 255) ++ printk(KERN_ERR "%s: invalid right_margin %d\n", ++ fbi->fb.fix.id, var->right_margin); ++ if (var->yres < 1 || var->yres > 1024) ++ printk(KERN_ERR "%s: invalid yres %d\n", ++ fbi->fb.fix.id, var->yres); ++ if (var->vsync_len < 1 || var->vsync_len > 64) ++ printk(KERN_ERR "%s: invalid vsync_len %d\n", ++ fbi->fb.fix.id, var->vsync_len); ++ if (var->upper_margin < 0 || var->upper_margin > 255) ++ printk(KERN_ERR "%s: invalid upper_margin %d\n", ++ fbi->fb.fix.id, var->upper_margin); ++ if (var->lower_margin < 0 || var->lower_margin > 255) ++ printk(KERN_ERR "%s: invalid lower_margin %d\n", ++ fbi->fb.fix.id, var->lower_margin); ++#endif ++ if( var->bits_per_pixel == 8) { ++ new_regs.LCDcontrol = LCD_CTRL_BPP8; ++ } else if( var->bits_per_pixel == 16) { ++ new_regs.LCDcontrol = LCD_CTRL_BPP16 | LCD_CTRL_BGR; ++ } ++ ++ new_regs.LCDcontrol |= fbi->LCDcontrol | LCD_CTRL_ENABLE; ++ ++ new_regs.LCDtiming0 = ++ LCD_TIMING0_HFP(var->right_margin) + ++ LCD_TIMING0_HBP(var->left_margin) + ++ LCD_TIMING0_HSW(var->hsync_len) + ++ LCD_TIMING0_PPL(var->xres); ++ ++ /* ++ * If we have a dual scan LCD, then we need to halve ++ * the YRES parameter. ++ */ ++ yres = var->yres; ++ if( fbi->LCDcontrol & LCD_CTRL_DUAL) ++ yres /= 2; ++ ++ new_regs.LCDtiming1 = ++ LCD_TIMING1_VBP(var->upper_margin) + ++ LCD_TIMING1_VFP(var->lower_margin) + ++ LCD_TIMING1_VSW(var->vsync_len) + ++ LCD_TIMING1_LPP(yres); ++ ++ new_regs.LCDtiming2 = fbi->LCDtiming2 | ++ LCD_TIMING2_CPL (480) | //(var->xres) | ++ LCD_TIMING2_PCD(pcd) | ++ (var->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : LCD_TIMING2_IHS) | ++ (var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : LCD_TIMING2_IVS); ++ ++ new_regs.LCDtiming3 = fbi->LCDtiming3; ++ new_regs.LCDICPsetup = fbi->LCDICPsetup | LCDICP_SETUP_PPL(var->xres); ++#if defined(CONFIG_ARCH_LH7A400) ++ new_regs.LCDICPsetup |= LCDICP_SETUP_POWER; ++#endif ++ ++ new_regs.LCDICPcontrol = fbi->LCDICPcontrol; ++ new_regs.LCDICPtiming1 = fbi->LCDICPtiming1; ++ new_regs.LCDICPtiming2 = fbi->LCDICPtiming2; ++ ++ DPRINTK("new LCDtiming0 = 0x%08x\n", (u32)new_regs.LCDtiming0); ++ DPRINTK("new LCDtiming1 = 0x%08x\n", (u32)new_regs.LCDtiming1); ++ DPRINTK("new LCDtiming2 = 0x%08x\n", (u32)new_regs.LCDtiming2); ++ DPRINTK("new LCDtiming3 = 0x%08x\n", (u32)new_regs.LCDtiming3); ++ DPRINTK("new LCDcontrol = 0x%08x\n", (u32)new_regs.LCDcontrol); ++ DPRINTK("new LCDICPsetup = 0x%08x\n", (u32)new_regs.LCDICPsetup); ++ DPRINTK("new LCDICPcontrol = 0x%08x\n", (u32)new_regs.LCDICPcontrol); ++ DPRINTK("new LCDICPtiming1 = 0x%08x\n", (u32)new_regs.LCDICPtiming1); ++ DPRINTK("new LCDICPtiming2 = 0x%08x\n", (u32)new_regs.LCDICPtiming2); ++ ++ ++ /* Update shadow copy atomically */ ++ local_irq_save(flags); ++ fbi->upbase = fbi->screen_dma; ++ ++ fbi->reg_LCDtiming0 = new_regs.LCDtiming0; ++ fbi->reg_LCDtiming1 = new_regs.LCDtiming1; ++ fbi->reg_LCDtiming2 = new_regs.LCDtiming2; ++ fbi->reg_LCDtiming3 = new_regs.LCDtiming3; ++ fbi->reg_LCDcontrol = new_regs.LCDcontrol; ++ fbi->reg_LCDICPsetup = new_regs.LCDICPsetup; ++ fbi->reg_LCDICPcontrol = new_regs.LCDICPcontrol; ++ fbi->reg_LCDICPtiming1 = new_regs.LCDICPtiming1; ++ fbi->reg_LCDICPtiming2 = new_regs.LCDICPtiming2; ++ local_irq_restore(flags); ++ ++ /* ++ * Only update the registers if the controller is enabled ++ * and something has changed. ++ */ ++ if ((LCD->timing0 != fbi->reg_LCDtiming0) || (LCD->timing1 != fbi->reg_LCDtiming1) || ++ (LCD->timing2 != fbi->reg_LCDtiming2) || (LCD->timing3 != fbi->reg_LCDtiming2) || ++ (LCD->control != fbi->reg_LCDcontrol) || (LCDICP->setup != fbi->reg_LCDICPsetup) || ++ (LCDICP->timing1 != fbi->reg_LCDICPtiming1) || (LCDICP->timing2 != fbi->reg_LCDICPtiming2) || ++ (LCD->upbase != fbi->upbase) || (LCD->lpbase != fbi->lpbase)) ++ pl110fb_schedule_task(fbi, C_REENABLE); ++ ++ return 0; ++} ++ ++/* ++ * NOTE! The following functions are purely helpers for set_ctrlr_state. ++ * Do not call them directly; set_ctrlr_state does the correct serialisation ++ * to ensure that things happen in the right way 100% of time time. ++ * -- rmk ++ */ ++ ++static void ++pl110fb_backlight_on(struct pl110fb_info *fbi) ++{ ++ DPRINTK("backlight on\n"); ++ ++#ifdef CONFIG_ARCH_LH79520 ++ if( machine_is_lh79520evb()) { ++ //cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ GPOUT16 |= BACKLIGHT; ++ ++ //cpld->lcd_pwr_cntl |= CPLD_BACKLIGHT_ON; ++ } ++#endif ++ ++#ifdef CONFIG_ARCH_LH7A400 ++ if( machine_is_lh7a400evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl |= CPLD_BACKLIGHT_ON; ++ } ++#endif ++} ++ ++static void ++pl110fb_backlight_off(struct pl110fb_info *fbi) ++{ ++ DPRINTK("backlight off\n"); ++ ++#ifdef CONFIG_ARCH_LH79520 ++ if( machine_is_lh79520evb()) { ++ //cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ GPOUT16 &= ~BACKLIGHT; ++ //cpld->lcd_pwr_cntl &= ~CPLD_BACKLIGHT_ON; ++ } ++#endif ++#ifdef CONFIG_ARCH_LH7A400 ++ if( machine_is_lh7a400evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl &= ~CPLD_BACKLIGHT_ON; ++ } ++#endif ++} ++ ++static void ++pl110fb_power_up_lcd(struct pl110fb_info *fbi) ++{ ++ DPRINTK("LCD power on\n"); ++ ++#ifdef CONFIG_ARCH_LH79520 ++ if( machine_is_lh79520evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl |= CPLD_LCDP_EN; ++ } ++#endif ++#ifdef CONFIG_ARCH_LH7A400 ++ if( machine_is_lh7a400evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl |= CPLD_LCDP_EN; ++ } ++#endif ++} ++ ++static void ++pl110fb_power_down_lcd(struct pl110fb_info *fbi) ++{ ++ DPRINTK("LCD power off\n"); ++#ifdef CONFIG_ARCH_LH79520 ++ if( machine_is_lh79520evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl &= ~CPLD_LCDP_EN; ++ } ++#endif ++#ifdef CONFIG_ARCH_LH7A400 ++ if( machine_is_lh7a400evb()) { ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ ++ cpld->lcd_pwr_cntl &= ~CPLD_LCDP_EN; ++ } ++#endif ++} ++ ++ ++static void ++pl110fb_setup_hw(struct pl110fb_info *fbi) ++{ ++#ifdef CONFIG_ARCH_LH79520 ++ rcpcRegs_t *rcpc = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ ioconRegs_t *iocon = (ioconRegs_t *)IO_ADDRESS( IOCON_PHYS); ++ ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; /* unlock RCPC registers */ ++ barrier(); ++ ++ /* ++ * use HCLK for the LCD clock. ++ */ ++ rcpc->spareClkCtrl &= ~RCPC_SPARE_CLKCTRL_LCDCLK_DISABLE; /* enable LCDCLK */ ++ rcpc->spareClkSel &= ~RCPC_SCLKSEL_LCDCLK; /* LCDCLK from HCLK */ ++ rcpc->spare0Prescale &= 0; ++ rcpc->AHBClkCtrl &= ~RCPC_CLKCTRL_DMAC_DISABLE; /* ensure DMA gets a clock */ ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; /* lock RCPC registers */ ++ ++ /* set the pin mux to enable all required LCD signals and disable the rest */ ++ ++ iocon->LCDMux = ++ LCDMUX_CLVDDEN ++// | LCDMUX_CLXCLK ++// | LCDMUX_CLSPL /* SPL */ ++// | LCDMUX_CLS /* CLS */ ++ | LCDMUX_PIOC2 /* don't need external LCD clock */ ++ | LCDMUX_CLCP /* DCLK */ ++ | LCDMUX_CLLP /* LP */ ++ | LCDMUX_CLD17 ++ | LCDMUX_CLD16 ++ | LCDMUX_CLD15 ++ | LCDMUX_CLD14 ++ | LCDMUX_CLD13 ++ | LCDMUX_CLD12 ++ | LCDMUX_CLFP ++ | LCDMUX_CLD11 ++ | LCDMUX_CLD10 ++ | LCDMUX_CLD8 ++ | LCDMUX_CLD9 ++ | LCDMUX_CLD2 /* red[1] */ ++ | LCDMUX_CLD3 /* red[2] */ ++ | LCDMUX_CLD4 /* red[3] */ ++ | LCDMUX_CLD5 /* red[4] */ ++ | LCDMUX_CLD7 /* green[0] */ ++ | LCDMUX_CLD6; /* green[1] */ ++ ++// iocon->LCDMux = LCDMUX_CLREV ++// | LCDMUX_CLXCLK ++// | LCDMUX_CLD13 /* blue[0] */ ++// | LCDMUX_CLD14 /* blue[1] */ ++// | LCDMUX_CLD15 /* blue[2] */ ++// | LCDMUX_CLD16 /* blue[3] */ ++// | LCDMUX_CLD17 /* blue[4] */ ++// | LCDMUX_CLSPL /* SPL */ ++// | LCDMUX_CLS /* CLS */ ++// | LCDMUX_PIOC2 /* don't need external LCD clock */ ++// | LCDMUX_CLCP /* DCLK */ ++// | LCDMUX_CLP /* LP */ ++// | LCDMUX_CLSPS /* SPS */ ++// | LCDMUX_CLD2 /* red[1] */ ++// | LCDMUX_CLD3 /* red[2] */ ++// | LCDMUX_CLD4 /* red[3] */ ++// | LCDMUX_CLD5 /* red[4] */ ++// | LCDMUX_CPS /* PS */ ++// | LCDMUX_CLD7 /* green[0] */ ++// | LCDMUX_CLD8 /* green[1] */ ++// | LCDMUX_CLD9 /* green[2] */ ++// | LCDMUX_CLD10 /* green[3] */ ++// | LCDMUX_CLD11; /* green[4] */ ++ ++ DPRINTK( "IOCON->LCDMux=%x\n", iocon->LCDMux); ++#endif ++#ifdef CONFIG_ARCH_LH7A400 ++ gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); ++ ++ gpio->pinmux |= (GPIO_PINMUX_PEOCON | GPIO_PINMUX_PDOCON); /* route LCD data bits */ ++ ++ DPRINTK( "gpio: pinmux=%x pdddr=0x%x peddr=0x%x\n", ++ gpio->pinmux, gpio->pdddr, gpio->peddr); // DDD ++#endif ++} ++ ++static void ++pl110fb_enable_controller(struct pl110fb_info *fbi) ++{ ++ lcdRegs_t *LCD = (lcdRegs_t *)IO_ADDRESS(LCD_PHYS); ++ lcdicpRegs_t *LCDICP = (lcdicpRegs_t *)IO_ADDRESS(LCDICP_PHYS); ++ ++#if defined(CONFIG_ARCH_LH79520) || defined(CONFIG_ARCH_LH7A400) ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++#endif ++ DPRINTK("Enabling LCD controller\n"); ++ ++ LCDICP->control = fbi->reg_LCDICPcontrol; ++ LCDICP->setup = fbi->reg_LCDICPsetup; ++ LCDICP->timing1 = fbi->reg_LCDICPtiming1; ++ LCDICP->timing2 = fbi->reg_LCDICPtiming2; ++ LCD->timing0 = fbi->reg_LCDtiming0; ++ LCD->timing1 = fbi->reg_LCDtiming1; ++ LCD->timing2 = fbi->reg_LCDtiming2; ++ LCD->timing3 = fbi->reg_LCDtiming3; ++ LCD->upbase = fbi->upbase; ++#if defined(CONFIG_ARCH_LH7A400) ++ LCD->lpoverflow = fbi->upbase; ++#endif ++ LCD->intrEnable = 0; ++ LCD->control = fbi->reg_LCDcontrol; ++ ++ /* ++ * enable lcd output ++ */ ++#if defined(CONFIG_ARCH_LH79520) || defined(CONFIG_ARCH_LH7A400) ++ cpld->lcd_pwr_cntl |= CPLD_LCD_OE; ++#endif ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(20 * HZ / 1000); ++ ++ LCD->control |= LCD_CTRL_PWR; ++ ++ ++#if defined(CONFIG_ARCH_LH7A400) ++ DPRINTK("real LCDoverflow = %p\n", (void *)LCD->lpoverflow); ++#endif ++ DPRINTK("real LCDupbase = %p\n", (void *)LCD->upbase); ++ DPRINTK("real LCDlpbase = %p\n", (void *)LCD->lpbase); ++ DPRINTK("real LCDtiming0 = 0x%08x\n", LCD->timing0); ++ DPRINTK("real LCDtiming1 = 0x%08x\n", LCD->timing1); ++ DPRINTK("real LCDtiming2 = 0x%08x\n", LCD->timing2); ++ DPRINTK("real LCDtiming3 = 0x%08x\n", LCD->timing3); ++ DPRINTK("real LCDcontrol = 0x%08x\n", LCD->control); ++ DPRINTK("real LCDICPsetup = 0x%08x\n", LCDICP->setup); ++ DPRINTK("real LCDICPcontrol = 0x%08x\n", LCDICP->control); ++ DPRINTK("real LCDICPtiming1 = 0x%08x\n", LCDICP->timing1); ++ DPRINTK("real LCDICPtiming2 = 0x%08x\n", LCDICP->timing2); ++} ++ ++ ++static void ++pl110fb_disable_controller(struct pl110fb_info *fbi) ++{ ++ lcdRegs_t *LCD = (lcdRegs_t *)IO_ADDRESS(LCD_PHYS); ++ lcdicpRegs_t *LCDICP = (lcdicpRegs_t *)IO_ADDRESS(LCDICP_PHYS); ++ ++#if defined(CONFIG_ARCH_LH79520) || defined(CONFIG_ARCH_LH7A400) ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++#endif ++ ++ DECLARE_WAITQUEUE(wait, current); ++ ++ DPRINTK("Disabling LCD controller\n"); ++ ++ add_wait_queue(&fbi->ctrlr_wait, &wait); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ ++ LCD->intrEnable |= LCD_STATUS_VCOMP; /* allow VCOMP interrupts */ ++ ++ /* turn off LCD power, wait a bit, then disable the controller */ ++ LCD->control &= ~LCD_CTRL_PWR; ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(20 * HZ / 1000); ++ ++ LCD->control = 0; ++ LCDICP->control = 0; ++ ++#if defined(CONFIG_ARCH_LH79520) || defined(CONFIG_ARCH_LH7A400) ++ cpld->lcd_pwr_cntl &= ~CPLD_LCD_OE; ++#endif ++ ++ schedule_timeout(20 * HZ / 1000); ++ current->state = TASK_RUNNING; ++ remove_wait_queue(&fbi->ctrlr_wait, &wait); ++} ++ ++ ++/* ++ * pl110fb_handle_irq: Handle 'LCD DONE' interrupts. ++ */ ++static void ++pl110fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct pl110fb_info *fbi = dev_id; ++ lcdRegs_t *LCD = (lcdRegs_t *)IO_ADDRESS(LCD_PHYS); ++ ++ unsigned int intr = LCD->maskedIntrStatus; ++ ++ DPRINTK("IRQ: status=0x%x\n", intr); ++ ++ if( intr & LCD_STATUS_VCOMP) { /* vertical compare interrupt */ ++ LCD->intrEnable = 0; /* only want one interrupt */ ++ wake_up(&fbi->ctrlr_wait); ++ } ++ ++ LCD->rawIntrStatus = 0; /* clear interrupt */ ++} ++ ++/* ++ * This function must be called from task context only, since it will ++ * sleep when disabling the LCD controller, or if we get two contending ++ * processes trying to alter state. ++ */ ++static void ++set_ctrlr_state(struct pl110fb_info *fbi, u_int state) ++{ ++ u_int old_state; ++ ++ down(&fbi->ctrlr_sem); ++ ++ old_state = fbi->state; ++ ++ switch (state) { ++ case C_DISABLE_CLKCHANGE: ++ /* ++ * Disable controller for clock change. If the ++ * controller is already disabled, then do nothing. ++ */ ++ if (old_state != C_DISABLE && old_state != C_DISABLE_PM) { ++ fbi->state = state; ++ pl110fb_disable_controller(fbi); ++ } ++ break; ++ ++ case C_DISABLE_PM: ++ case C_DISABLE: ++ /* ++ * Disable controller ++ */ ++ if (old_state != C_DISABLE) { ++ fbi->state = state; ++ ++ pl110fb_backlight_off(fbi); ++ if (old_state != C_DISABLE_CLKCHANGE) ++ pl110fb_disable_controller(fbi); ++ pl110fb_power_down_lcd(fbi); ++ } ++ break; ++ ++ case C_ENABLE_CLKCHANGE: ++ /* ++ * Enable the controller after clock change. Only ++ * do this if we were disabled for the clock change. ++ */ ++ if (old_state == C_DISABLE_CLKCHANGE) { ++ fbi->state = C_ENABLE; ++ pl110fb_enable_controller(fbi); ++ } ++ break; ++ ++ case C_REENABLE: ++ /* ++ * Re-enable the controller only if it was already ++ * enabled. This is so we reprogram the control ++ * registers. ++ */ ++ if (old_state == C_ENABLE) { ++ pl110fb_disable_controller(fbi); ++ pl110fb_setup_hw(fbi); ++ pl110fb_enable_controller(fbi); ++ } ++ break; ++ ++ case C_ENABLE_PM: ++ /* ++ * Re-enable the controller after PM. This is not ++ * perfect - think about the case where we were doing ++ * a clock change, and we suspended half-way through. ++ */ ++ if (old_state != C_DISABLE_PM) ++ break; ++ /* fall through */ ++ ++ case C_ENABLE: ++ /* ++ * Power up the LCD screen, enable controller, and ++ * turn on the backlight. ++ */ ++ if (old_state != C_ENABLE) { ++ fbi->state = C_ENABLE; ++ pl110fb_setup_hw(fbi); ++ pl110fb_power_up_lcd(fbi); ++ pl110fb_enable_controller(fbi); ++ pl110fb_backlight_on(fbi); ++ } ++ break; ++ } ++ up(&fbi->ctrlr_sem); ++} ++ ++ ++/* ++ * Our LCD controller task (which is called when we blank or unblank) ++ * via keventd. ++ */ ++static void ++pl110fb_task(void *dummy) ++{ ++ struct pl110fb_info *fbi = dummy; ++ u_int state = xchg(&fbi->task_state, -1); ++ ++ set_ctrlr_state(fbi, state); ++} ++ ++#ifdef CONFIG_CPU_FREQ ++/* ++ * Calculate the minimum DMA period over all displays that we own. ++ * This, together with the SDRAM bandwidth defines the slowest CPU ++ * frequency that can be selected. ++ */ ++static unsigned int ++pl110fb_min_dma_period(struct pl110fb_info *fbi) ++{ ++ unsigned int min_period = (unsigned int)-1; ++ int i; ++ ++ for (i = 0; i < MAX_NR_CONSOLES; i++) { ++ unsigned int period; ++ ++ /* ++ * Do we own this display? ++ */ ++ if (fb_display[i].fb_info != &fbi->fb) ++ continue; ++ ++ /* ++ * Ok, calculate its DMA period ++ */ ++ period = pl110fb_display_dma_period(get_con_var(&fbi->fb, i)); ++ if (period < min_period) ++ min_period = period; ++ } ++ ++ return min_period; ++} ++ ++/* ++ * CPU clock speed change handler. We need to adjust the LCD timing ++ * parameters when the CPU clock is adjusted by the power management ++ * subsystem. ++ */ ++static int ++pl110fb_clkchg_notifier(struct notifier_block *nb, unsigned long val, ++ void *data) ++{ ++ struct pl110fb_info *fbi = TO_INF(nb, clockchg); ++ struct cpufreq_minmax *mm = data; ++ u_int pcd; ++ ++ switch (val) { ++ case CPUFREQ_MINMAX: ++ printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, " ++ "new clock %d kHz\n", pl110fb_min_dma_period(fbi), ++ mm->cur_freq, mm->new_freq); ++ /* todo: fill in min/max values */ ++ break; ++ ++ case CPUFREQ_PRECHANGE: ++ set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); ++ break; ++ ++ case CPUFREQ_POSTCHANGE: ++ pcd = get_pcd(fbi->fb.var.pixclock); ++ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); // DDD ++ set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); ++ break; ++ } ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_PM ++/* ++ * Power management hook. Note that we won't be called from IRQ context, ++ * unlike the blank functions above, so we may sleep. ++ */ ++static int ++pl110fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ++{ ++ struct pl110fb_info *fbi = pm_dev->data; ++ ++ DPRINTK("pm_callback: %d\n", req); ++ ++ if (req == PM_SUSPEND || req == PM_RESUME) { ++ int state = (int)data; ++ ++ if (state == 0) { ++ /* Enter D0. */ ++ set_ctrlr_state(fbi, C_ENABLE_PM); ++ } else { ++ /* Enter D1-D3. Disable the LCD controller. */ ++ set_ctrlr_state(fbi, C_DISABLE_PM); ++ } ++ } ++ DPRINTK("done\n"); ++ return 0; ++} ++#endif ++ ++/* ++ * pl110fb_map_video_memory(): ++ * Allocates the DRAM memory for the frame buffer. This buffer is ++ * remapped into a non-cached, non-buffered, memory region to ++ * allow palette and pixel writes to occur without flushing the ++ * cache. Once this area is remapped, all virtual memory ++ * access to the video memory should occur at the new region. ++ */ ++static int __init ++pl110fb_map_video_memory(struct pl110fb_info *fbi) ++{ ++ /* ++ * We reserve one page for the palette, plus the size ++ * of the framebuffer. ++ */ ++ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len); ++ fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size, ++ &fbi->map_dma); ++ ++ if (fbi->map_cpu) { ++ fbi->screen_cpu = fbi->map_cpu; ++ fbi->screen_dma = fbi->map_dma; ++ fbi->fb.fix.smem_start = fbi->screen_dma; ++ } ++ ++ DPRINTK( "fix.smem_len = %d map_cpu = 0x%x screen_cpu = 0x%x screen_dma = 0x%x\n", ++ fbi->fb.fix.smem_len, fbi->map_cpu, fbi->screen_cpu, fbi->screen_dma); ++ ++ return fbi->map_cpu ? 0 : -ENOMEM; ++} ++ ++/* Fake monspecs to fill in fbinfo structure */ ++static struct fb_monspecs monspecs __initdata = { ++ 30000, 70000, 50, 65, 0 /* Generic */ ++}; ++ ++ ++static struct pl110fb_info * __init ++pl110fb_init_fbinfo(void) ++{ ++ struct pl110fb_mach_info *inf; ++ struct pl110fb_info *fbi; ++ int pixelsPerSecond; ++ ++ fbi = kmalloc(sizeof(struct pl110fb_info) + sizeof(struct display) + ++ sizeof(u16) * 16, GFP_KERNEL); ++ if (!fbi) ++ return NULL; ++ ++ memset(fbi, 0, sizeof(struct pl110fb_info) + sizeof(struct display)); ++ ++ fbi->currcon = -1; ++ ++ strcpy(fbi->fb.fix.id, PL110_NAME); ++ ++ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; ++ fbi->fb.fix.type_aux = 0; ++ fbi->fb.fix.xpanstep = 0; ++ fbi->fb.fix.ypanstep = 0; ++ fbi->fb.fix.ywrapstep = 0; ++ fbi->fb.fix.accel = FB_ACCEL_NONE; ++ ++ fbi->fb.var.nonstd = 0; ++ fbi->fb.var.activate = FB_ACTIVATE_NOW; ++ fbi->fb.var.height = -1; ++ fbi->fb.var.width = -1; ++ fbi->fb.var.accel_flags = 0; ++ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; ++ ++ strcpy(fbi->fb.modename, PL110_NAME); ++ strcpy(fbi->fb.fontname, "Acorn8x8"); ++ ++ fbi->fb.fbops = &pl110fb_ops; ++ fbi->fb.changevar = NULL; ++ fbi->fb.switch_con = pl110fb_switch; ++ fbi->fb.updatevar = pl110fb_updatevar; ++ fbi->fb.blank = pl110fb_blank; ++ fbi->fb.flags = FBINFO_FLAG_DEFAULT; ++ fbi->fb.node = -1; ++ fbi->fb.monspecs = monspecs; ++ fbi->fb.disp = (struct display *)(fbi + 1); ++ fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1); ++ ++ fbi->rgb[RGB_8] = &rgb_8; ++ fbi->rgb[RGB_16] = &def_rgb_16; ++ ++ inf = pl110fb_get_machine_info(fbi); ++ ++ /* ++ * Calculate pixclock. pixclock is the time in picoseconds spent ++ * drawing a pixel. The time (in seconds) to draw a pixel is ++ * the inverse of how many pixels we draw in a second (pixelsPerSecond). ++ * ++ * pixelsPerSecond is xres*yres*refresh, plus all the overhead time ++ * (horizontal and vertical front and back porches, plus horizontal ++ * and vertical sync lengths). ++ * ++ * ++ */ ++ pixelsPerSecond = ++ (inf->xres + inf->hsync_len + inf->left_margin + inf->right_margin) * ++ (inf->yres + inf->vsync_len + inf->upper_margin + inf->lower_margin) * ++ VERTICAL_REFRESH; ++ ++ inf->pixclock = 1000000000 / (pixelsPerSecond / 1000); ++ ++ DPRINTK( "pixelsPerSecond=%d pixclock=%d\n", pixelsPerSecond, inf->pixclock); ++ ++ ++ fbi->max_xres = inf->xres; ++ fbi->fb.var.xres = inf->xres; ++ fbi->fb.var.xres_virtual = inf->xres; ++ fbi->max_yres = inf->yres; ++ fbi->fb.var.yres = inf->yres; ++ fbi->fb.var.yres_virtual = inf->yres; ++ fbi->max_bpp = inf->bpp; ++ fbi->fb.var.bits_per_pixel = inf->bpp; ++ fbi->fb.var.pixclock = inf->pixclock; ++ fbi->fb.var.hsync_len = inf->hsync_len; ++ fbi->fb.var.left_margin = inf->left_margin; ++ fbi->fb.var.right_margin = inf->right_margin; ++ fbi->fb.var.vsync_len = inf->vsync_len; ++ fbi->fb.var.upper_margin = inf->upper_margin; ++ fbi->fb.var.lower_margin = inf->lower_margin; ++ fbi->fb.var.sync = inf->sync; ++ fbi->fb.var.grayscale = inf->cmap_greyscale; ++ fbi->cmap_inverse = inf->cmap_inverse; ++ fbi->cmap_static = inf->cmap_static; ++ fbi->LCDtiming2 = inf->LCDtiming2; ++ fbi->LCDtiming3 = inf->LCDtiming3; ++ fbi->LCDcontrol = inf->LCDcontrol; ++ fbi->LCDICPsetup = inf->LCDICPsetup; ++ fbi->LCDICPcontrol = inf->LCDICPcontrol; ++ fbi->LCDICPtiming1 = inf->LCDICPtiming1; ++ fbi->LCDICPtiming2 = inf->LCDICPtiming2; ++ fbi->state = C_DISABLE; ++ fbi->task_state = (u_char)-1; ++ fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * ++ fbi->max_bpp / 8; ++ ++ init_waitqueue_head(&fbi->ctrlr_wait); ++ INIT_TQUEUE(&fbi->task, pl110fb_task, fbi); ++ init_MUTEX(&fbi->ctrlr_sem); ++ ++ return fbi; ++} ++ ++int __init ++pl110fb_init(void) ++{ ++ struct pl110fb_info *fbi; ++ int ret; ++ ++ DPRINTK( "\n\npl110fb_init\n"); ++ ++ DPRINTK( "cpu clock = %d HCLK = %d\n", cpufreq_get(0), hclkfreq_get()); ++ ++ fbi = pl110fb_init_fbinfo(); ++ ret = -ENOMEM; ++ if (!fbi) ++ goto failed; ++ ++ /* Initialize video memory */ ++ ret = pl110fb_map_video_memory(fbi); ++ if (ret) ++ goto failed; ++ ++ ret = request_irq(IRQ_LCD, pl110fb_handle_irq, SA_INTERRUPT, ++ fbi->fb.fix.id, fbi); ++ if (ret) { ++ printk(KERN_ERR "pl110fb: request_irq failed: ret=%d\n", ret); ++ goto failed; ++ } ++ ++ pl110fb_set_var(&fbi->fb.var, -1, &fbi->fb); ++ ++ ret = register_framebuffer(&fbi->fb); ++ if (ret < 0) ++ goto failed; ++ ++#ifdef CONFIG_PM ++ /* ++ * Note that the console registers this as well, but we want to ++ * power down the display prior to sleeping. ++ */ ++ fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, pl110fb_pm_callback); ++ if (fbi->pm) ++ fbi->pm->data = fbi; ++#endif ++#ifdef CONFIG_CPU_FREQ ++ fbi->clockchg.notifier_call = pl110fb_clkchg_notifier; ++ cpufreq_register_notifier(&fbi->clockchg); ++#endif ++ ++ /* ++ * Ok, now enable the LCD controller ++ */ ++ set_ctrlr_state(fbi, C_ENABLE); ++ ++ /* This driver cannot be unloaded at the moment */ ++ MOD_INC_USE_COUNT; ++ ++ return 0; ++ ++failed: ++ if (fbi) ++ kfree(fbi); ++ return ret; ++} ++ ++int __init ++pl110fb_setup(char *options) ++{ ++ return 0; ++} ++ ++MODULE_DESCRIPTION("ARM PL110 framebuffer driver"); ++MODULE_LICENSE("GPL"); ++ +diff -urN linux-2.4.26/drivers/video/pl110fb.h linux-2.4.26-vrs1-lnode80/drivers/video/pl110fb.h +--- linux-2.4.26/drivers/video/pl110fb.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/drivers/video/pl110fb.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,350 @@ ++/* ++ * linux/drivers/video/pl110fb.h ++ * -- ARM PrimeCell PL110 LCD controller frame buffer device ++ * ++ * Copyright (C) 2002 Lineo, Inc. ++ * ++ * Portions Copyright (C) 2001 Sharp Microelectronics of the Americas, Inc. ++ * CAMAS, WA ++ * ++ * based in part on sa1100fb.h, which is Copyright (C) Eric A. Thomas ++ * ++ * 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. ++ */ ++ ++/* ++ * Color LCD Controller registers ++ */ ++typedef struct { ++ volatile u32 timing0; /* Horizontal axis panel control */ ++ volatile u32 timing1; /* Vertical axis panel control */ ++ volatile u32 timing2; /* clock and signal polarity control */ ++ volatile u32 timing3; /* line end control */ ++ volatile dma_addr_t upbase; /* upper panel frame base address */ ++ volatile dma_addr_t lpbase; /* lower panel frame base address */ ++ volatile u32 intrEnable; /* interrupt enable mask */ ++ volatile u32 control; /* LCD panel pixel parameters */ ++ volatile u32 rawIntrStatus; /* raw interrupt status */ ++ volatile u32 maskedIntrStatus; /* masked interrupt status */ ++ volatile dma_addr_t upcurr; /* upper panel current address */ ++ volatile dma_addr_t lpcurr; /* lower panel current address */ ++ volatile dma_addr_t lpoverflow; /* SDRAM fb base */ ++ volatile u32 reservedcc[115]; /* reserved */ ++ volatile u32 palette[128]; /* 256 x 16-bit color palette */ ++} lcdRegs_t; ++ ++ ++/* ++ * LCDTiming0 Register Bit Field constants ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than zero. ++ */ ++#define LCD_TIMING0_HBP(n) _SBF(24,((n)-1)) /* Horiz Back Porch */ ++#define LCD_TIMING0_HFP(n) _SBF(16,((n)-1)) /* Horiz Front Porch */ ++#define LCD_TIMING0_HSW(n) _SBF(8,((n)-1)) /* Horiz sync Pulse Width */ ++#define LCD_TIMING0_PPL(n) _SBF(2,((((n)/16)-1)&0x3F)) /* Pixels per line */ ++ ++/* ++ * LCDTiming1 Register Bit Field constants ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than zero. ++ */ ++#define LCD_TIMING1_VBP(n) _SBF(24,(n)) /* Vertical Back Porch */ ++#define LCD_TIMING1_VFP(n) _SBF(16,(n)) /* Vertical Front Porch */ ++#define LCD_TIMING1_VSW(n) _SBF(10,(n)) /* Vertical Synchronization Pulse */ ++#define LCD_TIMING1_LPP(n) _SBF(0,((n)-1)) /* Lines per Panel */ ++ ++/* ++ * LCDTiming2 Register Bit Field constants ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than two. ++ */ ++#define LCD_TIMING2_BCD _BIT(26) /* Bypass Pixel Clock Divider */ ++#define LCD_TIMING2_CPL(n) _SBF(16,((n)-1)&0x3FF) /* Clocks Per Line */ ++#define LCD_TIMING2_IOE _BIT(14) /* Invert Output Enable */ ++#define LCD_TIMING2_IPC _BIT(13) /* Invert Panel Clock */ ++#define LCD_TIMING2_IHS _BIT(12) /* Invert Horizontal Synchronization */ ++ /* set == HSYNC is active low */ ++#define LCD_TIMING2_IVS _BIT(11) /* Invert Vertical Synchronization */ ++ /* set == VSYNC is active low */ ++#define LCD_TIMING2_ACB(n) _SBF(6,((n)-1)) /* AC Bias Pin Frequency */ ++#define LCD_TIMING2_CLKSEL _BIT(5) /* Clock Selector */ ++#define LCD_TIMING2_PCD(n) _SBF(0,((n)-2)) /* Panel Clock Divisor */ ++ ++ ++/* ++ * LCDTiming3 Register Bit Field constants ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than one. ++ */ ++#define LCD_TIMING3_LEE _BIT(16) /* Line End Enable */ ++#define LCD_TIMING3_LED(n) _SBF(0,((n)-1)) /* Line End Signal Delay */ ++ ++ ++/* ++ * intrEnable, rawIntrStatus, maskedIntrStatus bit field positions ++ */ ++#define LCD_STATUS_MBERROR _BIT(4) /* Master Bus Error */ ++#define LCD_STATUS_VCOMP _BIT(3) /* Vertical Compare */ ++#define LCD_STATUS_LNBU _BIT(2) /* LCD Next addr. Base Update*/ ++#define LCD_STATUS_FUF _BIT(1) /* FIFO underflow */ ++ ++ ++/* ++ * Control Register Bit Field constants ++ */ ++#define LCD_CTRL_WATERMARK _BIT(16) /* LCD DMA FIFO Watermark Level */ ++#define LCD_CTRL_LDMAFIFOTME _BIT(15) /* LCD DMA FIFO Test Mode Enable */ ++ ++#define LCD_CTRL_VCOMP(n) _SBF(12,((n)&0x3)) /* Generate interrupt at: */ ++#define LCD_CTRL_VCOMP_SVS _SBF(12,0) /* start of vertical sync */ ++#define LCD_CTRL_VCOMP_SBP _SBF(12,1) /* start of back porch */ ++#define LCD_CTRL_VCOMP_SAV _SBF(12,2) /* start of active video */ ++#define LCD_CTRL_VCOMP_SFP _SBF(12,3) /* start of front porch */ ++ ++#define LCD_CTRL_PWR _BIT(11) /* LCD Power Enable */ ++#define LCD_CTRL_BEPO _BIT(10) /* Big Endian Pixel Order */ ++#define LCD_CTRL_BEBO _BIT(9) /* Big Endian Byte Order */ ++#define LCD_CTRL_BGR _BIT(8) /* Swap Red and Blue (RGB to BGR) */ ++#define LCD_CTRL_DUAL _BIT(7) /* Dual Panel STN */ ++#define LCD_CTRL_MON8 _BIT(6) /* Monochrome LCD has 8-bit interface */ ++#define LCD_CTRL_TFT _BIT(5) /* TFT LCD */ ++ ++#define LCD_CTRL_BW_COLOR _SBF(4,0) /* STN LCD is Color */ ++#define LCD_CTRL_BW_MONO _SBF(4,1) /* STN LCD is Monochrome */ ++ ++#define LCD_CTRL_BPP1 _SBF(1,0) /* Bits per pixel */ ++#define LCD_CTRL_BPP2 _SBF(1,1) ++#define LCD_CTRL_BPP4 _SBF(1,2) ++#define LCD_CTRL_BPP8 _SBF(1,3) ++#define LCD_CTRL_BPP16 _SBF(1,4) ++#define LCD_CTRL_BPP24 _SBF(1,5) ++ ++#define LCD_CTRL_ENABLE _BIT(0) /* LCD Controller Enable */ ++ ++ ++ ++typedef struct { ++ volatile u32 setup; /* Setup */ ++ volatile u32 control; /* Control */ ++ volatile u32 timing1; /* HR-TFT Timing 1 */ ++ volatile u32 timing2; /* HR-TFT Timing 2 */ ++} lcdicpRegs_t; ++ ++ ++ ++/* ++ * LCDICP Setup Register Bit Fields ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than zero. ++ */ ++#define LCDICP_SETUP_MODE_BYPASS _SBF(0,0) ++#define LCDICP_SETUP_MODE_HRTFT _SBF(0,1) ++#define LCDICP_SETUP_MODE_DMTN _SBF(0,2) ++#define LCDICP_SETUP_HORIZ_REVERSE _SBF(2,0) ++#define LCDICP_SETUP_HORIZ_NORMAL _SBF(2,1) ++#define LCDICP_SETUP_VERT_REVERSE _SBF(3,0) ++#define LCDICP_SETUP_VERT_NORMAL _SBF(3,1) ++/* Calculates bit field value from actual pixels per line */ ++#define LCDICP_SETUP_PPL(n) _SBF(4,((n)-1)) ++#define LCDICP_SETUP_POWER _BIT(13) /* lh7a400 only */ ++ ++ ++/* ++ * LCDICP Control Register Bit Fields ++ */ ++#define LCDICP_CONTROL_SPSEN _BIT(0) ++#define LCDICP_CONTROL_CLSEN _BIT(1) ++#define LCDICP_CONTROL_UBLEN _BIT(2) ++#define LCDICP_CONTROL_DISP _BIT(3) ++#define LCDICP_CONTROL_EN0 _BIT(4) ++#define LCDICP_CONTROL_EN1 _BIT(5) ++#define LCDICP_CONTROL_EN2 _BIT(6) ++#define LCDICP_CONTROL_EN3 _BIT(7) ++ ++ ++/* ++ * LCDICP Timing 1 Register Bit Fields ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than zero. ++ */ ++#define LCDICP_TIMING1_LPDEL(n) _SBF(0,((n)-1)&0xF) ++#define LCDICP_TIMING1_REVDEL(n) _SBF(4,((n)-1)&0xF) ++#define LCDICP_TIMING1_PSDEL(n) _SBF(8,((n)-1)&0xF) ++#define LCDICP_TIMING1_CLSDEL(n) _SBF(8,((n)-1)&0xF) ++ ++ ++/* ++ * LCDICP Timing 2 Register Bit Fields ++ * ++ * NOTE: Ensure the argument to the following macros is greater ++ * than zero. ++ */ ++#define LCDICP_TIMING2_PSDEL2(n) _SBF(0,((n)-1)&0x1FF) ++#define LCDICP_TIMING2_CLSDEL2(n) _SBF(0,((n)-1)&0x1FF) ++#define LCDICP_TIMING2_SPLVALUE(n) _SBF(9,((n)-1)&0x7F) ++ ++ ++/* ++ * These are the bitfields for each ++ * display depth that we support. ++ */ ++struct pl110fb_rgb { ++ struct fb_bitfield red; ++ struct fb_bitfield green; ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; ++}; ++ ++/* ++ * This structure describes the machine which we are running on. ++ */ ++struct pl110fb_mach_info { ++ u_long pixclock; ++ ++ u_short xres; ++ u_short yres; ++ ++ u_char bpp; ++ u_char hsync_len; /* horiz sync pulse width */ ++ u_char left_margin; /* horiz back porch */ ++ u_char right_margin; /* horiz front porch */ ++ ++ u_char vsync_len; /* vertical sync pulse width */ ++ u_char upper_margin; /* vertical back porch */ ++ u_char lower_margin; /* vertical front porch */ ++ u_char sync; ++ ++ u_int cmap_greyscale:1, ++ cmap_inverse:1, ++ cmap_static:1, ++ unused:29; ++ ++ u_long LCDtiming2; ++ u_long LCDtiming3; ++ u_long LCDcontrol; ++ u_long LCDICPsetup; ++ u_long LCDICPcontrol; ++ u_long LCDICPtiming1; ++ u_long LCDICPtiming2; ++}; ++ ++ ++/* Shadows for LCD/LCDICP controller registers */ ++struct pl110fb_lcd_reg { ++ u_long LCDtiming0; ++ u_long LCDtiming1; ++ u_long LCDtiming2; ++ u_long LCDtiming3; ++ u_long LCDcontrol; ++ u_long LCDICPsetup; ++ u_long LCDICPcontrol; ++ u_long LCDICPtiming1; ++ u_long LCDICPtiming2; ++}; ++ ++#define RGB_8 (0) ++#define RGB_16 (1) ++#define NR_RGB 2 ++ ++struct pl110fb_info { ++ struct fb_info fb; ++ signed int currcon; ++ ++ struct pl110fb_rgb *rgb[NR_RGB]; ++ ++ u_int max_bpp; ++ u_int max_xres; ++ u_int max_yres; ++ ++ /* ++ * These are the addresses we mapped ++ * the framebuffer memory region to. ++ */ ++ dma_addr_t map_dma; ++ u_char * map_cpu; ++ u_int map_size; ++ ++ u_char * screen_cpu; ++ dma_addr_t screen_dma; ++ u_int palette_size; ++ ++ dma_addr_t upbase; ++ dma_addr_t lpbase; ++ ++ u_long LCDtiming2; ++ u_long LCDtiming3; ++ u_long LCDcontrol; ++ u_long LCDICPsetup; ++ u_long LCDICPcontrol; ++ u_long LCDICPtiming1; ++ u_long LCDICPtiming2; ++ ++ u_int cmap_inverse:1, ++ cmap_static:1, ++ unused:30; ++ ++ u_long reg_LCDtiming0; ++ u_long reg_LCDtiming1; ++ u_long reg_LCDtiming2; ++ u_long reg_LCDtiming3; ++ u_long reg_LCDcontrol; ++ u_long reg_LCDICPsetup; ++ u_long reg_LCDICPcontrol; ++ u_long reg_LCDICPtiming1; ++ u_long reg_LCDICPtiming2; ++ ++ volatile u_char state; ++ volatile u_char task_state; ++ struct semaphore ctrlr_sem; ++ wait_queue_head_t ctrlr_wait; ++ struct tq_struct task; ++ ++#ifdef CONFIG_PM ++ struct pm_dev *pm; ++#endif ++#ifdef CONFIG_CPU_FREQ ++ struct notifier_block clockchg; ++#endif ++}; ++ ++#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member))) ++ ++#define TO_INF(ptr,member) __type_entry(ptr,struct pl110fb_info,member) ++ ++/* ++ * These are the actions for set_ctrlr_state ++ */ ++#define C_DISABLE (0) ++#define C_ENABLE (1) ++#define C_DISABLE_CLKCHANGE (2) ++#define C_ENABLE_CLKCHANGE (3) ++#define C_REENABLE (4) ++#define C_DISABLE_PM (5) ++#define C_ENABLE_PM (6) ++ ++#define PL110_NAME "PL110" ++ ++/* ++ * Debug macros ++ */ ++#if DEBUG ++# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) ++#else ++# define DPRINTK(fmt, args...) ++#endif ++ ++/* ++ * Minimum X and Y resolutions ++ */ ++#define MIN_XRES 64 ++#define MIN_YRES 64 ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/ads_784x.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ads_784x.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/ads_784x.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ads_784x.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,25 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++/* ++* linux/include/asm-arm/arch-lh79520/ads_784x.h ++* ++* Copyright (C) 2002 Lineo, Inc. ++* ++* Provide ADS_784x (touchscreen) types & definitions for LH7x EVB boards ++* ++*/ ++ ++#ifndef _ADS_784X_h ++#define _ADS_784X_h ++ ++#include <asm-arm/arch-lh79520/ssp_lh7x.h> ++ ++/********************************************************************* ++* Global Function Declarations ++*********************************************************************/ ++extern int ads_784x_register(sspContext_t *sspContext); ++extern int ads_784x_deregister(void); ++ ++ ++#endif /* _ADS_784X_h */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/cpld.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/cpld.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/cpld.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/cpld.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,138 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/cpld.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _LH79520_CPLD_H ++#define _LH79520_CPLD_H ++ ++typedef __attribute((packed)) struct { ++ volatile u16 keys_status; ++ volatile u16 reserved1; ++ volatile u16 l3_reg; ++ volatile u16 reserved2; ++ volatile u16 lcd_pwr_cntl; ++ volatile u16 reserved3; ++ volatile u16 l3_mode; ++ volatile u16 reserved4; ++ volatile u16 gpi; ++ volatile u16 reserved5; ++ volatile u16 gpo; ++ volatile u16 reserved6; ++ volatile u16 adc_dac_left; ++ volatile u16 adc_dac_right; ++ volatile u16 audio_control; ++ volatile u16 reserved7; ++ volatile u16 display_dip_sw; ++ volatile u16 reserved8; ++ volatile u16 seven_seg; ++ volatile u16 reserved9; ++ volatile u16 misc_stat; ++ volatile u16 reserved10; ++ volatile u16 gpio_data_dir; ++ volatile u16 reserved11; ++ volatile u16 ssp_dev_sel; ++ volatile u16 reserved12; ++ volatile u16 ser_port1_rts; ++ volatile u16 reserved13; ++ volatile u16 cf_reset; ++ volatile u16 reserved14; ++ volatile u16 cpu_dip_sw; ++ volatile u16 reserved15; ++ volatile u16 intr_mask; ++ volatile u16 reserved16; ++ volatile u16 reserved17; ++ volatile u16 reserved18; ++ volatile u16 reserved19; ++ volatile u16 reserved20; ++ volatile u16 reserved21; ++ volatile u16 reserved22; ++ volatile u16 nio_reg_clk; ++ volatile u16 reserved23; ++} cpldRegs_t; ++ ++ ++/* LCD power bits */ ++#define CPLD_EN26V _BIT(0) /* turn on the 26V supply */ ++#define CPLD_BACKLIGHT_ON _BIT(1) /* turn on the backlight */ ++#define CPLD_DISP_EN _BIT(2) /* note DISP_EN is not wired on the Sharp EVB display board */ ++#define CPLD_LCD_OE _BIT(3) /* enable the LCD drive signals */ ++#define CPLD_LCD_PWR _BIT(4) ++ ++/* ++ * enable the LCD 3.3V or 5V power supply; ++ * does not effect HR-TFT power on the Sharp EVB display board. ++ */ ++#define CPLD_LCDP_EN _BIT(4) ++ ++ ++/* intr_mask bits */ ++#define CPLD_TS_INTR_ENABLE _BIT(7) /* Enable touch screen IRQ */ ++#define CPLD_CTS_INTR_ENABLE _BIT(6) ++#define CPLD_RI_INTR_ENABLE _BIT(5) ++ ++/* misc_status bits */ ++#define CPLD_MISCSTS_TS_IRQ _BIT(4) /* Touch Screen caused IRQ */ ++#define CPLD_MISCSTS_TS_BUSY _BIT(5) /* Touch Screen busy */ ++ ++/* L3 mode bits */ ++#if 0 // DDD ++#define CPLD_L3_MODE_HI (cpld->l3_mode |= _BIT(0)) ++#define CPLD_L3_MODE_LOW (cpld->l3_mode |= ~(_BIT(0))) ++#else ++#define CPLD_L3_MODE_HI cpld->l3_mode = _BIT(0) ; barrier() ++#define CPLD_L3_MODE_LOW cpld->l3_mode = 0; barrier() ++#endif ++ ++/* I2S audio control register bits */ ++#define CPLD_DAC_USE_REQ1 _BIT(12) ++#define CPLD_ADC_DMA_ENABLE _BIT(7) ++#define CPLD_DAC_DMA_ENABLE _BIT(6) ++#define CPLD_ADC_DMA_AUTO _BIT(5) ++#define CPLD_DAC_DMA_AUTO _BIT(4) ++#define CPLD_ADC_IRQ_ENABLE _BIT(3) ++#define CPLD_DAC_IRQ_ENABLE _BIT(2) ++#define CPLD_ADC_IRQ_STATUS _BIT(1) ++#define CPLD_DAC_IRQ_STATUS _BIT(0) ++#define CPLD_AUDIO_DAC_INT_PENDING _BIT(0) ++#define CPLD_AUDIO_ADC_INT_PENDING _BIT(1) ++#define CPLD_AUDIO_DAC_INT_ENALBED _BIT(2) ++#define CPLD_AUDIO_ADC_INT_ENABLED _BIT(3) ++#define CPLD_AUDIO_DAC_INT_MASK \ ++ (CPLD_AUDIO_DAC_INT_PENDING | CPLD_AUDIO_DAC_INT_ENALBED) ++#define CPLD_AUDIO_ADC_INT_MASK \ ++ (CPLD_AUDIO_ADC_INT_PENDING | CPLD_AUDIO_ADC_INT_ENABLED) ++ ++#define CPLD_ALL_ADC_BITS (CPLD_ADC_IRQ_STATUS | \ ++ CPLD_ADC_IRQ_ENABLE | \ ++ CPLD_ADC_DMA_AUTO | \ ++ CPLD_ADC_DMA_ENABLE) ++ ++#define CPLD_ALL_DAC_BITS (CPLD_DAC_IRQ_STATUS | \ ++ CPLD_DAC_IRQ_ENABLE | \ ++ CPLD_DAC_DMA_AUTO | \ ++ CPLD_DAC_DMA_ENABLE | \ ++ CPLD_DAC_USE_REQ1) ++ ++#define CPLD_ALL_AUDIO_BITS (CPLD_ALL_DAC_BITS | CPLD_ALL_DAC_BITS) ++ ++#define CPLD_FS_BIT_FIELD 8 ++#define CPLD_FS_BITS _SBF(CPLD_FS_BIT_FIELD, _BITMASK(4) ); ++#define CPLD_FS_8000 0 ++#define CPLD_FS_11025 1 ++#define CPLD_FS_12000 2 ++#define CPLD_FS_16000 3 ++#define CPLD_FS_22050 4 ++#define CPLD_FS_24000 5 ++#define CPLD_FS_32000 6 ++#define CPLD_FS_44100 7 ++#define CPLD_FS_48000 8 ++ ++#endif // _LH79520_CPLD_H ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/dma.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/dma.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/dma.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/dma.h 2005-11-02 17:42:49.000000000 -0400 +@@ -0,0 +1,63 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/dma.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_DMA_H ++#define __ASM_ARCH_DMA_H ++ ++#include <asm/hardware.h> ++#include <asm/arch/cpld.h> ++ ++#define MAX_DMA_ADDRESS 0xfffc0000 ++ ++#define MAX_DMA_CHANNELS 0 ++#define LH79520_DMA_CHANNELS 4 ++ ++/* ++ * All possible LH79520 devices a DMA channel can be attached to. ++ */ ++/* FIXME */ ++ ++typedef enum { ++ DMA_SSP_Rx, ++ DMA_SSP_Tx, ++ DMA_Audio_Out, ++ DMA_Audio_In ++} dma_device_t; ++ ++ ++typedef void (*dma_callback_t)( void *buf_id, int size ); ++ ++ ++/* LH79520 DMA API */ ++extern int lh79520_request_dma( dmach_t *channel, const char *device_id, ++ dma_device_t device ); ++extern int lh79520_dma_set_callback( dmach_t channel, dma_callback_t cb ); ++extern int lh79520_dma_set_spin( dmach_t channel, dma_addr_t addr, int size ); ++extern int lh79520_dma_queue_buffer( dmach_t channel, void *buf_id, ++ dma_addr_t data, int size ); ++extern int lh79520_dma_get_current( dmach_t channel, void **buf_id, dma_addr_t *addr ); ++extern int lh79520_dma_stop( dmach_t channel ); ++extern int lh79520_dma_resume( dmach_t channel ); ++extern int lh79520_dma_flush_all( dmach_t channel ); ++extern void lh79520_free_dma( dmach_t channel ); ++extern int lh79520_dma_sleep( dmach_t channel ); ++extern int lh79520_dma_wakeup( dmach_t channel ); ++ ++#endif /* _ASM_ARCH_DMA_H */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/gpio.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/gpio.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/gpio.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/gpio.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,139 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/gpio.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Original Author: BarnettH ++ * Date: May 17 2001 17:47:58 ++ * ++ * Project: ARM IP headers ++ * ++ * Description: ++ * This file contains the structure definitions and manifest ++ * constants for ARM IP component: ++ * General Purpose Input/Output PrimeCell PL060 ++ * ++ * Each GPIO Module has two GPIO (digital IO) ports which are ++ * designated PORTA and PORTB. ++ * ++ * Multiple instances of a GPIO module, and thus port pairs, ++ * may be implemented in a single SOC. ++ * ++ * Each port has eight bits, PORTx[7:0]. ++ * ++ * Each port has two 8-bit registers associated with it: ++ * GPIOPxDR - Data register (dr) ++ * GPIOPxDDR - Data Direction register (ddr) ++ * ++ * The specific SOC will have its own unique name for the port. ++ * Each port pair will have its own unique base address for the ++ * port pair. ++ * ++ * This include file is designed to permit the definition of ++ * pointers in the SOC map include file to distinct 8-bit ports ++ * using the name designation is suitable for the SOC ++ * implementation. ++ * ++ * Example: ++ * A map file that includes this file should specify a ++ * base address for each GPIO module, e.g.: ++ * ++ * #define GPIO0_BASE (0xFFFDF000) ++ * #define GPIO1_BASE (0xFFFDE000) ++ * * ++ * * ++ * * ++ * ++ * The SOC map file will use these base addresses to define ++ * pointers to GPIO port A, B, C, D, E, ... thusly: ++ * ++ * #define GPIOPA ((volatile GPIOAREGS *)(GPIO0_BASE)) ++ * #define GPIOPB ((volatile GPIOBREGS *)(GPIO0_BASE)) ++ * #define GPIOPC ((volatile GPIOAREGS *)(GPIO1_BASE)) ++ * #define GPIOPD ((volatile GPIOBREGS *)(GPIO1_BASE)) ++ * #define GPIOPE ((volatile GPIOAREGS *)(GPIO2_BASE)) ++ * * ++ * * ++ * * ++ * ++ * Example usage of these definitions in user code for Port C: ++ * ++ * unsigned int data; ++ * ++ * GPIOC->ddr = 0xF; sets bits [7:4] as outputs ++ * and bits [3:0] as inputs ++ * GPIOC->dr = 0xF0; sets bits [7:4] to "1" ++ * ++ * data = GPIOC->dr; sets data to the value of ++ * data register ++ * ++ * Note: If it is desired to use the type qualifier "__packed" ++ * to enable packing of structures, the manifest constant ++ * "PACKED" must be defined as follows or as a ++ * predefine at compilation (ARM-specific notation): ++ * ++ * #define PACKED __packed ++ * ++ * If a different compiler/preprocessor is used, the appropriate ++ * notation must be substituted for "__packed". ++ * ++ * Reference: ARM PrimeCell General Purpose Input/Output (PL060) ++ * Technical Reference Manual, ARM DDI 0142B. ++ * ++ * Revision History: ++ * ++ * Rev 1.1 May 17 2001 17:47:58 BarnettH ++ * Changed structure component types to reflect 32-bit access requirements. ++ * ++ * Rev 1.0 Mar 30 2001 16:03:30 BarnettH ++ * Initial revision. ++ * ++ * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC. ++ * CAMAS, WA ++ *********************************************************************/ ++ ++#ifndef ARM_GPIO_PL060_H ++#define ARM_GPIO_PL060_H ++ ++/* GPIO Register Structures */ ++//typedef __attribute((packed)) struct { ++typedef struct { ++ volatile unsigned int dr; ++ volatile unsigned int reserveda1; ++ volatile unsigned int ddr; ++ volatile unsigned int reserveda2; ++} gpioARegs_t; ++ ++//typedef __attribute((packed)) struct { ++typedef struct { ++ volatile unsigned int reservedb1; ++ volatile unsigned int dr; ++ volatile unsigned int reservedb2; ++ volatile unsigned int ddr; ++} gpioBRegs_t; ++ ++/* ++ * The names and usage of the bit fields in these registers is ++ * implementation specific, so few bit field constants are defined. ++ */ ++ ++#ifndef _BIT ++#define _BIT(n) (1 << (n)) ++#endif ++ ++#ifndef _SBF ++#define _SBF(f,v) ((v) << (f)) ++#endif ++ ++#define SSPFRM_GPIO_BIT _BIT(2) ++#define SSPEN_GPIO_BIT _BIT(0) ++ ++#define GPIOPAREGS gpioARegs_t ++#define GPIOPBREGS gpioBRegs_t ++ ++#endif /* ARM_GPIO_PL060_H */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/hardware.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/hardware.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/hardware.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/hardware.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,341 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/hardware.h ++ * ++ * Copyright (C) 2001 Sharp Microelectronics of the Americas, Inc. ++ * CAMAS, WA ++ * Portions 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * References: ++ * (1) Sharp LH79520 Universal Microcontroller User's Guide, ++ * Version 1.x, Sharp Microelectronics of the Americas, Inc. ++ * ++ */ ++ ++#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 ++ ++/* Hardware addresses of major areas. ++ * *_START is the physical address ++ * *_SIZE is the size of the region ++ * *_BASE is the virtual address ++ */ ++ ++/* ++ * we can do an identity mapping (V=P) of all of I/O ++ * space, except for the VIC. ++ * ++ * One of the places you can find the VIC is at 0xffff0000, ++ * which is the same place the interrupt vectors want to live, ++ * so we'll leave a hole there, and use the VIC at it's other ++ * address: 0xfffff000. ++ */ ++ ++#define APB_START 0xfffc0000 /* Physical address of APB I/O space */ ++#define APB_BASE 0xfffc0000 /* Virtual address of APB I/O space */ ++#define APB_SIZE 0x00026000 /* its size (up to 0xfffe6000) */ ++ ++#define AHB_START 0xffff1000 /* Physical address of AHB I/O space */ ++#define AHB_BASE 0xffff1000 /* Virtual address of AHB I/O space */ ++#define AHB_SIZE 0x00004000 /* its size (up to 0xffff5000) */ ++ ++#define VIC_START VIC_PHYS /* Physical address of VIC */ ++#define VIC_BASE 0xfffff000 /* Virtual address of VIC */ ++#define VIC_SIZE 0x1000 /* its size */ ++ ++ ++ ++#define FLASH_START 0x40000000 /* Flash on SMC bank 0 */ ++#define FLASH_BASE 0xf4000000 ++#define FLASH_SIZE (4 * 1024 * 1024) ++ ++#define EXT_SRAM_START 0x44000000 /* External SRAM on SMC bank 1 */ ++#define EXT_SRAM_BASE 0xf4400000 ++#define EXT_SRAM_SIZE (2 * 1024 * 1024) ++ ++ ++// not used, but there is still code that breaks without it ++#define CPLD_START 0x48000000 /* CPLD on SMC bank 2 */ ++#define CPLD_BASE 0xf4800000 ++#define CPLD_SIZE 4096 ++ ++#define CS8900_START 0x48000000 /* Ethernet on SMC bank 2 */ ++#define CS8900_BASE 0xf4800000 ++#define CS8900_SIZE 4096 ++ ++#define GPOUT16_START 0x4c000000 /* latch on bank 3 */ ++#define GPOUT16_BASE 0xf4c00000 ++#define GPOUT16_SIZE 4096 ++ ++ ++#define IDE_START 0x50000000 /* CF/IDE on SMC bank 4 */ ++#define IDE_BASE 0xf5000000 ++#define IDE_SIZE 4096 ++ ++#define IDE2_START 0x54000000 /* CF/IDE on SMC bank 5 */ ++#define IDE2_BASE 0xf5400000 ++#define IDE2_SIZE 4096 ++ ++#define UNUSED_START 0x58000000 /* unused on SMC bank 6 */ ++#define RESERVED_START 0x5C000000 /* reserved on SMC bank 7 */ ++ ++#define INT_SRAM_START 0x60000000 /* on-chip SRAM */ ++#define INT_SRAM_BASE 0xf6000000 ++#define INT_SRAM_SIZE (32 * 1024) ++ ++ ++#define IO_START APB_START ++#define IO_BASE APB_BASE ++ ++/* macro to get at IO space when running virtually */ ++#define IO_ADDRESS(phys) (phys) ++ ++#define PCIO_BASE IO_BASE ++ ++ ++/********************************************************************** ++ * AHB BASES ++ *********************************************************************/ ++#define AHB_PHYS (0xFFFF0000) ++#define VIC_PHYS_MIRROR (AHB_PHYS + 0x0000) ++#define SMC_REGS_PHYS (AHB_PHYS + 0x1000) ++#define SDRAM_REGS_PHYS (AHB_PHYS + 0x2000) ++#define LCD_PHYS (AHB_PHYS + 0x4000) ++#define VIC_PHYS (AHB_PHYS + 0xF000) ++ ++/********************************************************************** ++ * APB PHYSS ++ *********************************************************************/ ++#define APB_PHYS (0xFFFC0000) ++#define UART0_PHYS (APB_PHYS + 0x00000) ++#define UART1_PHYS (APB_PHYS + 0x01000) ++#define UART2_PHYS (APB_PHYS + 0x02000) ++#define PWM_PHYS (APB_PHYS + 0x03000) ++#define TIMER0_PHYS (APB_PHYS + 0x04000) ++#define TIMER1_PHYS (APB_PHYS + 0x05000) ++#define SSP_PHYS (APB_PHYS + 0x06000) ++#define GPIO3_PHYS (APB_PHYS + 0x1C000) ++#define GPIO2_PHYS (APB_PHYS + 0x1D000) ++#define GPIO1_PHYS (APB_PHYS + 0x1E000) ++#define GPIO0_PHYS (APB_PHYS + 0x1F000) ++#define RTC_PHYS (APB_PHYS + 0x20000) ++#define DMAC_PHYS (APB_PHYS + 0x21000) ++#define RCPC_PHYS (APB_PHYS + 0x22000) ++#define WDTIMER_PHYS (APB_PHYS + 0x23000) ++#define LCDICP_PHYS (APB_PHYS + 0x24000) ++#define IOCON_PHYS (APB_PHYS + 0x25000) ++ ++/********************************************************************** ++ * REMAPping ++ *********************************************************************/ ++#define SDRAM_MEM_PHYS (0x20000000) ++#define SMC_MEM_PHYS (0x40000000) ++#define INTERNAL_MEM_PHYS (0x60000000) ++ ++// DDD #if REMAP == 0 ++#define SMC_MIRROR_MEM_PHYS (0x00000000) ++// DDD #elif REMAP == 1 ++// DDD #define SDRAM_MIRROR_MEM_PHYS (0x00000000) ++// DDD #elif REMAP == 2 ++// DDD #define INTERNAL_MIRROR_MEM_PHYS (0x00000000) ++// DDD #else ++// DDD #error REMAP must be defined as 0, 1, or 2 ++// DDD #endif ++ ++/********************************************************************** ++ * xSPR bits ++ *********************************************************************/ ++#define CORE_IRQ _BIT(7) ++#define CORE_FIQ _BIT(6) ++ ++/********************************************************************** ++ * SMC Memory Bank Address Space Bases ++ *********************************************************************/ ++ ++#define SMC_BANK0_PHYS (SMC_MEM_PHYS + 0x00000000) ++#define SMC_BANK1_PHYS (SMC_MEM_PHYS + 0x04000000) ++#define SMC_BANK2_PHYS (SMC_MEM_PHYS + 0x08000000) ++#define SMC_BANK3_PHYS (SMC_MEM_PHYS + 0x0C000000) ++#define SMC_BANK4_PHYS (SMC_MEM_PHYS + 0x10000000) ++#define SMC_BANK5_PHYS (SMC_MEM_PHYS + 0x14000000) ++#define SMC_BANK6_PHYS (SMC_MEM_PHYS + 0x18000000) ++#define SMC_BANK7_PHYS (SMC_MEM_PHYS + 0x1C000000) ++ ++/********************************************************************** ++ * SDRAMC Memory Bank Address Space Bases ++ *********************************************************************/ ++ ++#define SDRAM_BANK0_PHYS (SDRAM_MEM_PHYS + 0x00000000) ++#define SDRAM_BANK1_PHYS (SDRAM_MEM_PHYS + 0x08000000) ++ ++/********************************************************************** ++ * Vectored Interrupt Controller (VIC) ++ *********************************************************************/ ++#define VICID_OFFSET (0xFE0) ++// DDD #define VIC ((VICREGS *)(VIC_PHYS)) ++// DDD #define VICID ((VICIDREGS *)(VIC_PHYS + VICID_OFFSET)) ++#define VIC_INT_TYPE_IRQ 0 ++#define VIC_INT_TYPE_FIQ 1 ++ ++/* VIC Interrupt Sources */ ++#define VIC_EXTINT0 0 ++#define VIC_EXTINT1 1 ++#define VIC_EXTINT2 2 ++#define VIC_EXTINT3 3 ++#define VIC_EXTINT4 4 ++#define VIC_EXTINT5 5 ++#define VIC_EXTINT6 6 ++#define VIC_EXTINT7 7 ++#define VIC_SPEXTINT0 8 ++#define VIC_SPEXTINT1 9 ++#define VIC_SPEXTINT2 10 ++#define VIC_SPEXTINT3 11 ++#define VIC_CLCDC 12 ++#define VIC_SSPTXINTR 13 ++#define VIC_SSPRXINTR 14 ++#define VIC_SSPRORINTR 15 ++#define VIC_SSPINTR 16 ++#define VIC_TIMER0 17 ++#define VIC_TIMER1 18 ++#define VIC_TIMER2 19 ++#define VIC_TIMER3 20 ++#define VIC_UART0_RX 21 ++#define VIC_UART0_TX 22 ++#define VIC_UART0 23 ++#define VIC_UART1 24 ++#define VIC_UART2 25 ++#define VIC_DMA0 26 ++#define VIC_DMA1 27 ++#define VIC_DMA2 28 ++#define VIC_DMA3 29 ++#define VIC_RTC 30 ++#define VIC_WDT 31 ++ ++/* VIC Vectors */ ++#define VIC_VECT_0 0 ++#define VIC_VECT_1 1 ++#define VIC_VECT_2 2 ++#define VIC_VECT_3 3 ++#define VIC_VECT_4 4 ++#define VIC_VECT_5 5 ++#define VIC_VECT_6 6 ++#define VIC_VECT_7 7 ++#define VIC_VECT_8 8 ++#define VIC_VECT_9 9 ++#define VIC_VECT_10 10 ++#define VIC_VECT_11 11 ++#define VIC_VECT_12 12 ++#define VIC_VECT_13 13 ++#define VIC_VECT_14 14 ++#define VIC_VECT_15 15 ++#define VIC_VECT_MAX VIC_VECT_15 ++#define VIC_VECT_DEFAULT ~(0) ++ ++ ++#define XTAL_IN 14745600 /* 14.7456 MHz crystal */ ++#define PLL_CLOCK (XTAL_IN * 21) /* 309 MHz PLL clock */ ++ ++ ++ ++/********************************************************************** ++ * UART'S ++ *********************************************************************/ ++#define UARTID_OFFSET (0xFE0) ++// DDD #define UART0 ((UARTREGS *)(UART0_PHYS)) ++// DDD #define UART1 ((UARTREGS *)(UART1_PHYS)) ++// DDD #define UART2 ((UARTREGS *)(UART2_PHYS)) ++// DDD #define UART0ID ((UARTIDREGS *)(UART0_PHYS + UARTID_OFFSET)) ++// DDD #define UART1ID ((UARTIDREGS *)(UART1_PHYS + UARTID_OFFSET)) ++// DDD #define UART2ID ((UARTIDREGS *)(UART2_PHYS + UARTID_OFFSET)) ++ ++/********************************************************************** ++ * IRDA ++ *********************************************************************/ ++// DDD #define IRDA0 ((UARTREGS *)(UART0_PHYS)) ++// DDD #define IRDA1 ((UARTREGS *)(UART1_PHYS)) ++// DDD #define IRDA2 ((UARTREGS *)(UART2_PHYS)) ++ ++/********************************************************************** ++ * Pulse Width Modulator (PWM) ++ *********************************************************************/ ++// DDD #define PWMX_OFFSET (0x20) ++// DDD #define PWM ((PWMREGS *)(PWM_PHYS)) ++// DDD #define PWM0 ((PWMXREGS *)(PWM_PHYS)) ++// DDD #define PWM1 ((PWMXREGS *)(PWM_PHYS + PWMX_OFFSET)) ++ ++/********************************************************************** ++ * TIMER ++ *********************************************************************/ ++// DDD #define TIMER2_OFFSET (0x20) ++// DDD #define TIMER0 ((TIMERREG *)(TIMER0_PHYS)) ++// DDD #define TIMER1 ((volatile TIMERREG *)(TIMER0_PHYS + TIMER2_OFFSET)) ++// DDD #define TIMER2 ((TIMERREG *)(TIMER1_PHYS)) ++// DDD #define TIMER3 ((TIMERREG *)(TIMER1_PHYS + TIMER2_OFFSET)) ++ ++/********************************************************************** ++ * Synchronous Serial Port (SSP) ++ *********************************************************************/ ++// DDD #define SSP ((SSPREGS *)(SSP_PHYS)) ++ ++/********************************************************************** ++ * General Purpose Input/Output (GPIO) ++ *********************************************************************/ ++#define GPIOA ((GPIOPAREGS *)(GPIO0_PHYS)) ++#define GPIOB ((GPIOPBREGS *)(GPIO0_PHYS)) ++#define GPIOC ((GPIOPAREGS *)(GPIO1_PHYS)) ++#define GPIOD ((GPIOPBREGS *)(GPIO1_PHYS)) ++#define GPIOE ((GPIOPAREGS *)(GPIO2_PHYS)) ++#define GPIOF ((GPIOPBREGS *)(GPIO2_PHYS)) ++#define GPIOG ((GPIOPAREGS *)(GPIO3_PHYS)) ++#define GPIOH ((GPIOPBREGS *)(GPIO3_PHYS)) ++ ++/********************************************************************** ++ * Real Time Clock (RTC) ++ *********************************************************************/ ++// DDD #define RTC ((RTCREGS *)(RTC_PHYS)) ++ ++/********************************************************************** ++ * DMA Controller (DMAC) ++ *********************************************************************/ ++// DDD #define DMAC ((DMACREGS *)(DMAC_PHYS)) ++ ++/********************************************************************** ++ * Reset, Clock, and Power Controller (RCPC) ++ *********************************************************************/ ++// DDD #define RCPC ((RCPCREGS *)(RCPC_PHYS)) ++ ++/********************************************************************** ++ * Watchdog Timer (WDTIMER) ++ *********************************************************************/ ++// DDD #define WDTIMER ((WDTIMERREGS *)(WDTIMER_PHYS)) ++ ++/********************************************************************** ++ * LCD Interface Control Processor (LCDICP) ++ *********************************************************************/ ++// DDD #define LCDICP ((LCDICPREGS *)(LCDICP_PHYS)) ++ ++/********************************************************************** ++ * IOCON ++ *********************************************************************/ ++// DDD #define IOCON ((IOCONREGS *)(IOCON_PHYS)) ++ ++/********************************************************************** ++ * GPOUT16 (MARMALADE) ++ *********************************************************************/ ++#define nLED _BIT(8) ++#define TS_DIN _BIT(9) ++#define nTS_CS _BIT(10) ++#define TS_DCLK _BIT(11) ++#define BACKLIGHT _BIT(15) +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/ide.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ide.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/ide.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ide.h 2005-11-02 17:48:27.000000000 -0400 +@@ -0,0 +1,58 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/ide.h ++ * ++ * Copyright 2002 Lineo, Inc. ++ * ++ * 17-Jan-2002: Initial clone of arch-anakin/ide.h ++ */ ++ ++#include <linux/config.h> ++#include <asm/irq.h> ++#include <asm/hardware.h> ++ ++/* ++ * Set up a hw structure for a specified data port, control port and IRQ. ++ * This should follow whatever the default interface uses. ++ */ ++static __inline__ void ++ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq) ++{ ++ ide_ioreg_t reg; ++ int i; ++ int regincr = 4; ++ ++ memset(hw, 0, sizeof(*hw)); ++ ++ reg = (ide_ioreg_t)data_port; ++ ++ for( i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { ++ hw->io_ports[i] = reg; ++ reg += regincr; ++ } ++ ++ hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port; ++ ++ if (irq) ++ *irq = 0; ++} ++ ++ ++/* ++ * This registers the standard ports for this architecture with the IDE ++ * driver. ++ */ ++static __inline__ void ++ide_init_default_hwifs(void) ++{ ++ hw_regs_t hw; ++ ++ /* ++ * The IDE data ports are mapped in at IDE_BASE, and are aligined on 32 bit boundaries ++ * The IDE control port (usually found at port 0x3f6 on a PC, e.g.) is 6 ints into IDE_BASE2. ++ */ ++ ide_init_hwif_ports( &hw, IDE_BASE, (char *)IDE2_BASE + 6*sizeof(int), NULL); ++ hw.irq = IRQ_CF; ++ ide_register_hw( &hw, NULL); ++} ++ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/iocon.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/iocon.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/iocon.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/iocon.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,210 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/iocon.h ++ * ++ * Copyright (C) 2002 Lineo, Inc. ++ * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC. ++ * CAMAS, WA ++ * ++ * 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 ++ * ++ * Description: ++ * This file contains the structure definitions and manifest ++ * constants for ARM IP component: ++ * I/O Configuration Block ++ * ++ * References: ++ * (1) Sharp LH79520 Universal Microcontroller User's Guide, ++ * Version 1.x, Sharp Microelectronics of the Americas, Inc. ++ * (2) ARM Isis Technical Reference Manual, System on Chip Group, ++ * ARM SC063-TRM-0001-B ++ * ++ *********************************************************************/ ++ ++#ifndef LH79520_IOCON_H ++#define LH79520_IOCON_H ++ ++#if 0 ++#ifndef _BIT ++#define _BIT(n) (1 << (n)) ++#endif ++ ++#ifndef _SBF ++#define _SBF(f,v) ((v) << (f)) ++#endif ++#endif // 0 ++ ++/* ++ * IO Configuration Block Structure ++ */ ++typedef struct { ++ volatile unsigned int MemMux; ++ volatile unsigned int LCDMux; ++ volatile unsigned int MiscMux; ++ volatile unsigned int DMAMux; ++ volatile unsigned int UARTMux; ++ volatile unsigned int SSIMux; ++ volatile unsigned int Scratchreg; ++} ioconRegs_t; ++ ++/* ++ * Memory Multiplexing IOCON Register Bit Field constants ++ */ ++#define MEMMUX_PIOE_NOMUX _SBF(0,0) ++#define MEMMUX_MIDQM32 _SBF(0,1) ++#define MEMMUX_MIDQM30 _SBF(0,3) ++#define MEMMUX_PIOE4 _SBF(2,0) ++#define MEMMUX_MINWE _SBF(2,1) ++#define MEMMUX_PIOE5 _SBF(3,0) ++#define MEMMUX_MISDNCS0 _SBF(3,1) ++#define MEMMUX_PIOE6 _SBF(4,0) ++#define MEMMUX_MISDNCS1 _SBF(4,1) ++#define MEMMUX_PIOE7 _SBF(5,0) ++#define MEMMUX_MICKE _SBF(5,1) ++#define MEMMUX_PIOF0 _SBF(6,0) ++#define MEMMUX_MICLKIO _SBF(6,1) ++#define MEMMUX_PIO_X _SBF(7,0) ++#define MEMMUX_MIDATA_X _SBF(7,1) ++#define MEMMUX_PIOH2 _SBF(8,0) ++#define MEMMUX_MICSN3 _SBF(8,1) ++#define MEMMUX_PIOH3 _SBF(9,0) ++#define MEMMUX_MICSN4 _SBF(9,1) ++#define MEMMUX_PIOH4 _SBF(10,0) ++#define MEMMUX_MICSN5 _SBF(10,1) ++#define MEMMUX_PIOH5 _SBF(11,0) ++#define MEMMUX_MICSN6 _SBF(11,1) ++#define MEMMUX_PIOH6 _SBF(12,0) ++#define MEMMUX_MIBLSN2 _SBF(12,1) ++#define MEMMUX_PIOH7 _SBF(13,0) ++#define MEMMUX_MIBLSN3 _SBF(13,1) ++ ++/* ++ * LCD Multiplexing IOCON Register Bit Field constants ++ */ ++#define LCDMUX_PIOB4 _SBF(0,0) ++#define LCDMUX_CLD12 _SBF(0,1) ++#define LCDMUX_CLREV _SBF(0,2) ++#define LCDMUX_PIOB5 _SBF(2,0) ++#define LCDMUX_CLD13 _SBF(2,1) ++#define LCDMUX_PIOB6 _SBF(3,0) ++#define LCDMUX_CLD14 _SBF(3,1) ++#define LCDMUX_PIOB7 _SBF(4,0) ++#define LCDMUX_CLD15 _SBF(4,1) ++#define LCDMUX_CLDSPLEN _SBF(4,2) ++#define LCDMUX_PIOC0 _SBF(6,0) ++#define LCDMUX_CLDEN _SBF(6,1) ++#define LCDMUX_CLSPL _SBF(6,2) ++#define LCDMUX_PIOC1 _SBF(8,0) ++#define LCDMUX_CLVDDEN _SBF(8,1) ++#define LCDMUX_CLS _SBF(8,2) ++#define LCDMUX_PIOC2 _SBF(10,0) ++#define LCDMUX_CLXCLK _SBF(10,1) ++#define LCDMUX_PIOC3 _SBF(11,0) ++#define LCDMUX_CLCP _SBF(11,1) ++#define LCDMUX_PIOC4 _SBF(12,0) ++#define LCDMUX_CLD16 _SBF(12,1) ++#define LCDMUX_PIOC5 _SBF(13,0) ++#define LCDMUX_CLLP _SBF(13,1) ++#define LCDMUX_CLP _SBF(13,2) ++#define LCDMUX_PIOC6 _SBF(15,0) ++#define LCDMUX_CLD17 _SBF(15,1) ++#define LCDMUX_PIOC7 _SBF(16,0) ++#define LCDMUX_CLFP _SBF(16,1) ++#define LCDMUX_CLSPS _SBF(16,2) ++#define LCDMUX_PIOD0 _SBF(18,0) ++#define LCDMUX_CLD2 _SBF(18,1) ++#define LCDMUX_PIOD1 _SBF(19,0) ++#define LCDMUX_CLD3 _SBF(19,1) ++#define LCDMUX_PIOD2 _SBF(20,0) ++#define LCDMUX_CLD4 _SBF(20,1) ++#define LCDMUX_PIOD3 _SBF(21,0) ++#define LCDMUX_CLD5 _SBF(21,1) ++#define LCDMUX_PIOD4 _SBF(22,0) ++#define LCDMUX_CLD6 _SBF(22,1) ++#define LCDMUX_CPS _SBF(22,2) ++#define LCDMUX_PIOD5 _SBF(24,0) ++#define LCDMUX_CLD7 _SBF(24,1) ++#define LCDMUX_PIOD6 _SBF(25,0) ++#define LCDMUX_CLD8 _SBF(25,1) ++#define LCDMUX_PIOD7 _SBF(26,0) ++#define LCDMUX_CLD9 _SBF(26,1) ++#define LCDMUX_RCEII6 _SBF(27,0) ++#define LCDMUX_CLD10 _SBF(27,1) ++#define LCDMUX_RCEII7 _SBF(28,0) ++#define LCDMUX_CLD11 _SBF(28,1) ++ ++/* ++ * Miscellaneous Multiplexing IOCON Register Bit Field constants ++ */ ++#define MISCMUX_PWM1 _SBF(0,0) ++#define MISCMUX_DCDEOT1 _SBF(0,1) ++#define MISCMUX_PIOA5 _SBF(1,0) ++#define MISCMUX_RCCLKOUT _SBF(1,1) ++#define MISCMUX_PIOA6 _SBF(2,0) ++#define MISCMUX_RCEII0 _SBF(2,1) ++#define MISCMUX_PIOA7 _SBF(3,0) ++#define MISCMUX_RCEII1 _SBF(3,1) ++#define MISCMUX_PIOB0 _SBF(4,0) ++#define MISCMUX_RCEII2 _SBF(4,1) ++#define MISCMUX_RCEII3 _SBF(5,0) ++#define MISCMUX_PWM0SYNC _SBF(5,1) ++#define MISCMUX_RCEII4 _SBF(6,0) ++#define MISCMUX_PWM0 _SBF(6,1) ++#define MISCMUX_RCCTOUT _SBF(7,0) ++#define MISCMUX_DCDACK1 _SBF(7,1) ++#define MISCMUX_DCDREQ1 _SBF(8,0) ++#define MISCMUX_RCEII5 _SBF(8,1) ++#define MISCMUX_PIOF1 _SBF(9,0) ++#define MISCMUX_RCCLKEN _SBF(9,1) ++#define MISCMUX_RCCLKIN _SBF(10,0) ++#define MISCMUX_RCUTCLK _SBF(10,1) ++ ++/* ++ * DMA Multiplexing IOCON Register Bit Field constants ++ */ ++#define DMAMUX_PIOB1 _SBF(0,0) ++#define DMAMUX_DCDEOT0 _SBF(0,1) ++#define DMAMUX_PIOB2 _SBF(1,0) ++#define DMAMUX_DCDACK0N _SBF(1,1) ++#define DMAMUX_PIOB3 _SBF(2,0) ++#define DMAMUX_DCDREQ0 _SBF(2,1) ++ ++/* ++ * UART Multiplexing IOCON Register Bit Field constants ++ */ ++#define UARTMUX_UT0IRRXA _SBF(0,0) ++#define UARTMUX_UT0RXD _SBF(0,1) ++#define UARTMUX_UT0IRTXA _SBF(1,0) ++#define UARTMUX_UT0TXD _SBF(1,1) ++#define UARTMUX_PIOA3 _SBF(2,0) ++#define UARTMUX_UT1RXD _SBF(2,1) ++#define UARTMUX_PIOA4 _SBF(3,0) ++#define UARTMUX_UT1TXD _SBF(3,1) ++ ++/* ++ * SSI Multiplexing IOCON Register Bit Field constants ++ */ ++#define SSIMUX_SSPIN _SBF(0,0) ++#define SSIMUX_UT2RXD _SBF(0,1) ++#define SSIMUX_SSPOUT _SBF(1,0) ++#define SSIMUX_UT2TXD _SBF(1,1) ++#define SSIMUX_PIOA0 _SBF(2,0) ++#define SSIMUX_SSPENB _SBF(2,1) ++#define SSIMUX_PIOA1 _SBF(3,0) ++#define SSIMUX_SSPCLK _SBF(3,1) ++#define SSIMUX_PIOA2 _SBF(4,0) ++#define SSIMUX_SSPFRM _SBF(4,1) ++ ++#endif /* LH79520_IOCON_H */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/io.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/io.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/io.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/io.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,52 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/io.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARM_ARCH_IO_H ++#define __ASM_ARM_ARCH_IO_H ++ ++#define IO_SPACE_LIMIT 0xffffffff ++ ++/* ++ * We don't actually have real ISA nor PCI buses, but there is so many ++ * drivers out there that might just work if we fake them... ++ */ ++// DDD #define __io(a) (PCIO_BASE + (a)) ++#define __io(a) (a) ++#define __mem_pci(a) ((unsigned long)(a)) ++#define __mem_isa(a) ((unsigned long)(a)) ++ ++/* ++ * Generic virtual read/write ++ */ ++#define __arch_getw(a) (*(volatile unsigned short *)(a)) ++#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) ++#define __arch_ioremap __ioremap ++#define __arch_iounmap __iounmap ++ ++/* ++ * Validate the pci memory address for ioremap. ++ */ ++// DDD #define iomem_valid_addr(iomem,size) (1) ++ ++/* ++ * Convert PCI memory space to a CPU physical address ++ */ ++// DDD #define iomem_to_phys(iomem) (iomem) ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/irq.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/irq.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/irq.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/irq.h 2005-11-02 17:51:52.000000000 -0400 +@@ -0,0 +1,250 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/irq.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include <linux/delay.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/rcpc.h> ++#include <asm/arch/iocon.h> ++#if 0 ++#include <asm/arch/cpld.h> // DDD only for testing the switches ++#endif ++ ++ ++#define NR_VEC 16 /* number of vectors */ ++/* ++ * Vectored Interrupt Controller Module Register Structure ++ */ ++typedef struct { ++ u32 IRQStatus; /* masked IRQ status */ ++ u32 FIQStatus; /* masked FIQ status */ ++ u32 RawIntr; /* raw status */ ++ u32 IntSelect; /* select whether source generates IRQ or FIQ */ ++ u32 IntEnable; /* int enable mask */ ++ u32 IntEnClear; /* writes here clear bits in IntEnable */ ++ u32 SoftInt; /* gen soft interrupts */ ++ u32 SoftIntClear; /* writes here clear bits in SoftInt */ ++ u32 Protection; /* protection enable */ ++ u32 reserved1[3]; ++ u32 CurrentISR; /* interrupt vector address of current interrupt */ ++ u32 DefVectAddr; /* default vector address */ ++ u32 reserved2[50]; ++ u32 VectAddr[NR_VEC]; /* interrupt vector address 0...NR_VEC */ ++ u32 reserved3[48]; ++ u32 VectCntl[NR_VEC]; /* vector control 0...NR_VEC */ ++ u32 reserved4[48]; ++ u32 ITCR; /* test mode */ ++ u32 ITIP1; /* test mode */ ++ u32 ITIP2; /* test mode */ ++ u32 ITOP1; /* test mode */ ++ u32 ITOP2; /* test mode */ ++ u32 reserved5[819]; /* empty */ ++ u32 periphid[4]; /* Peripheral ID register bits */ ++ u32 cellid[4]; /* PrimeCell ID register bits */ ++} vicRegs_t; ++ ++ ++/********************************************************************** ++ * Vectored Interrupt Controller Register Bit Fields ++ *********************************************************************/ ++ ++/********************************************************************** ++ * The bit fields of the following registers have implementation ++ * specific meaning, and must be defined at the implementation level. ++ * ++ * irqstatus - VICIRQStatus ++ * fiqstatus - VICFIQStatus ++ * rawintr - VICRawIntr ++ * intselect - VICIntSelect ++ * intenable - VICIntEnable ++ * intenclear - VICIntEnClear ++ * softint - VICSoftInt ++ * softintclear- VICSoftIntClear ++ * ++ * The following definitions for these registers are generic, ++ * i.e., they are implementation independent. They can be used to ++ * create implementation specific macros. ++ *********************************************************************/ ++ ++/********************************************************************** ++ * VIC Interrupt Select Register Bit Fields ++ *********************************************************************/ ++/* The following can be OR'd with the IntSelect Register to select ++ * an interrupt as FIQ. */ ++#define VIC_INTSELECT_FIQ(n) _BIT((n) & 0x1F) ++/* The following can be AND'd with the IntSelect Register to select ++ * an interrupt as IRQ. */ ++#define VIC_INTSELECT_IRQ(n) ~(_BIT((n) & 0x1F)) ++ ++/********************************************************************** ++ * VIC Interrupt Enable, Interrupt Enable Clear Register Bit Fields ++ * VIC Soft Interrupt, Soft Interrupt Clear Register Bit Fields ++ *********************************************************************/ ++#define VIC_INT_ENABLE(n) _BIT((n) & 0x1F) ++#define VIC_INT_CLEAR(n) _BIT((n) & 0x1F) ++ ++/********************************************************************** ++ * VIC Protection Enable Register Bit Fields ++ *********************************************************************/ ++#define VIC_PROTECTION _BIT(0) ++ ++/********************************************************************** ++ * VIC Vector Address Clear Register ++ *********************************************************************/ ++#define VIC_VECTORADDR_CLEAR 0 ++ ++/********************************************************************** ++ * VIC Vector Control Register Bit Fields ++ *********************************************************************/ ++/* To revise a Vector Control Register, clear the register, then ++ * use the SELECT macro to associate a line and enable the vector ++ * with the same operation. ++ * The ENABLE macro is provided for completeness. ++ * Use this register to enable and disable the VECTOR feature; ++ * use the intenable register to enable the interrupt ++ * itself, and the intenclear register to clear the interrupt. */ ++#define VIC_VECTCNTL_SELECT(n) (_SBF(0,((n) & 0x1F)) | _BIT(5)) ++#define VIC_VECTCNTL_ENABLE _BIT(5) ++ ++/********************************************************************** ++ * Vectored Interrupt Controller Test Registers ++ *********************************************************************/ ++/********************************************************************** ++ * itcr - Test Control ++ *********************************************************************/ ++#define VIC_ITCR_ITEN _BIT(0) ++ ++/********************************************************************** ++ * itip1 - Test Input 1 ++ *********************************************************************/ ++#define VIC_ITIP1_F _BIT(6) ++#define VIC_ITIP1_I _BIT(7) ++ ++/********************************************************************** ++ * itop1 - Test Output 1 ++ *********************************************************************/ ++#define VIC_ITOP1_F _BIT(6) ++#define VIC_ITOP1_I _BIT(7) ++ ++ ++ ++ ++#define fixup_irq(i) (i) ++ ++#define TESTIRQ ++ ++#ifdef TESTIRQ // DDD ++static unsigned int myReadCp15(void) ++{ ++ unsigned int x; ++ asm ("mrc p15, 0, %0, c1, c0, 0;" : "=r"(x) : ); ++ return x; ++} ++#endif ++ ++ ++ ++static void lh79520_mask_irq( u32 irq) ++{ ++ vicRegs_t *vic = (vicRegs_t *)VIC_BASE; ++ vic->IntEnClear = (1 << irq); ++} ++ ++static void lh79520_unmask_irq( u32 irq) ++{ ++ vicRegs_t *vic = (vicRegs_t *)VIC_BASE; ++ ++#ifdef TESTIRQ ++ if (irq != 17) ++ udelay(1); // printk( "VIC unmask irq %d\n", irq); ++#endif // 0 DDD ++ vic->IntEnable = (1 << irq); ++} ++ ++#undef TESTIRQ ++ ++static __inline__ void irq_init_irq(void) ++{ ++ int irq, i; ++ vicRegs_t *vic = (vicRegs_t *)VIC_BASE; ++ rcpcRegs_t *rcpc = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ ioconRegs_t *iocon = (ioconRegs_t *)IO_ADDRESS( IOCON_PHYS); ++ ++ /* allow external interrupts to come in */ ++ iocon->MiscMux = MISCMUX_RCEII0 | ++ MISCMUX_RCEII1 | ++ MISCMUX_RCEII2; ++ ++#ifdef TESTIRQ // DDD ++ printk( "irq_init_irq() cr1=%08X\n", myReadCp15()); ++ printk( "vic=0x%08lX rcpc=0x%08lX\n", (unsigned long) vic, (unsigned long) rcpc); ++ printk( "vic periph id[0-3] = 0x%X 0x%X 0x%X 0x%X\n", vic->periphid[0], vic->periphid[1], vic->periphid[2], vic->periphid[3]); ++#endif // 0 ++ ++ vic->IntEnClear = 0xffffffff; /* clear all interrupt enables */ ++ vic->IntSelect = 0; /* everything generates IRQ */ ++ ++ // DDD don't want to do this !! vic->Protection = 1; /* allow only priviledged access */ ++ ++ /* disable vectored interrupts */ ++ for( i = 0; i < NR_VEC; i++) { ++ vic->VectAddr[i] = 0; ++ vic->VectCntl[i] = 0; ++ } ++ ++ for (irq = 0; irq < NR_IRQS; irq++) { ++ irq_desc[irq].valid = 1; ++ irq_desc[irq].probe_ok = 1; ++ irq_desc[irq].mask_ack = lh79520_mask_irq; ++ irq_desc[irq].mask = lh79520_mask_irq; ++ irq_desc[irq].unmask = lh79520_unmask_irq; ++ } ++ ++ /* ++ * External interrupts 0-2 and 6-7 are active LOW, and External ++ * interrupts 3-5 are active HIGH. <---= DDD wrong ++ */ ++ ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; /* unlock RCPC registers */ ++ barrier(); ++ ++ rcpc->intClear = 0xff; /* clear all external interrupts */ ++ ++ rcpc->intConfig = ( ++ RCPC_INTCONFIG( RCPC_INT1, RCPC_INT_HLT) | // irq 1 (ide) high level ++ RCPC_INTCONFIG( RCPC_INT2, RCPC_INT_LLT) | // irq 2 (MARMALADE ETH) is low level ++ RCPC_INTCONFIG( RCPC_INT3, RCPC_INT_FET) | // irq 3 (MARMALADE TS) active low ++ RCPC_INTCONFIG( RCPC_INT4, RCPC_INT_HLT) | ++ RCPC_INTCONFIG( RCPC_INT5, RCPC_INT_HLT) | ++ RCPC_INTCONFIG( RCPC_INT6, RCPC_INT_LLT) ++ ); ++ ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; /* lock RCPC registers */ ++ printk( "RCPC locked ->control=0x%08lX\n", (unsigned long) rcpc->control); ++ printk( "RCPC ->intConfig = 0x%08lX\n", (unsigned long) rcpc->intConfig); ++ ++#if 0 ++ { // DDD test the switches ++ cpldRegs_t *cpld = (cpldRegs_t *)CPLD_BASE; ++ cpld->intr_mask = 0x1f; ++ } ++#endif ++ ++ // DDD init_FIQ(); ++} +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/irqs.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/irqs.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/irqs.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/irqs.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,51 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/irqs.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __ASM_ARCH_IRQS_H ++#define __ASM_ARCH_IRQS_H ++ ++#define NR_IRQS 32 ++ ++ ++#define IRQ_ETHERNET 0 ++#define IRQ_CF 1 ++#define IRQ_CPLD 2 ++#define IRQ_PWM0SYNC 3 ++#define IRQ_PWM0 4 ++#define IRQ_DREQ1 5 ++#define IRQ_LCDVD10 6 ++#define IRQ_LCDVD11 7 ++#define IRQ_spare_i0 8 /* spare internal */ ++#define IRQ_spare_i1 9 /* spare internal */ ++#define IRQ_spare_i2 10 /* spare internal */ ++#define IRQ_SPEXTINT3 11 ++#define IRQ_LCD 12 ++#define IRQ_SSPTXINTR 13 ++#define IRQ_SSPRXINTR 14 ++#define IRQ_SSPRORINTR 15 ++#define IRQ_SSPINTR 16 ++#define IRQ_TIMER0 17 ++#define IRQ_TIMER1 18 ++#define IRQ_TIMER2 19 ++#define IRQ_TIMER3 20 ++#define IRQ_UART0_RX 21 ++#define IRQ_UART0_TX 22 ++#define IRQ_UART0 23 ++#define IRQ_UART1 24 ++#define IRQ_UART2 25 ++#define IRQ_DMA 26 /* all DMA channels */ ++#define IRQ_spare_i4 27 /* spare internal */ ++#define IRQ_spare_i5 28 /* spare internal */ ++#define IRQ_spare_i6 29 /* spare internal */ ++#define IRQ_RTC 30 ++#define IRQ_WDT 31 ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/keyboard.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/keyboard.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/keyboard.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/keyboard.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,15 @@ ++/* ++ * linux/include/asm-arm/arch-anakin/keyboard.h ++ * ++ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V. ++ * ++ * 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. ++ * ++ * Changelog: ++ * 11-Apr-2001 TTC Created ++ */ ++#define kbd_init_hw() do { } while (0) ++#define kbd_enable_irq() do { } while (0) ++#define kbd_disable_irq() do { } while (0) +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/lh7x-7seg.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/lh7x-7seg.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/lh7x-7seg.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/lh7x-7seg.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,71 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++#ifndef _LH79X_7SEG_H_ ++#define _LH79X_7SEG_H_ ++ ++/********************************************************************** ++* linux/drivers/misc/lh79x_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. ++* ++**********************************************************************/ ++ ++/********************************************************************** ++* The sharp 7-segment display ++* ++* _ == a ++* | | == f b ++* - == g ++* | | == e c ++* -. == d dot ++* ++* NOTE: The 7-segment display bars are bit-mapped. ++* NOTE: The 7-segment display bars are ACTIVE LOW. ++* ++* NOTE: When read, the 7-segment display does not return valid data. As a ++* result, it is HIGHLY recommended daemons accessing the display ++* use the provided routines which programatically track the current ++* value of the display to simulate read functionality. Otherwise, ++* application access of the display will be tainted. ++* ++**********************************************************************/ ++ ++#define SSD_A 0x01 ++#define SSD_B 0x02 ++#define SSD_C 0x04 ++#define SSD_D 0x08 ++#define SSD_E 0x10 ++#define SSD_F 0x20 ++#define SSD_G 0x40 ++#define SSD_DOT 0x80 ++#define SSD_DP SSD_DOT ++ ++#ifdef KERNEL ++ ++extern uint16_t lh79x_7seg_read_raw_display(void); ++extern u_char lh79x_7seg_read_raw_display_lsb(void); ++extern u_char lh79x_7seg_read_raw_display_msb(void); ++ ++extern uint16_t lh79x_7seg_read_display(void); ++extern u_char lh79x_7seg_read_display_lsb(void); ++extern u_char lh79x_7seg_read_display_msb(void); ++ ++extern void lh79x_7seg_write_raw_display(uint16_t raw_val); ++extern void lh79x_7seg_write_raw_display_lsb(u_char raw_lsb); ++extern void lh79x_7seg_write_raw_display_msb(u_char raw_msb); ++ ++extern void lh79x_7seg_write_display(uint16_t val) ++extern void lh79x_7seg_write_display_lsb(u_char lsb) ++extern void lh79x_7seg_write_display_msb(u_char msb) ++extern void lh79x_7seg_write_display_str(u_char *str); ++ ++#endif /* KERNEL */ ++ ++#endif /* _LH79X_7SEG_H_ */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/memory.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/memory.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/memory.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/memory.h 2005-11-02 17:42:57.000000000 -0400 +@@ -0,0 +1,116 @@ ++/* ++ * linux/include/asm-arm/arch-sa1100/memory.h ++ * ++ * Copyright (C) 1999-2000 Nicolas Pitre <nico@cam.org> ++ */ ++ ++#ifndef __ASM_ARCH_MEMORY_H ++#define __ASM_ARCH_MEMORY_H ++ ++#include <linux/config.h> ++ ++/* ++ * Task size: 3GB ++ */ ++#define TASK_SIZE (0xc0000000UL) ++#define TASK_SIZE_26 (0x04000000UL) ++ ++/* ++ * This decides where the kernel will search for a free chunk of vm ++ * space during mmap's. ++ */ ++#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) ++ ++/* ++ * Page offset: 3GB ++ */ ++#define PAGE_OFFSET (0xc0000000UL) ++ ++/* ++ * Physical DRAM offset is 0xc0000000 on the SA1100 ++ */ ++#define PHYS_OFFSET (0x20000000UL) ++#define PHYS_OFFSET2 (0x28000000UL) /* Phys addr of second bank of SDRAM */ ++ ++/* ++ * We take advantage of the fact that physical and virtual address can be the ++ * same. The NUMA code is handling the large holes that might exist between ++ * all memory banks. ++ */ ++#define __virt_to_phys__is_a_macro ++#define __phys_to_virt__is_a_macro ++#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET) ++#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET) ++ ++/* ++ * Virtual view <-> DMA view memory address translations ++ * virt_to_bus: Used to translate the virtual address to an ++ * address suitable to be passed to set_dma_addr ++ * bus_to_virt: Used to convert an address for DMA operations ++ * to an address that the kernel can use. ++ * ++ * On the SA1100, bus addresses are equivalent to physical addresses. ++ */ ++#define __virt_to_bus__is_a_macro ++#define __bus_to_virt__is_a_macro ++#define __virt_to_bus(x) __virt_to_phys(x) ++#define __bus_to_virt(x) __phys_to_virt(x) ++ ++#ifdef CONFIG_DISCONTIGMEM ++/* ++ * Because of the wide memory address space between physical RAM banks on the ++ * SA1100, it's much more convenient to use Linux's NUMA support to implement ++ * our memory map representation. Assuming all memory nodes have equal access ++ * characteristics, we then have generic discontiguous memory support. ++ * ++ * Of course, all this isn't mandatory for SA1100 implementations with only ++ * one used memory bank. For those, simply undefine CONFIG_DISCONTIGMEM. ++ * ++ * The nodes are matched with the physical memory bank addresses which are ++ * incidentally the same as virtual addresses. ++ * ++ * node 0: 0xc0000000 - 0xc7ffffff ++ * node 1: 0xc8000000 - 0xcfffffff ++ * node 2: 0xd0000000 - 0xd7ffffff ++ * node 3: 0xd8000000 - 0xdfffffff ++ */ ++ ++#define NR_NODES 4 ++ ++/* ++ * Given a kernel address, find the home node of the underlying memory. ++ */ ++#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 27) ++ ++/* ++ * Given a page frame number, convert it to a node id. ++ */ ++#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (27 - PAGE_SHIFT)) ++ ++/* ++ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory ++ * and returns the mem_map of that node. ++ */ ++#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr)) ++ ++/* ++ * Given a page frame number, find the owning node of the memory ++ * and returns the mem_map of that node. ++ */ ++#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) ++ ++/* ++ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory ++ * and returns the index corresponding to the appropriate page in the ++ * node's mem_map. ++ */ ++#define LOCAL_MAP_NR(addr) \ ++ (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) ++ ++#else ++ ++#define PFN_TO_NID(addr) (0) ++ ++#endif ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/param.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/param.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/param.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/param.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,21 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/param.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define HZ 100 +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/rcpc.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/rcpc.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/rcpc.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/rcpc.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,222 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/rcpc.h ++ * ++ * Copyright (C) 2001 Sharp Microelectronics of the Americas, Inc. ++ * Camas, WA ++ * Portions Copyright (C) 2002 Lineo, Inc. ++ * ++ * DDD ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++ ++#ifndef RCPC_H ++#define RCPC_H ++ ++/* ++ * RCPC: Reset, Clock, and Power Controller Register Structure ++ */ ++typedef __attribute((packed)) struct { ++ u32 control; /* control register */ ++ u32 id; /* identification */ ++ u32 remap; /* Remap Control */ ++ u32 softReset; /* Soft Reset */ ++ u32 resetStatus; /* Reset Status */ ++ u32 resetStatusclr; /* Reset Status Clear */ ++ u32 HCLKPrescale; /* HCLK Prescaler */ ++ u32 CpuClkPrescale; /* ARM Core Clk Prescaler */ ++ u32 PCLKPrescale; /* PCLK Prescaler */ ++ u32 periphClkCtrl; /* Peripheral Clock Ctrl */ ++ u32 spareClkCtrl; /* Spare Clock Ctrl */ ++ u32 AHBClkCtrl; /* AHB Clock Ctrl */ ++ u32 periphClkSel; /* Peripheral Clock Select*/ ++ u32 spareClkSel; /* Spare Clock Select */ ++ u32 PWM0Prescale; /* PWM 0 Prescaler*/ ++ u32 PWM1Prescale; /* PWM 1 Prescaler*/ ++ u32 spare0Prescale; /* Spare clock 0 Prescaler*/ ++ u32 spare1Prescale; /* Spare clock 1 Prescaler*/ ++ u32 spare2Prescale; /* Spare clock 2 Prescaler*/ ++ u32 spare3Prescale; /* Spare clock 3 Prescaler*/ ++ u32 spare4Prescale; /* Spare clock 4 Prescaler*/ ++ u32 spare5Prescale; /* Spare clock 5 Prescaler*/ ++ u32 spare6Prescale; /* Spare clock 6 Prescaler*/ ++ u32 spare7Prescale; /* Spare clock 7 Prescaler*/ ++ u32 spare8Prescale; /* Spare clock 8 Prescaler*/ ++ u32 spare9Prescale; /* Spare clock 9 Prescaler*/ ++ u32 spare10Prescale; /* Spare clck 10 Prescaler*/ ++ u32 spare11Prescale; /* Spare clck 11 Prescaler*/ ++ u32 spare12Prescale; /* Spare clck 12 Prescaler*/ ++ u32 spare13Prescale; /* Spare clck 13 Prescaler*/ ++ u32 spare14Prescale; /* Spare clck 14 Prescaler*/ ++ u32 spare15Prescale; /* Spare clck 15 Prescaler*/ ++ u32 intConfig; /* Ext. Interrupt Config */ ++ u32 intClear; /* Ext. Interrupt Clear */ ++ u32 coreClkConfig; /* ARM Core Clock Config */ ++} rcpcRegs_t; ++ ++ ++/* ++ * RCPC Bit Fields ++ */ ++ ++/* ++ * control Register Bit Fields ++ */ ++#define RCPC_CTRL_EP _BIT(0) /* Enable PLL */ ++#define RCPC_CTRL_EX _BIT(1) /* Enable Internal XTAL */ ++ ++#define RCPC_CTRL_PWRDWNSEL(n) _SBF(2,(n)) /* Power Down Mode Sel*/ ++/* Mode Arguments to RCPC_CTRL_PWRDWNSEL(n) */ ++#define PWRDWNSEL_ACTIVE 0 ++#define PWRDWNSEL_STANDBY 1 ++#define PWRDWNSEL_SLEEP 2 ++#define PWRDWNSEL_STOP1 3 ++#define PWRDWNSEL_STOP2 4 ++ ++#define RCPC_CTRL_OUTSEL(n) _SBF(5,(n)) ++/* Arguments to RCPC_CTRL_OUTSEL(n) */ ++#define OUTSEL_CLK_INTOSC 0 ++#define OUTSEL_CLK_PLL 1 ++#define OUTSEL_FCLK_CPU 2 ++#define OUTSEL_HCLK 3 ++ ++#define RCPC_CTRL_CLKSEL_PLL _SBF(7,0) ++#define RCPC_CTRL_CLKSEL_EXT _SBF(7,1) ++ ++#define RCPC_CTRL_WRTLOCK_LOCKED _SBF(9,0) ++#define RCPC_CTRL_WRTLOCK_ENABLED _SBF(9,1) ++ ++/********************************************************************** ++ * identification - Identification Register Bit Fields ++ *********************************************************************/ ++#define RCPC_ID_DEFAULT (0x5200) ++ ++/********************************************************************** ++ * remap - Remap Control Register Bit Fields ++ *********************************************************************/ ++#define RCPC_REMAP_SMEM0 (0) ++#define RCPC_REMAP_SDMEM0 (1) ++#define RCPC_REMAP_IMEM0 (2) ++ ++/********************************************************************** ++ * softreset - Soft Reset Register Bit Fields ++ *********************************************************************/ ++#define RCPC_SOFTRESET_ALL (0xDEAD) ++#define RCPC_SOFTRESET_GBL (0xDEAC) ++ ++/********************************************************************** ++ * resetstatus, resetstatusclr - Reset Status Register Bit Fields ++ *********************************************************************/ ++#define RCPC_RESET_STATUS_EXT _BIT(0) ++#define RCPC_RESET_STATUS_WDTO _BIT(1) ++ ++/********************************************************************** ++ * hclkPrescale - HCLK Prescaler Register Bit Fields ++ * cpuclkPrescale - ARM Core Clock Prescaler Register Bit Fields ++ * pclkPrescale - PCLK Prescaler Register Bit Fields ++ * pwm0Prescale - PWM0 Prescaler Register Bit Fields ++ * pwm1Prescale - PWM1 Prescaler Register Bit Fields ++ * sparePrescale - Spare Prescaler Register Bit Fields ++ * Note: not all constants are applicable to all registers. ++ * See Reference. ++ *********************************************************************/ ++#define RCPC_PRESCALER_DIV1 _SBF(0,0) ++#define RCPC_PRESCALER_DIV2 _SBF(0,1) ++#define RCPC_PRESCALER_DIV4 _SBF(0,2) ++#define RCPC_PRESCALER_DIV6 _SBF(0,3) ++#define RCPC_PRESCALER_DIV8 _SBF(0,4) ++#define RCPC_PRESCALER_DIV16 _SBF(0,8) ++#define RCPC_PRESCALER_DIV30 _SBF(0,15) ++#define RCPC_PRESCALER_DIV32 _SBF(0,16) ++#define RCPC_PRESCALER_DIV64 _SBF(0,32) ++#define RCPC_PRESCALER_DIV128 _SBF(0,64) ++#define RCPC_PRESCALER_DIV256 _SBF(0,128) ++#define RCPC_PRESCALER_DIV65534 (0xFFFF) ++ ++/********************************************************************** ++ * periphclkctrl - Peripheral Clock Control Register Bit Fields ++ * spareclkctrl - Spare Clock Control Register Bit Fields ++ * ahbclkctrl - AHB Clock Control Register Bit Fields ++ * Writing a "0" to a bit in these registers enables the ++ * corresponding clock ++ *********************************************************************/ ++#define RCPC_CLKCTRL_U0_DISABLE _BIT(0) ++#define RCPC_CLKCTRL_U1_DISABLE _BIT(1) ++#define RCPC_CLKCTRL_U2_DISABLE _BIT(2) ++#define RCPC_CLKCTRL_CT0_DISABLE _BIT(3) ++#define RCPC_CLKCTRL_CT1_DISABLE _BIT(4) ++#define RCPC_CLKCTRL_CT2_DISABLE _BIT(5) ++#define RCPC_CLKCTRL_CT3_DISABLE _BIT(6) ++#define RCPC_CLKCTRL_PWM0_DISABLE _BIT(7) ++#define RCPC_CLKCTRL_PWM1_DISABLE _BIT(8) ++#define RCPC_CLKCTRL_RTC_DISABLE _BIT(9) ++#define RCPC_CLKCTRL_SPARE_DISABLE(f) _BIT(f) ++ ++#define RCPC_SPARE_CLKCTRL_SSPCLK_DISABLE _BIT(1) ++#define RCPC_SPARE_CLKCTRL_LCDCLK_DISABLE _BIT(0) ++ ++#define RCPC_CLKCTRL_DMAC_DISABLE _BIT(0) ++#define RCPC_CLKCTRL_HCLKSP0_DISABLE _BIT(1) ++ ++/********************************************************************** ++ * periphclksel - Peripheral Clock Select Register Bit Fields ++ * Writing a "0" to U0-U2 in this register enables the ++ * XTAL Oscillator as the clock source ++ * Writing a "0" to CT0-CT3 in this register enables the ++ * HCLK as the clock source ++ *********************************************************************/ ++#define RCPC_PCLKSEL_U0_EXT _BIT(0) /* U0 Clock Source */ ++#define RCPC_PCLKSEL_U1_EXT _BIT(1) /* U1 Clock Source */ ++#define RCPC_PCLKSEL_U2_EXT _BIT(2) /* U2 Clock Source */ ++#define RCPC_PCLKSEL_CT0_EXT _BIT(3) /* CT0 Clock Source */ ++#define RCPC_PCLKSEL_CT1_EXT _BIT(4) /* CT1 Clock Source */ ++#define RCPC_PCLKSEL_CT2_EXT _BIT(5) /* CT2 Clock Source */ ++#define RCPC_PCLKSEL_CT3_EXT _BIT(6) /* CT3 Clock Source */ ++#define RCPC_PCLKSEL_RTC_32 0 /* RTC Clock Source 32KHz */ ++#define RCPC_PCLKSEL_RTC_EXT _SBF(7,2) /* RTC Clock Source Ext */ ++ ++/********************************************************************** ++ * spareclksel - Peripheral Clock Select Register Bit Fields ++ * Writing a "0" to a bit in this register enables the ++ * HCLK as the clock source ++ *********************************************************************/ ++#define RCPC_SCLKSEL_SP(n) _SBF((n),1) /* SP2 - SP15 */ ++#define RCPC_SCLKSEL_SSPCLK _BIT(1) /* SSP Clock External */ ++#define RCPC_SCLKSEL_LCDCLK _BIT(0) /* LCD Clock External */ ++ ++/********************************************************************** ++ * intconfig - External Interrupt Configuration Register Bit Fields ++ *********************************************************************/ ++#define RCPC_INTCONFIG(f,v) _SBF((f),(v)) ++/* RCPC_INTCONFIG arguments for 'f' parameter */ ++#define RCPC_INT0 0 ++#define RCPC_INT1 2 ++#define RCPC_INT2 4 ++#define RCPC_INT3 6 ++#define RCPC_INT4 8 ++#define RCPC_INT5 10 ++#define RCPC_INT6 12 ++#define RCPC_INT7 14 ++/* RCPC_INTCONFIG arguments for 'v' parameter */ ++#define RCPC_INT_LLT 0 /* Low Level Trigger */ ++#define RCPC_INT_HLT 1 /* High Level Trigger */ ++#define RCPC_INT_FET 2 /* Falling Edge Trigger */ ++#define RCPC_INT_RET 3 /* Rising Edge Trigger */ ++ ++/********************************************************************** ++ * intclear - External Interrupt Clear Register Bit Fields ++ *********************************************************************/ ++#define RCPC_INTCLEAR(n) _BIT(n) /* Clear Edge Interrupt 'n' */ ++ ++/********************************************************************** ++ * coreclkconfig - Core Clock Configuration Register Bit Fields ++ *********************************************************************/ ++#define RCPC_CCC_STDASYNCH 0 /* Standard Mode, Asynch operation */ ++#define RCPC_CCC_FASTBUS 1 /* Fast Bus Extension Mode */ ++#define RCPC_CCC_STDSYNCH 2 /* Standard Mode, Synch operation */ ++ ++#endif // RCPC_H +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/serial.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/serial.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/serial.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/serial.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,34 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/serial.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++#ifndef __ASM_ARCH_SERIAL_H ++#define __ASM_ARCH_SERIAL_H ++ ++/* ++ * This assumes you have a 14.7456 MHz clock for your UART. ++ */ ++#define BASE_BAUD (14745600 / 16) ++ ++/* ++ * Standard COM flags ++ */ ++#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) ++ ++#define RS_TABLE_SIZE 2 ++ ++#define STD_SERIAL_PORT_DEFNS \ ++ /* MAGIC UART CLK PORT IRQ FLAGS */ \ ++ { 0, BASE_BAUD, UART0_BASE, IRQ_UART0, STD_COM_FLAGS }, /* ttyAM0 */ \ ++ { 0, BASE_BAUD, UART1_BASE, IRQ_UART1, STD_COM_FLAGS }, /* ttyAM0 */ \ ++ { 0, BASE_BAUD, UART2_BASE, IRQ_UART2, STD_COM_FLAGS }, /* ttyAM1 */ \ ++ ++#define EXTRA_SERIAL_PORT_DEFNS ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/smc_pl090.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/smc_pl090.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/smc_pl090.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/smc_pl090.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,68 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/smc_pl090.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * ++ * This file contains the structure definitions and manifest ++ * constants for ARM IP component: ++ * Static Memory Controller PrimeCell PL090 ++ * ++ * References: ++ * (1) ARM PrimeCell Static Memory Controller (PL090) ++ * Technical Reference Manual, ARM DDI 0160C. ++ * (2) ARM Isis Technical Reference Manual, System on Chip Group, ++ * ARM SC063-TRM-0001-B ++ * ++ * COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC. ++ * CAMAS, WA ++ */ ++ ++#ifndef SMC_PL090_H ++#define SMC_PL090_H ++ ++#ifndef _BIT ++#define _BIT(n) (1 << (n)) ++#endif ++ ++#ifndef _SBF ++#define _SBF(f,v) ((v) << (f)) ++#endif ++ ++/* ++ * Static Memory Controller Module Register Structure ++ */ ++typedef struct { ++ volatile unsigned int bcr0; /* Configuration for bank 0 */ ++ volatile unsigned int bcr1; /* Configuration for bank 1 */ ++ volatile unsigned int bcr2; /* Configuration for bank 2 */ ++ volatile unsigned int bcr3; /* Configuration for bank 3 */ ++ volatile unsigned int bcr4; /* Configuration for bank 4 */ ++ volatile unsigned int bcr5; /* Configuration for bank 5 */ ++ volatile unsigned int bcr6; /* Configuration for bank 6 */ ++ volatile unsigned int bcr7; /* Configuration for bank 7 */ ++} smcRegs_t; ++ ++/* ++ * Static Memory Controller Bit Field constants ++ */ ++#define IDCY(n) _SBF(0,((n)&0x0F)) /* Idle Cycle Time */ ++#define WST1(n) _SBF(5,((n)&0x1F)) /* Wait State 1 */ ++#define RBLE(n) _SBF(10,((n)&0x01)) /* Read Byte Lane Enable */ ++#define WST2(n) _SBF(11,((n)&0x1F)) /* Wait State 2 */ ++#define BUSERR _BIT(24) /* Bus Transfer Error Flag */ ++#define WPERR _BIT(25) /* Write Protect Error Flag */ ++#define WP _BIT(26) /* Write Protect */ ++#define BM _BIT(27) /* Burst Mode */ ++#define MW8 _SBF(28,0) /* Memory width 8 bits */ ++#define MW16 _SBF(28,1) /* Memory width 16 bits */ ++#define MW32 _SBF(28,2) /* Memory width 32 bits */ ++#define ATNONE _SBF(30,0) /* No Retry */ ++#define ATEVERY _SBF(30,2) /* Retry after every access */ ++#define ATAFTER4 _SBF(30,3) /* Retry after 4 accesses */ ++ ++#endif /* SMC_PL090_H */ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/ssp_lh7x.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ssp_lh7x.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/ssp_lh7x.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/ssp_lh7x.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,159 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++/********************************************************************** ++* linux/include/asm-arm/arch-lh79520/ssp_lh7x.h ++* ++* Provide SSP (Synchronous Serial Port) types & definitions ++* 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. ++* ++**********************************************************************/ ++ ++#ifndef _SSP_LH7X_h ++#define _SSP_LH7X_h ++ ++//#define SSP_BASE SSP_PHYS ++ ++/********************************************************************* ++* Synchronous Serial Port Registers ++*********************************************************************/ ++#define SSPCR0 (SSP_BASE+0x00) /* Control reg. 0 */ ++#define SSPCR1 (SSP_BASE+0x04) /* Control reg. 1 */ ++#define SSPDR (SSP_BASE+0x08) /* Receive FIFO (Read)*/ ++ /* Transmit FIFO data reg. (Write)*/ ++#define SSPSR (SSP_BASE+0x0C) /* Status Reg. */ ++#define SSPCPSR (SSP_BASE+0x10) /* Clock prescale reg. */ ++#define SSPIIR (SSP_BASE+0x14) /* Interrupt identification reg. (Read) */ ++#define SSPICR SSPIIR /* Interrupt clear reg. (Write) */ ++/* ++* RESERVED: ++* 0x18 - 0x3C ++* 0x40 - 0x90 (For test purposes) ++* 0x94 - 0xFF ++*/ ++ ++/********************************************************************* ++* Synchronous Serial Port Register Structure ++*********************************************************************/ ++typedef struct { ++ volatile unsigned int cr0; ++ volatile unsigned int cr1; ++ volatile unsigned int dr; ++ volatile unsigned int sr; ++ volatile unsigned int cpsr; ++ union { ++ volatile unsigned int iir; ++ volatile unsigned int icr; ++ } u; ++ volatile unsigned int reservedssp[58]; ++} sspRegs_t; ++ ++/* ++* To use the structure, declare the following in your source ++* static sspRegs_t *ssp = (sspRegs_t *)SSP_BASE; ++*/ ++ ++/********************************************************************* ++* 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 ++ ++/********************************************************************* ++* Synchronous Serial Port Bit Fields ++*********************************************************************/ ++ ++/********************************************************************* ++* Control 0 Register Bit Fields ++*********************************************************************/ ++/* Valid range for argument to SSP_CR0_DSS(n) is [4-16] */ ++#define SSP_CR0_DSS(n) _SBF(0,(n)-1) /* Data Size Select */ ++#define SSP_CR0_FRF_MOT _SBF(4,0) /* Motorola SPI frame */ ++#define SSP_CR0_FRF_TI _SBF(4,1) /* TI synchronous serial frame */ ++#define SSP_CR0_FRF_NS _SBF(4,2) /* National Microwire frame */ ++#define SSP_CR0_SPO _BIT(6) /* SPI Polarity */ ++#define SSP_CR0_SPH _BIT(7) /* SPI Polarity */ ++#define SSP_CR0_SCR(n) _SBF(8,(n)) /* Serial Clock Rate */ ++ ++/********************************************************************* ++* Control 1 Register Bit Fields ++*********************************************************************/ ++#define SSP_CR1_RIE _BIT(0) /* RX FIFO interrupt enable */ ++#define SSP_CR1_TIE _BIT(1) /* TX FIFO interrupt enable */ ++#define SSP_CR1_RORIE _BIT(2) /* RX FIFO overrun int. enable */ ++#define SSP_CR1_LBM _BIT(3) /* Loop back mode */ ++#define SSP_CR1_SSE _BIT(4) /* Synchronous serial port enable */ ++ ++/********************************************************************* ++* Status Register Bit Fields ++*********************************************************************/ ++#define SSP_SR_TFE _BIT(0) /* TX FIFO Empty */ ++#define SSP_SR_TNF _BIT(1) /* TX FIFO not full */ ++#define SSP_SR_RNE _BIT(2) /* RX FIFO not empty */ ++#define SSP_SR_RFF _BIT(3) /* RX FIFO full */ ++#define SSP_SR_BSY _BIT(4) /* Busy flag */ ++ ++/********************************************************************* ++* Clock Prescale Divisor Register Bit Fields ++*********************************************************************/ ++#define SSP_CPSR_CPDVSR(n) _SBF(0,(n)&0xFE) /* Clock prescale divisor */ ++ ++/********************************************************************* ++* Interrupt Identification / Interrupt Clear Register Bit Fields ++* Note: ARM Reference conflicts on the definition of these bits ++* and the usage of the registers. Verify before using these ++* definitions. ++*********************************************************************/ ++#define SSP_IIR_RIS _BIT(0) /* TX FIFO Empty */ ++#define SSP_IIR_TIS _BIT(1) /* TX FIFO not full */ ++#define SSP_IIR_RORIS _BIT(2) /* RX FIFO overrun int. status */ ++ ++/********************************************************************* ++* The TouchScreen communication BPS (bits per second) ++*********************************************************************/ ++#define LH7x_TS_BPS 100000 ++ ++/********************************************************************* ++* Misc. ++*********************************************************************/ ++#define SSP_MAX_TIMEOUT 0xffff ++#define RCPC_SSP_PRESCALE_MAX 256 ++#define SSP_PRESCALE_MAX 254 ++#define SSP_PRESCALE_MIN 2 ++#define SSP_DIVIDER_MAX 256 ++ ++/* Define values to associate with the device we are conencted to */ ++#define SSP_INVALID_DEVICE 0xFF ++#define SSP_EEPROM 0x00 ++#define SSP_TOUCHSCREEN 0x01 ++ ++/********************************************************************* ++* Context Structure Definition ++*********************************************************************/ ++typedef struct sspContext_t sspContext_t; ++struct sspContext_t { ++ wait_queue_head_t *irq_wait_ptr; ++ int irq_state; ++ int ssp_dev_sel; // cpld->ssp_dev_sel is not readable !!! ++ int ts_txTimeout; ++ int ts_rxTimeout; ++ int ee_txTimeout; ++ int ee_rxTimeout; ++ int haveIrq; ++ spinlock_t sspLock; ++}; ++ ++#endif /* _SSP_LH7X_h */ ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/system.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/system.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/system.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/system.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,28 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/system.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Changelog: ++ * 07-Jan-2001 Duck Created ++ */ ++ ++#ifndef __ASM_ARCH_SYSTEM_H ++#define __ASM_ARCH_SYSTEM_H ++ ++static inline void ++arch_idle(void) ++{ ++} ++ ++static inline void ++arch_reset(char mode) ++{ ++ cpu_reset(0); ++} ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/time.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/time.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/time.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/time.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,111 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/time.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Changelog: ++ * 07-Jan-2002 Duck Created ++ */ ++ ++#ifndef __ASM_ARCH_TIME_H ++#define __ASM_ARCH_TIME_H ++ ++#include <asm/arch/hardware.h> ++#include <asm/arch/rcpc.h> ++ ++/* ++ * Dual Timer Module Register Structure ++ * The LH79520 has two of these. ++ */ ++typedef struct { ++ unsigned int Timer1Load; ++ unsigned int Timer1Value; ++ unsigned int Timer1Control; ++ unsigned int Timer1Clear; ++ unsigned int Timer1Test; ++ unsigned int reservedtmr1[3]; ++ unsigned int Timer2Load; ++ unsigned int Timer2Value; ++ unsigned int Timer2Control; ++ unsigned int Timer2Clear; ++ unsigned int Timer2Test; ++ unsigned int reservedtmr2[3]; ++} timerRegs_t; ++ ++ ++/* ++ * Timer Control Register Bit Field constants ++ * All other bits in the Timer Control Register must be written as ++ * zero ++ */ ++#define TMRCTRL_ENABLE _SBF(7,1) ++#define TMRCTRL_DISABLE _SBF(7,0) ++#define TMRCTRL_MODE_PERIODIC _SBF(6,1) ++#define TMRCTRL_MODE_FREERUN _SBF(6,0) ++#define TMRCTRL_CASCADE_ENABLE _SBF(4,1) ++#define TMRCTRL_CASCADE_DISABLE _SBF(4,0) ++#define TMRCTRL_PRESCALE1 _SBF(2,0) ++#define TMRCTRL_PRESCALE16 _SBF(2,1) ++#define TMRCTRL_PRESCALE256 _SBF(2,2) ++ ++/* ++ * what to load the timer with ++ * it's 14.745600 MHz * 21 (PLL multiplier) / 6 (PCLK prescalar) / 16 (TIMER_PRESCALE) / HZ ++ * this gives us timerLoad=32256 for Hz=100 ++ */ ++#define TIMER_PRESCALE 16 ++ ++static void ++timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ timerRegs_t *mod1Timer = (timerRegs_t *)IO_ADDRESS( TIMER0_PHYS); ++ ++ mod1Timer->Timer1Clear = 1; /* clear interrupt */ ++ ++ do_timer(regs); ++} ++ ++ ++static inline void ++setup_timer(void) ++{ ++ rcpcRegs_t *rcpc = (rcpcRegs_t *)IO_ADDRESS( RCPC_PHYS); ++ timerRegs_t *mod1Timer = (timerRegs_t *)IO_ADDRESS( TIMER0_PHYS), /* first timer module */ ++ *mod2Timer = (timerRegs_t *)IO_ADDRESS( TIMER1_PHYS); /* second timer module */ ++ u32 timerLoad; ++ ++ timerLoad = hclkfreq_get() / TIMER_PRESCALE / HZ; ++ printk( "setup_timer(): timerLoad=%d\n", timerLoad); ++ ++ /* stop all timers */ ++ mod1Timer->Timer1Control = 0; ++ mod1Timer->Timer2Control = 0; ++ mod2Timer->Timer1Control = 0; ++ mod2Timer->Timer2Control = 0; ++ ++ /* enable clock to first timer */ ++ rcpc->control |= RCPC_CTRL_WRTLOCK_ENABLED; /* unlock RCPC registers */ ++ barrier(); ++ ++ rcpc->periphClkCtrl &= ~RCPC_CLKCTRL_CT0_DISABLE; ++ rcpc->control &= ~RCPC_CTRL_WRTLOCK_ENABLED; /* lock RCPC registers */ ++ ++ /* setup the FRC in the first timer in the first module. */ ++ mod1Timer->Timer1Load = timerLoad; ++ ++ mod1Timer->Timer1Control = TMRCTRL_ENABLE | ++ TMRCTRL_MODE_PERIODIC | ++ TMRCTRL_PRESCALE16; ++ ++ ++ ++ timer_irq.handler = timer_interrupt; ++ timer_irq.flags = SA_INTERRUPT; ++ setup_arm_irq( IRQ_TIMER0, &timer_irq); ++} ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/timex.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/timex.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/timex.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/timex.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,16 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/timex.h ++ * ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++/* ++ * On the LH79520, the DDD ++ */ ++#define CLOCK_TICK_RATE (PLL_CLOCK / 6 / 16) ++ +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/uncompress.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/uncompress.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/uncompress.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/uncompress.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,52 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/uncompress.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define UART_DR (*(volatile unsigned char *)0xfffc1000) ++#define UART_FR (*(volatile unsigned short *)0xfffc1018) ++ ++#define UARTFR_TXFE 0x80 ++ ++/* ++ * This does not append a newline ++ */ ++static void ++puts( const char *s) ++{ ++ while( *s) { ++ while( (UART_FR & UARTFR_TXFE) == 0) /* wait for room in the tx FIFO */ ++ ; ++ ++ UART_DR = *s; /* ship a char */ ++ ++ if (*s == '\n') { /* it's a new line */ ++ while( (UART_FR & UARTFR_TXFE) == 0) /* wait for room in the tx FIFO */ ++ ; ++ ++ UART_DR = '\r'; /* ship a carriage return */ ++ } ++ s++; ++ } ++} ++ ++/* ++ * nothing to do ++ */ ++#define arch_decomp_setup() ++#define arch_decomp_wdog() +diff -urN linux-2.4.26/include/asm-arm/arch-lh79520/vmalloc.h linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/vmalloc.h +--- linux-2.4.26/include/asm-arm/arch-lh79520/vmalloc.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/arch-lh79520/vmalloc.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,32 @@ ++/* ++ * linux/include/asm-arm/arch-lh79520/vmalloc.h ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/* ++ * Just any arbitrary offset to the start of the vmalloc VM area: the ++ * current 8MB value just means that there will be a 8MB "hole" after the ++ * physical memory until the kernel virtual memory starts. That means that ++ * any out-of-bounds memory accesses will hopefully be caught. ++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced ++ * area for the same reason. ;) ++ */ ++#define VMALLOC_OFFSET (8*1024*1024) ++#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) ++#define VMALLOC_VMADDR(x) ((unsigned long)(x)) ++#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +diff -urN linux-2.4.26/include/asm-arm/hardware/cradle.h linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/cradle.h +--- linux-2.4.26/include/asm-arm/hardware/cradle.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/cradle.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,14 @@ ++/* ++ * cradle.h ++ */ ++#ifndef _INCLUDE_CRADLE_H_ ++#define _INCLUDE_CRADLE_H_ ++ ++#define CRADLE_MAJOR 254 ++ ++#define CRADLE_GET_DOCKING_STATE_IOCTL 0 ++ ++#define CRADLE_DOCKED_STATE 0 ++#define CRADLE_UNDOCKED_STATE 1 ++ ++#endif +diff -urN linux-2.4.26/include/asm-arm/hardware/lcd_contrast.h linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/lcd_contrast.h +--- linux-2.4.26/include/asm-arm/hardware/lcd_contrast.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/lcd_contrast.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,30 @@ ++/* ++ lcd_contrast.h ++ ++ ++These values are intended to be passed to the ++pl110fb lcd driver. The driver was modified to control ++a Maxim contrast controller to make life easy. ++ ++*/ ++ ++ ++#ifndef _LCD_CONTRAST_ ++#define _LCD_CONTRAST_ ++ ++ ++//ioctls ++#define LCD_CONTRAST_RESET 0 ++#define LCD_CONTRAST_INC 1 ++#define LCD_CONTRAST_DEC 2 ++ ++#define LCD_CONTRAST_PRESET 3 ++// above takes parameters (0 - 63) ++// 0 - reset ++// 31 - highest ++// 63 - lowest ++ ++ ++#endif //__LCD_CONTRAST__ ++ ++ +diff -urN linux-2.4.26/include/asm-arm/hardware/serial_amba_pl011.h linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/serial_amba_pl011.h +--- linux-2.4.26/include/asm-arm/hardware/serial_amba_pl011.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/asm-arm/hardware/serial_amba_pl011.h 2005-11-02 17:37:32.000000000 -0400 +@@ -0,0 +1,114 @@ ++/* ++ * linux/include/asm-arm/hardware/serial_amba_pl011.h ++ * ++ * Internal header file for AMBA PrimeCell PL011 serial ports ++ * ++ * Copyright (C) 2002 Lineo, Inc. ++ * ++ * Based on serial_amba.h, which is: ++ * Copyright (C) ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef ASM_ARM_HARDWARE_SERIAL_AMBA_PL011_H ++#define ASM_ARM_HARDWARE_SERIAL_AMBA_PL011_H ++ ++/* ------------------------------------------------------------------------------- ++ * From AMBA UART (PL011) TRM ++ * ------------------------------------------------------------------------------- ++ * UART Register Offsets. ++ */ ++#define AMBA_UARTDR 0x00 /* Data read or written from the interface. */ ++#define AMBA_UARTRSR 0x04 /* Receive status register (Read). */ ++#define AMBA_UARTECR 0x04 /* Error clear register (Write). */ ++ ++ ++#define AMBA_UARTFR 0x18 /* Flag register (Read only). */ ++#define AMBA_UARTILPR 0x20 /* IrDA low power counter register. */ ++#define AMBA_UARTIBRD 0x24 /* Integer baud rate divisor. */ ++#define AMBA_UARTFBRD 0x28 /* Fractional baud rate divisor. */ ++#define AMBA_UARTLCR_H 0x2C /* Line control register, high byte. */ ++#define AMBA_UARTCR 0x30 /* Control register. */ ++#define AMBA_UARTIFLS 0x34 /* Interrupt FIFO level select. */ ++#define AMBA_UARTIMSC 0x38 /* Interrupt Mask Set/Clear. */ ++#define AMBA_UARTRIS 0x3C /* Raw Interrupt status register (Read). */ ++#define AMBA_UARTMIS 0x40 /* Masked Interrupt status register (Read). */ ++#define AMBA_UARTICR 0x44 /* Interrupt clear register (Write). */ ++ ++#define AMBA_UARTRSR_OE 0x0800 /* Overrun error */ ++#define AMBA_UARTRSR_BE 0x0400 /* Break error */ ++#define AMBA_UARTRSR_PE 0x0200 /* Parity error */ ++#define AMBA_UARTRSR_FE 0x0100 /* framing error */ ++ ++#define AMBA_UARTFR_TXFF 0x20 /* Tx FIFO full */ ++#define AMBA_UARTFR_RXFE 0x10 /* Rx FIFO empty */ ++#define AMBA_UARTFR_BUSY 0x08 /* busy xmitting */ ++#define AMBA_UARTFR_DCD 0x04 ++#define AMBA_UARTFR_DSR 0x02 ++#define AMBA_UARTFR_CTS 0x01 ++#define AMBA_UARTFR_TMSK (AMBA_UARTFR_TXFF + AMBA_UARTFR_BUSY) ++ ++/* Interrupt Mask Set/Clear register bits */ ++#define AMBA_UARTIMSC_RTIM 0x40 /* Rx timeout interrupt mask */ ++#define AMBA_UARTIMSC_TXIM 0x20 /* Tx interrupt mask */ ++#define AMBA_UARTIMSC_RXIM 0x10 /* Rx interrupt mask */ ++#define AMBA_UARTIMSC_DSRMIM 0x08 /* DSR Modem Interrupt mask */ ++#define AMBA_UARTIMSC_DCDMIM 0x04 /* DCD Modem Interrupt mask */ ++#define AMBA_UARTIMSC_CTSMIM 0x02 /* CTS Modem Interrupt mask */ ++#define AMBA_UARTIMSC_RIMIM 0x01 /* RI Modem Interrupt mask */ ++/* all modem mask bits */ ++#define AMBA_UARTIMSC_Modem (AMBA_UARTIMSC_DSRMIM |AMBA_UARTIMSC_DCDMIM | \ ++ AMBA_UARTIMSC_CTSMIM |AMBA_UARTIMSC_RIMIM) ++ ++ ++ ++/* Control Register bits */ ++ ++#define AMBA_UARTCR_RTS 0x800 /* nRTS */ ++#define AMBA_UARTCR_DTR 0x400 /* nDTR */ ++#define AMBA_UARTCR_RXE 0x200 /* Rx enable */ ++#define AMBA_UARTCR_TXE 0x100 /* Tx enable */ ++#define AMBA_UARTCR_LBE 0x080 /* Loopback enable */ ++#define AMBA_UARTCR_SIRLP 0x004 /* IR SIR Low Power Mode */ ++#define AMBA_UARTCR_SIREN 0x002 /* IR SIR enable */ ++#define AMBA_UARTCR_UARTEN 0x001 /* UART enable */ ++ ++#define AMBA_UARTLCR_H_WLEN_8 0x60 ++#define AMBA_UARTLCR_H_WLEN_7 0x40 ++#define AMBA_UARTLCR_H_WLEN_6 0x20 ++#define AMBA_UARTLCR_H_WLEN_5 0x00 ++#define AMBA_UARTLCR_H_FEN 0x10 ++#define AMBA_UARTLCR_H_STP2 0x08 ++#define AMBA_UARTLCR_H_EPS 0x04 ++#define AMBA_UARTLCR_H_PEN 0x02 ++#define AMBA_UARTLCR_H_BRK 0x01 ++ ++/* Raw/Masked Interrupt Status Register bits*/ ++#define AMBA_UART_IS_RT 0x40 ++#define AMBA_UART_IS_TX 0x20 ++#define AMBA_UART_IS_RX 0x10 ++#define AMBA_UART_IS_DSR 0x08 ++#define AMBA_UART_IS_DCD 0x04 ++#define AMBA_UART_IS_CTS 0x02 ++#define AMBA_UART_IS_RI 0x01 ++#define AMBA_UART_IS_MI (AMBA_UART_IS_DSR | AMBA_UART_IS_DCD | \ ++ AMBA_UART_IS_CTS | AMBA_UART_IS_RI ) ++ ++#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE) ++#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS) ++ ++#endif /* ASM_ARM_HARDWARE_SERIAL_AMBA_PL011_H */ ++ +diff -urN linux-2.4.26/include/lh79520.h linux-2.4.26-vrs1-lnode80/include/lh79520.h +--- linux-2.4.26/include/lh79520.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/lh79520.h 2005-11-02 17:37:33.000000000 -0400 +@@ -0,0 +1,340 @@ ++/* ++ * lh79520.h: LH79520 specific defines ++ * ++ * 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 as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++ ++#ifndef BLOB_ARCH_LH79520_H ++#define BLOB_ARCH_LH79520_H ++ ++#ifndef _BIT ++#define _BIT(n) (1 << (n)) ++#endif ++ ++#ifndef _SBF ++#define _SBF(f,v) ((v) << (f)) ++#endif ++ ++/* the base address were BLOB is loaded by the first stage loader */ ++// #define BLOB_ABS_BASE_ADDR (0x60000000) // for gdb bootstrap in SRAM ++#define BLOB_ABS_BASE_ADDR (0x20200400) ++ ++ ++/* where do various parts live in RAM */ ++#define BLOB_RAM_BASE (0x20100000) ++#define KERNEL_RAM_BASE (0x20008000) ++#define PARAM_RAM_BASE (0x20110000) ++#define RAMDISK_RAM_BASE (0x20400000) ++#define RAMDISK_VIRTUAL_BASE (0xC0400000) // kernel virtual address of where ramdisk will be ++ ++ ++/* and where do they live in flash */ ++#define BLOB_FLASH_BASE (0x00000000) ++#define BLOB_FLASH_LEN (128 * 1024) // 128 KB for blob ++ ++#define PARAM_FLASH_BASE (BLOB_FLASH_BASE + BLOB_FLASH_LEN) ++#define PARAM_FLASH_LEN (64 * 1024) // 64 KB for params ++ ++#define KERNEL_FLASH_BASE (PARAM_FLASH_BASE + PARAM_FLASH_LEN) ++#define KERNEL_FLASH_LEN (1024 * 1024 - \ ++ (BLOB_FLASH_LEN + PARAM_FLASH_LEN)) // 1 MB - (BLOB + PARAM) for kernel ++ ++#define RAMDISK_FLASH_BASE (KERNEL_FLASH_BASE + KERNEL_FLASH_LEN) ++#define RAMDISK_FLASH_LEN (3 * 1024 * 1024) // 3 MB for ramdisk ++ ++#define PARAM_START PARAM_FLASH_BASE ++#define PARAM_LEN PARAM_FLASH_LEN ++ ++/* the position of the kernel boot parameters */ ++#define BOOT_PARAMS (0x20000100) ++ ++ ++/* the size (in kbytes) to which the compressed ramdisk expands */ ++#define RAMDISK_SIZE (8 * 1024) ++ ++ ++/* Memory configuration */ ++ ++/********************************************************************** ++ * AHB BASES ++ *********************************************************************/ ++#define AHB_PHYS (0xFFFF0000) ++#define VIC_PHYS_MIRROR (AHB_PHYS + 0x0000) ++#define SMC_REGS_BASE (AHB_PHYS + 0x1000) ++#define SDRAM_REGS_BASE (AHB_PHYS + 0x2000) ++#define LCD_BASE (AHB_PHYS + 0x4000) ++#define VIC_PHYS (AHB_PHYS + 0xF000) ++ ++/********************************************************************** ++ * APB BASES ++ *********************************************************************/ ++#define APB_PHYS (0xFFFC0000) ++#define UART0_BASE (APB_PHYS + 0x00000) ++#define UART1_BASE (APB_PHYS + 0x01000) ++#define UART2_BASE (APB_PHYS + 0x02000) ++#define PWM_BASE (APB_PHYS + 0x03000) ++#define TIMER0_BASE (APB_PHYS + 0x04000) ++#define TIMER1_BASE (APB_PHYS + 0x05000) ++#define SSP_BASE (APB_PHYS + 0x06000) ++#define GPIO3_BASE (APB_PHYS + 0x1C000) ++#define GPIO2_BASE (APB_PHYS + 0x1D000) ++#define GPIO1_BASE (APB_PHYS + 0x1E000) ++#define GPIO0_BASE (APB_PHYS + 0x1F000) ++#define RTC_BASE (APB_PHYS + 0x20000) ++#define DMAC_BASE (APB_PHYS + 0x21000) ++#define RCPC_BASE (APB_PHYS + 0x22000) ++#define WDTIMER_BASE (APB_PHYS + 0x23000) ++#define LCDICP_BASE (APB_PHYS + 0x24000) ++#define IOCON_BASE (APB_PHYS + 0x25000) ++ ++#define SDRAM_MEM_BASE 0x20000000 ++#define SMC_MEM_BASE (0x40000000) ++#define INTERNAL_MEM_BASE (0x60000000) ++ ++ ++/********************************************************************** ++ * SMC Memory Bank Address Space Bases ++ *********************************************************************/ ++ ++#define SMC_BANK0_BASE (SMC_MEM_BASE + 0x00000000) ++#define SMC_BANK1_BASE (SMC_MEM_BASE + 0x04000000) ++#define SMC_BANK2_BASE (SMC_MEM_BASE + 0x08000000) ++#define SMC_BANK3_BASE (SMC_MEM_BASE + 0x0C000000) ++#define SMC_BANK4_BASE (SMC_MEM_BASE + 0x10000000) ++#define SMC_BANK5_BASE (SMC_MEM_BASE + 0x14000000) ++#define SMC_BANK6_BASE (SMC_MEM_BASE + 0x18000000) ++#define SMC_BANK7_BASE (SMC_MEM_BASE + 0x1C000000) ++ ++/* Flash ROM */ ++#define FLASH_PHYS_BASE 0x00000000 ++#define FLASH_PHYS_SIZE 0x00400000 ++ ++/********************************************************************** ++ * SDRAMC Memory Bank Address Space Bases ++ *********************************************************************/ ++ ++#define SDRAM_BANK0_BASE (SDRAM_MEM_BASE + 0x00000000) ++#define SDRAM_BANK1_BASE (SDRAM_MEM_BASE + 0x08000000) ++ ++// WDT offsets ++#define WDT_WDCTLR_OFFSET 0x0 ++ ++// RCPC offsets for assembly files ++#define RCPC_CONTROL_OFFSET 0x00 ++#define RCPC_REMAP_OFFSET 0x08 ++#define RCPC_SOFTRESET_OFFSET 0x0C ++#define RCPC_RESETSTATUS_OFFSET 0x10 ++#define RCPC_RESETSTATUS_CLEAR_OFFSET 0x14 ++#define RCPC_HCLKCLK_PRESCALE_OFFSET 0x18 ++#define RCPC_CPUCLK_PRESCALE_OFFSET 0x1C ++#define RCPC_PERIPHCLKCTRL_OFFSET 0x24 ++#define RCPC_AHBCLKCTRL_OFFSET 0x2C ++#define RCPC_PERIPHCLKSELECT_OFFSET 0x30 ++#define RCPC_CORECLKCONFIG_OFFSET 0x88 ++ ++#define RCPC_CPUCLK_PRESCALE_78 0x2 ++#define RCPC_CPUCLK_PRESCALE_52 0x3 ++#define RCPC_CPUCLK_PRESCALE_39 0x4 ++#define RCPC_HCLK_PRESCALE_52 0x3 ++#define RCPC_HCLK_PRESCALE_39 0x4 ++#define RCPC_CPUCLK_PRESCALE_DEFAULT RCPC_CPUCLK_PRESCALE_52 ++#define RCPC_HCLK_PRESCALE_DEFAULT RCPC_HCLK_PRESCALE_52 ++//#define RCPC_CPUCLK_PRESCALE_DEFAULT RCPC_CPUCLK_PRESCALE_78 ++//#define RCPC_HCLK_PRESCALE_DEFAULT RCPC_HCLK_PRESCALE_52 ++ ++/* IOCON offsets for assembly code */ ++#define IOCON_MEMMUX_OFFSET 0x00 ++//#define IOCON_MEMMUX_INIT 0x00003fff ++#define IOCON_MEMMUX_INIT 0x00000075 ++#define IOCON_LCDMUX_OFFSET 0x04 ++#define IOCON_LCDMUX_INIT 0x1f3db95d ++#define IOCON_MISCMUX_OFFSET 0x08 ++#define IOCON_MISCMUX_INIT 0x0000005e ++#define IOCON_DMAMUX_OFFSET 0x0C ++#define IOCON_DMAMUX_INIT 0x00000000 ++#define IOCON_UARTMUX_OFFSET 0x10 ++#define IOCON_UARTMUX_INIT 0x0000000f ++#define IOCON_SSPMUX_OFFSET 0x14 ++#define IOCON_SSPMUX_INIT 0x0000001c ++ ++#if 0 ++/* GPIO Configuration */ ++#define GPIOB_DATA_OFFSET 0x000 ++#define GPIOB_DATA_INIT 0x00000000 ++#define GPIOB_DDR_OFFSET 0x008 ++#define GPIOB_DDR_INIT 0x00000000 ++#define GPIOF_DATA_OFFSET 0x000 ++#define GPIOF_DATA_INIT 0x000000DA ++#define GPIOF_DDR_OFFSET 0x008 ++#define GPIOF_DDR_INIT 0x000000FA ++#define GPIOG_DATA_OFFSET 0x000 ++#define GPIOG_DATA_INIT 0x000000E0 ++#define GPIOG_DDR_OFFSET 0x008 ++#define GPIOG_DDR_INIT 0x000000E0 ++#define GPIOH_DATA_OFFSET 0x004 ++#define GPIOH_DATA_INIT 0x00000043 ++#define GPIOH_DDR_OFFSET 0x00C ++#define GPIOH_DDR_INIT 0x00000043 ++#endif ++ ++#define GPIOB_DATA_OFFSET 0x004 ++#define GPIOB_DATA_INIT 0x00000000 ++#define GPIOB_DDR_OFFSET 0x00c ++#define GPIOB_DDR_INIT 0x00000000 ++#define GPIOF_DATA_OFFSET 0x004 ++#define GPIOF_DATA_INIT 0x00000008 ++#define GPIOF_DDR_OFFSET 0x00C ++#define GPIOF_DDR_INIT 0x00000038 ++#define GPIOG_DATA_OFFSET 0x000 ++#define GPIOG_DATA_INIT 0x000000E0 ++#define GPIOG_DDR_OFFSET 0x008 ++#define GPIOG_DDR_INIT 0x000000E0 ++#define GPIOH_DATA_OFFSET 0x004 ++#define GPIOH_DATA_INIT 0x00000043 ++#define GPIOH_DDR_OFFSET 0x00C ++#define GPIOH_DDR_INIT 0x00000043 ++ ++ ++ ++ ++/* SDRAM controller offsets */ ++#define SDRAM_CFG0_OFF 0 ++#define SDRAM_CFG1_OFF 4 ++#define SDRAM_REFTIMER_OFF 8 ++ ++#define SDRAM_INIT_NORMAL 0 ++#define SDRAM_INIT_PALL 1 ++#define SDRAM_INIT_MODE 2 ++#define SDRAM_INIT_NOP 3 ++#define SDRAM_BUSY 0x20 /* SDRAM Engine Status */ ++ ++ ++/* ++ * Clock Indexes ++ * Caution: these indexes have to be coherent with the equivalent indexes ++ * included with associated 'C' modules ++ */ ++ ++#define RCPC_CLKIDX_DEFAULT 0 ++#define RCPC_CLKIDX_39_39 1 ++#define RCPC_CLKIDX_52_39 2 ++#define RCPC_CLKIDX_52_52 3 ++#define RCPC_CLKIDX_78_39 4 ++#define RCPC_CLKIDX_78_52 5 ++#define RCPC_CLKIDX_78_78 6 ++#define RCPC_CLKIDX_10_10 7 ++ ++/* ++ * SDRAM Refresh timer values for various Clock Indexes ++ */ ++#define REFTIMER_78 0x480 ++#define REFTIMER_52 0x320 ++#define REFTIMER_39 0x270 ++#define REFTIMER_10 0x80 ++ ++ ++/********************************************************************** ++ * Static Memory Controller (SMC) ++ *********************************************************************/ ++#define SMC ((SMCREGS *)(SMC_REGS_BASE)) ++ ++/********************************************************************** ++ * SDRAM Controller (SDRAM) ++ *********************************************************************/ ++#define SDRAM ((SDRAMREGS *)(SDRAM_REGS_BASE)) ++ ++/********************************************************************** ++ * Color LCD Controller (CLCDC) ++ *********************************************************************/ ++#define CLCDC ((CLCDCREGS *)(LCD_BASE)) ++ ++/********************************************************************** ++ * UARTs ++ *********************************************************************/ ++#define UARTID_OFFSET (0xFE0) ++#define UART0 ((UART *)(UART0_BASE)) ++#define UART1 ((UART *)(UART1_BASE)) ++#define UART2 ((UART *)(UART2_BASE)) ++#define UART0ID ((UARTID *)(UART0_BASE + UARTID_OFFSET)) ++#define UART1ID ((UARTID *)(UART1_BASE + UARTID_OFFSET)) ++#define UART2ID ((UARTID *)(UART2_BASE + UARTID_OFFSET)) ++ ++/* use this serial port */ ++#define UART ((UARTREGS *)(UART0_BASE)) ++#define LH_UART_NUM 0 ++ ++ ++/********************************************************************** ++ * TIMER ++ *********************************************************************/ ++#define TIMER2_OFFSET (0x20) ++#define TIMER0 ((TIMERREG *)(TIMER0_BASE)) ++#define TIMER1 ((volatile TIMERREG *)(TIMER0_BASE + TIMER2_OFFSET)) ++#define TIMER2 ((TIMERREG *)(TIMER1_BASE)) ++#define TIMER3 ((TIMERREG *)(TIMER1_BASE + TIMER2_OFFSET)) ++ ++/* ++ * base addresses of each dual timer module ++ */ ++#define MOD1_TIMER ((TIMERREGS *) TIMER0_BASE) ++#define MOD2_TIMER ((TIMERREGS *) TIMER1_BASE) ++ ++ ++#define RCPC ((RCPCREGS *)(RCPC_BASE)) ++#define LCDICP ((LCDICPREGS *)(LCDICP_BASE)) ++#define IOCON ((IOCONREGS *)(IOCON_BASE)) ++#define CPLD_PHYS_BASE SMC_BANK2_BASE ++#define CPLD ((CPLDREGS *)(CPLD_PHYS_BASE)) ++ ++#define _7seg(val) \ ++ { \ ++ CPLDREGS *cpld = CPLD; \ ++ cpld->seven_seg = (val); \ ++ } ++ ++/* ++ * CPU board DIP switches ++ */ ++#define DIPSW1 0x01 ++#define DIPSW2 0x02 ++#define DIPSW3 0x04 ++#define DIPSW4 0x08 ++#define DIPSW5 0x10 ++#define DIPSW6 0x20 ++#define DIPSW7 0x40 ++#define DIPSW8 0x80 ++ ++/* ++ * CPU and BUS speeds, also tied to SDRAM speed ++ * NOTE: Don't change one without changing the others!!!! ++ */ ++ ++#if 0 // run the CPU at 52 MHz, and the bus at 52 MHz ++ #define CPU_CLK_PRESCALAR RCPC_CPUCLK_PRESCALE_52 ++ #define SDRAM_REFTIMER REFTIMER_52 ++ #define HCLK_PRESCALAR RCPC_HCLK_PRESCALE_52 ++ #define CORE_CLK_CONFIG 3 /* FastBus */ ++#else // run the CPU at 78 MHz, and the Bus at 52 MHz ++ #define CPU_CLK_PRESCALAR RCPC_CPUCLK_PRESCALE_78 ++ #define SDRAM_REFTIMER 0x320 /*REFTIMER_78*/ ++ #define HCLK_PRESCALAR RCPC_HCLK_PRESCALE_52 ++ #define CORE_CLK_CONFIG 0 /* std mode, async */ ++#endif ++ ++ ++#endif // BLOB_ARCH_LH79520_H +diff -urN linux-2.4.26/include/linux/serial_core.h linux-2.4.26-vrs1-lnode80/include/linux/serial_core.h +--- linux-2.4.26/include/linux/serial_core.h 2005-11-02 16:54:26.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/linux/serial_core.h 2005-11-02 17:46:47.000000000 -0400 +@@ -51,6 +51,8 @@ + #define PORT_SA1100 34 + #define PORT_UART00 35 + #define PORT_21285 37 ++#define PORT_AMBA_PL011 38 ++#define PORT_LH7A400 39 + + /* Sparc type numbers. */ + #define PORT_SUNZILOG 38 +diff -urN linux-2.4.26/include/linux/verbosedebug.h linux-2.4.26-vrs1-lnode80/include/linux/verbosedebug.h +--- linux-2.4.26/include/linux/verbosedebug.h 1969-12-31 20:00:00.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/include/linux/verbosedebug.h 2005-11-02 17:37:33.000000000 -0400 +@@ -0,0 +1,51 @@ ++/* vi: set sw=4 ts=4 ai: */ ++ ++/********************************************************************** ++* linux/include/linux/verbosedebug.h ++* ++* Provide Verbose, Debug, and Verbose+Debug printk macros that can be ++* enabled or disabled vi the definitions of DEBUG and VERBOSE. ++* ++* vprintk -- Verbose printk ++* dprintk -- Debug printk ++* vdprintk -- Verbose+Debug printk ++* ++* 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. ++* ++**********************************************************************/ ++ ++#ifndef _VerboseDebug_h ++#define _VerboseDebug_h ++ ++#ifndef DRVNAME ++# define DRVNAME "" ++#endif ++ ++#ifdef VERBOSE ++# ifdef DEBUG ++# define vprintk(fmt,args...) {printk(DRVNAME ": " fmt, ## args);} ++# define dprintk(fmt,args...) {printk(DRVNAME ": " fmt, ## args);} ++# define vdprintk(fmt,args...) {printk(DRVNAME ": " fmt, ## args);} ++# else ++# define vprintk(fmt,args...) {printk(DRVNAME ": " fmt, ## args);} ++# define dprintk(fmt,args...) {} ++# define vdprintk(fmt,args...) {} ++# endif ++#else ++# ifdef DEBUG ++# define vprintk(fmt,args...) {} ++# define dprintk(fmt,args...) {printk(DRVNAME ": " fmt, ## args);} ++# define vdprintk(fmt,args...) {} ++# else ++# define vprintk(fmt,args...) {} ++# define dprintk(fmt,args...) {} ++# define vdprintk(fmt,args...) {} ++# endif ++#endif ++ ++#endif /* _VerboseDebug_h */ ++ +diff -urN linux-2.4.26/Makefile linux-2.4.26-vrs1-lnode80/Makefile +--- linux-2.4.26/Makefile 2005-11-02 16:54:16.000000000 -0400 ++++ linux-2.4.26-vrs1-lnode80/Makefile 2005-11-03 10:28:43.000000000 -0400 +@@ -1,11 +1,11 @@ + VERSION = 2 + PATCHLEVEL = 4 + SUBLEVEL = 26 +-EXTRAVERSION =-vrs1 ++EXTRAVERSION =-vrs1-lnode80 + + 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 := arm + KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") + + CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ +@@ -19,7 +19,7 @@ + HOSTCC = gcc + HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer + +-CROSS_COMPILE = ++CROSS_COMPILE = arm-linux- + + # + # Include the make variables (CC, etc...) |