14499 lines
435 KiB
Plaintext
14499 lines
435 KiB
Plaintext
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...)
|