summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-21 22:00:56 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-21 22:00:56 +0000
commit168660f24dfc46c2702acbe4701a446f42a59578 (patch)
treef431368afbf6b1b71809cf3fd904d800ea126f4d /arch/arm
parent6420f767924fa73b0ea267864d96820815f4ba5a (diff)
Merge with Linux 2.4.0-test5-pre3.
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Makefile10
-rw-r--r--arch/arm/boot/compressed/Makefile2
-rw-r--r--arch/arm/boot/compressed/head-sa1100.S80
-rw-r--r--arch/arm/boot/compressed/setup-sa1100.S130
-rw-r--r--arch/arm/config.in41
-rw-r--r--arch/arm/kernel/Makefile22
-rw-r--r--arch/arm/kernel/arch.c40
-rw-r--r--arch/arm/kernel/armksyms.c9
-rw-r--r--arch/arm/kernel/bios32.c2
-rw-r--r--arch/arm/kernel/dma-a5k.c99
-rw-r--r--arch/arm/kernel/dma-arc.c260
-rw-r--r--arch/arm/kernel/dma-dummy.c34
-rw-r--r--arch/arm/kernel/dma-footbridge.c88
-rw-r--r--arch/arm/kernel/dma-isa.c44
-rw-r--r--arch/arm/kernel/dma-isa.h29
-rw-r--r--arch/arm/kernel/dma-rpc.c312
-rw-r--r--arch/arm/kernel/dma.c307
-rw-r--r--arch/arm/kernel/dma.h68
-rw-r--r--arch/arm/kernel/ecard.c11
-rw-r--r--arch/arm/kernel/hw-sa1100.c18
-rw-r--r--arch/arm/kernel/oldlatches.c57
-rw-r--r--arch/arm/kernel/process.c31
-rw-r--r--arch/arm/kernel/signal.c1
-rw-r--r--arch/arm/kernel/sys_arm.c3
-rw-r--r--arch/arm/kernel/time.c6
-rw-r--r--arch/arm/kernel/traps.c3
-rw-r--r--arch/arm/lib/Makefile3
-rw-r--r--arch/arm/mm/init.c26
-rw-r--r--arch/arm/mm/mm-sa1100.c20
-rw-r--r--arch/arm/vmlinux-armo.lds.in1
-rw-r--r--arch/arm/vmlinux-armv.lds.in5
31 files changed, 877 insertions, 885 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 9f2e5347a..5bd7af915 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -114,12 +114,7 @@ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS
-ifeq ($(CONFIG_ARCH_A5K),y)
-MACHINE = a5k
-ARCHDIR = arc
-endif
-
-ifeq ($(CONFIG_ARCH_ARC),y)
+ifeq ($(CONFIG_ARCH_ARCA5K),y)
MACHINE = arc
ARCHDIR = arc
endif
@@ -197,7 +192,8 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
# The following is a hack to get 'constants.h' up
# to date before starting compilation
-CONSTANTS := constants
+
+$(patsubst %, _dir_%, $(SUBDIRS)) : constants
constants: $(TOPDIR)/include/asm-arm/proc-fns.h dummy
@$(MAKE) -C arch/arm/lib constants.h
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index f8ff4124c..f3c45c553 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -48,7 +48,7 @@ ZRELADDR = 0x40008000
endif
ifeq ($(CONFIG_ARCH_SA1100),y)
-OBJS += head-sa1100.o
+OBJS += head-sa1100.o setup-sa1100.o
ZTEXTADDR = 0xc0008000
ZRELADDR = 0xc0008000
ifeq ($(CONFIG_SA1100_VICTOR),y)
diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S
index 7b12ecef6..6b0d4624d 100644
--- a/arch/arm/boot/compressed/head-sa1100.S
+++ b/arch/arm/boot/compressed/head-sa1100.S
@@ -3,10 +3,12 @@
*
* Copyright (C) 1999 Nicolas Pitre <nico@cam.org>
*
- * SA1100 specific tweaks. This is merged with head.S by the linker.
+ * SA1100 specific tweaks. This is merged into head.S by the linker.
+ *
*/
#include <linux/config.h>
+#include <linux/linkage.h>
#ifndef CONFIG_ARCH_SA1100
#error What am I doing here...
@@ -36,6 +38,9 @@ __SA1100_start:
#endif
#ifdef CONFIG_SA1100_VICTOR
+ teq r9, #26 @ MACH_TYPE_VICTOR
+ bne 10f
+
@ Copy cmdline to 0xc0000000
mov r1, #0xc0000000
cmp r0, #0
@@ -44,6 +49,7 @@ __SA1100_start:
cmpne r2, #0
strb r2, [r1], #1
bne 1b
+10:
#endif
@ Data cache might be active.
@@ -64,73 +70,13 @@ __SA1100_start:
bic r0, r0, #0x0d @ clear WB, DC, MMU
bic r0, r0, #0x1000 @ clear Icache
mcr p15, 0, r0, c1, c0, 0
-
-#if defined( CONFIG_SA1100_ASSABET ) || \
- defined( CONFIG_SA1100_BRUTUS )
- @ Initialize UART1 for early serial communication
- @ since UART3 is used by angelboot. It is routed to
- @ alternate GPIO functions on Brutus.
- b 1f
-
-#ifdef CONFIG_SA1100_BRUTUS
-#define ALT_UART
-#endif
-
-GPIO_BASE: .long 0x90040000
-#define GPDR 0x04
-#define GAFR 0x1c
-
-PPC_BASE: .long 0x90060000
-#define PPAR 0x08
-
-UART1_BASE: .long 0x80010000
-#define UTCR0 0x00
-#define UTCR1 0x04
-#define UTCR2 0x08
-#define UTCR3 0x0c
-#define UTSR0 0x1c
-#define UTSR1 0x20
-
-#define BAUD_DIV_230400 0x000
-#define BAUD_DIV_115200 0x001
-#define BAUD_DIV_57600 0x003
-#define BAUD_DIV_38400 0x005
-#define BAUD_DIV_19200 0x00b
-#define BAUD_DIV_9600 0x017
-#define BAUD_DIV BAUD_DIV_9600
-
-1:
-#ifdef ALT_UART
- ldr r0, GPIO_BASE
- ldr r1, [r0, #GPDR]
- bic r1, r1, #1<<15
- orr r1, r1, #1<<14
- str r1, [r0, #GPDR]
- ldr r1, [r0, #GAFR]
- orr r1, r1, #(1<<15)|(1<<14)
- str r1, [r0, #GAFR]
- ldr r0, PPC_BASE
- ldr r1, [r0, #PPAR]
- orr r1, r1, #1<<12
- str r1, [r0, #PPAR]
-#endif
- ldr r0, UART1_BASE
-1: ldr r1, [r0, #UTSR1]
- tst r1, #1<<0 @ TBY
+/*
+ * Pause for a short time so that we give enough time
+ * for the host to start a terminal up.
+ */
+ mov r0, #0x02000000
+1: subs r0, r0, #1
bne 1b
- mov r1, #0
- str r1, [r0, #UTCR3]
- mov r1, #0x08 @ 8N1
- str r1, [r0, #UTCR0]
- mov r1, #BAUD_DIV
- str r1, [r0, #UTCR2]
- mov r1, r1, lsr #8
- str r1, [r0, #UTCR1]
- mov r1, #0x03 @ RXE + TXE
- str r1, [r0, #UTCR3]
- mov r1, #0xff @ flush status reg
- str r1, [r0, #UTSR0]
-#endif
@ Restore initial r0/r1
mov r0, r8
diff --git a/arch/arm/boot/compressed/setup-sa1100.S b/arch/arm/boot/compressed/setup-sa1100.S
new file mode 100644
index 000000000..6fd5b84e6
--- /dev/null
+++ b/arch/arm/boot/compressed/setup-sa1100.S
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/boot/compressed/setup-sa1100.S
+ *
+ * Copyright (C) 2000 Nicolas Pitre <nico@cam.org>
+ *
+ * SA1100 setup routines, to be used after BSS has been cleared.
+ *
+ * John G Dorsey <john+@cs.cmu.edu> 2000/05/25 :
+ * Runtime test for Neponset added.
+ */
+
+#define __ASSEMBLY__
+#include <linux/linkage.h>
+
+ .text
+
+GPIO_BASE: .long 0x90040000
+#define GPLR 0x00
+#define GPDR 0x04
+#define GPSR 0x08
+#define GAFR 0x1c
+
+PPC_BASE: .long 0x90060000
+#define PPAR 0x08
+
+UART1_BASE: .long 0x80010000
+UART3_BASE: .long 0x80050000
+#define UTCR0 0x00
+#define UTCR1 0x04
+#define UTCR2 0x08
+#define UTCR3 0x0c
+#define UTSR0 0x1c
+#define UTSR1 0x20
+
+#define BAUD_DIV_230400 0x000
+#define BAUD_DIV_115200 0x001
+#define BAUD_DIV_57600 0x003
+#define BAUD_DIV_38400 0x005
+#define BAUD_DIV_19200 0x00b
+#define BAUD_DIV_9600 0x017
+#define BAUD_DIV BAUD_DIV_9600
+
+SCR_loc: .long SYMBOL_NAME(SCR_value)
+#define GPIO_2_9 0x3fc
+
+
+ENTRY(sa1100_setup)
+ mov r3, r0 @ keep machine type in r3
+
+@ Read System Configuration "Register" for Assabet.
+@ (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
+@ User's Guide," p.4-9)
+
+ teq r3, #25 @ MACH_TYPE_ASSABET
+ bne skip_SCR
+
+ ldr r0, GPIO_BASE
+ ldr r1, [r0, #GPDR]
+ and r1, r1, #GPIO_2_9
+ str r1, [r0, #GPDR]
+ mov r1, #GPIO_2_9
+ str r1, [r0, #GPSR]
+ ldr r1, [r0, #GPDR]
+ bic r1, r1, #GPIO_2_9
+ str r1, [r0, #GPDR]
+
+ mov r2, #100
+1: ldr r1, [r0, #GPLR]
+ subs r2, r2, #1
+ bne 1b
+
+ and r2, r1, #GPIO_2_9
+ ldr r1, SCR_loc
+ str r2, [r1]
+
+ ldr r1, [r0, #GPDR]
+ and r1, r1, #GPIO_2_9
+ str r1, [r0, #GPDR]
+
+skip_SCR:
+
+ @ Initialize UART (if bootloader has not done it yet)...
+ teq r3, #16 @ MACH_TYPE_BRUTUS
+ teqne r3, #25 @ MACH_TYPE_ASSABET
+ bne skip_uart
+
+ @ UART3 if Assabet is used with Neponset
+ teq r3, #25 @ if Assabet
+ tsteq r2, #(1 << 9) @ ... and Neponset present
+ ldreq r0, UART3_BASE
+ beq uart_init
+
+ @ At least for Brutus, the UART1 is used through
+ @ the alternate GPIO function...
+ teq r3, #16 @ MACH_TYPE_BRUTUS
+ bne uart1
+
+alt_GPIO_uart: ldr r0, GPIO_BASE
+ ldr r1, [r0, #GPDR]
+ bic r1, r1, #1<<15
+ orr r1, r1, #1<<14
+ str r1, [r0, #GPDR]
+ ldr r1, [r0, #GAFR]
+ orr r1, r1, #(1<<15)|(1<<14)
+ str r1, [r0, #GAFR]
+ ldr r0, PPC_BASE
+ ldr r1, [r0, #PPAR]
+ orr r1, r1, #1<<12
+ str r1, [r0, #PPAR]
+
+uart1: ldr r0, UART1_BASE
+
+uart_init: ldr r1, [r0, #UTSR1]
+ tst r1, #1<<0 @ TBY
+ bne 1b
+ mov r1, #0
+ str r1, [r0, #UTCR3]
+ mov r1, #0x08 @ 8N1
+ str r1, [r0, #UTCR0]
+ mov r1, #BAUD_DIV
+ str r1, [r0, #UTCR2]
+ mov r1, r1, lsr #8
+ str r1, [r0, #UTCR1]
+ mov r1, #0x03 @ RXE + TXE
+ str r1, [r0, #UTCR3]
+ mov r1, #0xff @ flush status reg
+ str r1, [r0, #UTSR0]
+skip_uart:
+out: mov pc, lr
+
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 7e7e337b6..95c94d666 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -28,8 +28,7 @@ mainmenu_option next_comment
comment 'System Type'
choice 'ARM system type' \
- "Archimedes CONFIG_ARCH_ARC \
- A5000 CONFIG_ARCH_A5K \
+ "Archimedes/A5000 CONFIG_ARCH_ARCA5K \
Co-EBSA285 CONFIG_ARCH_CO285 \
EBSA-110 CONFIG_ARCH_EBSA110 \
FootBridge CONFIG_ARCH_FOOTBRIDGE \
@@ -40,6 +39,14 @@ choice 'ARM system type' \
# Cirrus CL-PS7500FE CONFIG_ARCH_CLPS7500 \
# LinkUp-L7200 CONFIG_ARCH_L7200
+if [ "$CONFIG_ARCH_ARCA5K" = "y" ]; then
+ # These architectures will be combined. However, until this
+ # is complete... Note that the ARC will take precidence over
+ # A5K
+ comment 'Archimedes/A5000 Implementations (select only ONE)'
+ bool ' Archimedes support' CONFIG_ARCH_ARC
+ bool ' A5000 support' CONFIG_ARCH_A5K
+fi
if [ "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then
comment 'Footbridge Implementations'
bool ' CATS support' CONFIG_ARCH_CATS
@@ -55,7 +62,7 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
bool ' Include support for Neponset' CONFIG_ASSABET_NEPONSET
fi
bool ' Include support for Brutus' CONFIG_SA1100_BRUTUS
- bool ' Include support for Compaq iPAQ 3600 (Bitsy)' CONFIG_SA1100_BITSY
+ bool ' Include support for Compaq iPAQ H3600 (Bitsy)' CONFIG_SA1100_BITSY
# bool ' Include support for Empeg' CONFIG_SA1100_EMPEG
# bool ' Include support for Itsy' CONFIG_SA1100_ITSY
bool ' Include support for LART' CONFIG_SA1100_LART
@@ -68,8 +75,7 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
fi
# Figure out whether this system uses 26-bit or 32-bit CPUs.
-if [ "$CONFIG_ARCH_ARC" = "y" -o \
- "$CONFIG_ARCH_A5K" = "y" ]; then
+if [ "$CONFIG_ARCH_ARCA5K" = "y" ]; then
define_bool CONFIG_CPU_32 n
define_bool CONFIG_CPU_26 y
bool '2MB physical memory' CONFIG_PAGESIZE_16
@@ -94,7 +100,7 @@ if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
define_bool CONFIG_CPU_SA110 y
fi
if [ "$CONFIG_ARCH_CLPS7500" = "y" ]; then
- define_bool CONFIG_CPU_32v4 y
+ define_bool CONFIG_CPU_32v3 y
define_bool CONFIG_CPU_ARM7 y
fi
if [ "$CONFIG_ARCH_L7200" = "y" ]; then
@@ -107,8 +113,7 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
fi
# Select various configuration options depending on the machine type
-if [ "$CONFIG_ARCH_ARC" = "y" -o \
- "$CONFIG_ARCH_A5K" = "y" -o \
+if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
"$CONFIG_ARCH_RPC" = "y" ]; then
define_bool CONFIG_ARCH_ACORN y
else
@@ -154,9 +159,8 @@ else
define_bool CONFIG_PCI n
fi
-if [ "$CONFIG_ARCH_CATS" = "y" -o \
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_NETWINDER" = "y" ]; then
+if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
+ "$CONFIG_ARCH_SHARK" = "y" ]; then
define_bool CONFIG_ISA y
define_bool CONFIG_ISA_DMA y
else
@@ -185,6 +189,11 @@ choice 'Kernel core (/proc/kcore) format' \
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Power Management support' CONFIG_PM
+fi
+
if [ "$CONFIG_CPU_32" = "y" ]; then
tristate 'RISC OS personality' CONFIG_ARTHUR
fi
@@ -219,9 +228,8 @@ fi
endmenu
source drivers/parport/Config.in
-
+source drivers/mtd/Config.in
source drivers/pnp/Config.in
-
source drivers/block/Config.in
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
@@ -268,8 +276,6 @@ if [ "$CONFIG_SCSI" != "n" ]; then
fi
endmenu
-source drivers/mtd/Config.in
-
source drivers/ieee1394/Config.in
source drivers/i2o/Config.in
@@ -328,7 +334,10 @@ source drivers/usb/Config.in
mainmenu_option next_comment
comment 'Kernel hacking'
-bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
+# Always compile kernel with framepointer (until 2.4 real comes out)
+# Bug reports aren't much use without this.
+#bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
+define_bool CONFIG_FRAME_POINTER y
bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS
bool 'Verbose user fault messages' CONFIG_DEBUG_USER
bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7662f42ef..62c0ca60e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -8,38 +8,32 @@
HEAD_OBJ = head-$(PROCESSOR).o
ENTRY_OBJ = entry-$(PROCESSOR).o
-ifeq ($(CONFIG_ISA_DMA),y)
- ISA_DMA_OBJS += dma-isa.o
-endif
-
O_OBJS_arc = dma-arc.o oldlatches.o
-O_OBJS_a5k = dma-a5k.o
O_OBJS_rpc = dma-rpc.o
-O_OBJS_ebsa110 = dma-dummy.o
-O_OBJS_footbridge = dma.o dma-footbridge.o $(ISA_DMA_OBJS) hw-footbridge.o isa.o
-O_OBJS_clps7500 = dma-dummy.o
-O_OBJS_nexuspci = dma-dummy.o
-O_OBJS_sa1100 = dma-dummy.o hw-sa1100.o
-O_OBJS_l7200 = dma-dummy.o fiq.o
+O_OBJS_footbridge = dma-footbridge.o hw-footbridge.o isa.o
+O_OBJS_sa1100 = hw-sa1100.o
+O_OBJS_l7200 = fiq.o
O_TARGET := kernel.o
# Object file lists.
-obj-y := arch.o $(ENTRY_OBJ) irq.o process.o ptrace.o \
+obj-y := arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o \
semaphore.o setup.o signal.o sys_arm.o time.o \
traps.o $(O_OBJS_$(MACHINE))
obj-m :=
obj-n :=
obj- :=
-export-objs := armksyms.o dma.o ecard.o hw-footbridge.o hw-sa1100.o leds-$(MACHINE).o
+export-objs := armksyms.o dma.o ecard.o hw-footbridge.o \
+ hw-sa1100.o leds-$(MACHINE).o oldlatches.o
-obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o fiq.o time-acorn.o
+obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o
obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o
obj-$(CONFIG_MODULES) += armksyms.o
obj-$(CONFIG_LEDS) += leds-$(MACHINE).o
obj-$(CONFIG_ARTHUR) += arthur.o
+obj-$(CONFIG_ISA_DMA) += dma-isa.o
ifeq ($(MACHINE),nexuspci)
obj-$(CONFIG_PCI) += plx9080.o
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
index 8b67943ce..0ce6d9d21 100644
--- a/arch/arm/kernel/arch.c
+++ b/arch/arm/kernel/arch.c
@@ -8,6 +8,8 @@
*/
#include <linux/config.h>
#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
#include <linux/init.h>
#include <asm/dec21285.h>
@@ -134,8 +136,10 @@ fixup_netwinder(struct machine_desc *desc, struct param_struct *params,
isapnp_disable = 1;
#endif
- if (params->u1.s.nr_pages != 0x2000 &&
- params->u1.s.nr_pages != 0x4000) {
+ if (params->u1.s.nr_pages != 0x02000 &&
+ params->u1.s.nr_pages != 0x04000 &&
+ params->u1.s.nr_pages != 0x08000 &&
+ params->u1.s.nr_pages != 0x10000) {
printk(KERN_WARNING "Warning: bad NeTTrom parameters "
"detected, using defaults\n");
@@ -207,6 +211,14 @@ MACHINE_END
#ifdef CONFIG_ARCH_SA1100
+static void victor_power_off(void)
+{
+ /* switch off power supply */
+ mdelay(2000);
+ GPCR = GPIO_GPIO23;
+ while (1);
+}
+
extern void select_sa1100_io_desc(void);
#define SET_BANK(__nr,__start,__size) \
mi->bank[__nr].start = (__start), \
@@ -219,9 +231,31 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
select_sa1100_io_desc();
if (machine_is_assabet()) {
+ /*
+ * On Assabet, we must probe for the Neponset board *before*
+ * paging_init() has occured to actually determine the amount
+ * of RAM available.
+ */
+ extern void map_sa1100_gpio_regs(void);
+ extern void get_assabet_scr(void);
+ map_sa1100_gpio_regs();
+ get_assabet_scr();
+
SET_BANK( 0, 0xc0000000, 32*1024*1024 );
mi->nr_banks = 1;
+ if (machine_has_neponset()) {
+ printk("Neponset expansion board detected\n");
+ /*
+ * Note that Neponset RAM is slower...
+ * and still untested.
+ * This would be a candidate for
+ * _real_ NUMA support.
+ */
+ //SET_BANK( 1, 0xd0000000, 32*1024*1024 );
+ //mi->nr_banks = 2;
+ }
+
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
setup_ramdisk( 1, 0, 0, 8192 );
setup_initrd( 0xc0800000, 3*1024*1024 );
@@ -297,6 +331,8 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
/* power off if any problem */
strcat( *cmdline, " panic=1" );
+
+ pm_power_off = victor_power_off;
}
}
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 5ac0743be..6723291df 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -8,13 +8,14 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
#include <linux/vt_kern.h>
#include <asm/byteorder.h>
#include <asm/elf.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/dma.h>
#include <asm/pgalloc.h>
#include <asm/proc-fns.h>
#include <asm/processor.h>
@@ -28,9 +29,6 @@ extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
extern void inswb(unsigned int port, void *to, int len);
extern void outswb(unsigned int port, const void *to, int len);
-extern unsigned int local_bh_count[NR_CPUS];
-extern unsigned int local_irq_count[NR_CPUS];
-
extern void __bad_xchg(volatile void *ptr, int size);
/*
@@ -68,6 +66,7 @@ extern void __umodsi3(void);
extern void ret_from_exception(void);
extern void fpundefinstr(void);
extern void fp_enter(void);
+
#define EXPORT_SYMBOL_ALIAS(sym,orig) \
const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \
__MODULE_STRING(##sym##); \
@@ -108,6 +107,8 @@ EXPORT_SYMBOL(__bad_xchg);
EXPORT_SYMBOL(__readwrite_bug);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(pm_idle);
+EXPORT_SYMBOL(pm_power_off);
/* processor dependencies */
#ifdef MULTI_CPU
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a077f13b9..b2c644198 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -365,7 +365,7 @@ static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin)
/* ebsa285 host-specific stuff */
#ifdef CONFIG_ARCH_EBSA285
-static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
+static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin)
{
diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c
deleted file mode 100644
index d79013af2..000000000
--- a/arch/arm/kernel/dma-a5k.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/kernel/dma-a5k.c
- *
- * Copyright (C) 1998 Russell King
- *
- * DMA functions specific to A5000 architecture
- */
-#include <linux/sched.h>
-#include <linux/init.h>
-
-#include <asm/dma.h>
-#include <asm/fiq.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-
-#include "dma.h"
-
-static struct fiq_handler fh = {
- name: "floppydma"
-};
-
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
-{
- if (channel == DMA_VIRTUAL_FLOPPY)
- return 0;
- else
- return -EINVAL;
-}
-
-void arch_free_dma(dmach_t channel, dma_t *dma)
-{
- if (channel != DMA_VIRTUAL_FLOPPY)
- printk("arch_free_dma: invalid channel %d\n", channel);
-}
-
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
-{
- if (channel != DMA_VIRTUAL_FLOPPY)
- printk("arch_dma_count: invalid channel %d\n", channel);
- else {
- struct pt_regs regs;
- get_fiq_regs(&regs);
- return regs.ARM_r9;
- }
- return 0;
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
-{
- if (channel != DMA_VIRTUAL_FLOPPY)
- printk("arch_enable_dma: invalid channel %d\n", channel);
- else {
- struct pt_regs regs;
- void *fiqhandler_start;
- unsigned int fiqhandler_length;
- extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
- unsigned long port);
-
- if (dma->dma_mode == DMA_MODE_READ) {
- extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
- fiqhandler_start = &floppy_fiqin_start;
- fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
- } else {
- extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
- fiqhandler_start = &floppy_fiqout_start;
- fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
- }
- if (claim_fiq(&fh)) {
- printk("floppydma: couldn't claim FIQ.\n");
- return;
- }
- memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
- regs.ARM_r9 = dma->buf.length;
- regs.ARM_r10 = __bus_to_virt(dma->buf.address);
- regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
- set_fiq_regs(&regs);
- enable_irq(dma->dma_irq);
- }
-}
-
-void arch_disable_dma(dmach_t channel, dma_t *dma)
-{
- if (channel != DMA_VIRTUAL_FLOPPY)
- printk("arch_disable_dma: invalid channel %d\n", channel);
- else {
- disable_irq(dma->dma_irq);
- release_fiq(&fh);
- }
-}
-
-int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
-{
- return 0;
-}
-
-void __init arch_dma_init(dma_t *dma)
-{
- dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
-}
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c
index 53ef12b1c..5a2f93b67 100644
--- a/arch/arm/kernel/dma-arc.c
+++ b/arch/arm/kernel/dma-arc.c
@@ -3,148 +3,200 @@
*
* Copyright (C) 1998-1999 Dave Gilbert / Russell King
*
- * DMA functions specific to Archimedes architecture
+ * DMA functions specific to Archimedes and A5000 architecture
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <asm/dma.h>
+#include <asm/fiq.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include "dma.h"
-#define DEBUG
+#define DPRINTK(x...) printk(KERN_DEBUG x)
-int arch_request_dma(dmach_t channel, dma_t *dma, const char * dev_id)
+#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
+static void arc_floppy_data_enable_dma(dmach_t channel, dma_t *dma)
{
- printk("arch_request_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
- if (channel == DMA_VIRTUAL_FLOPPY0 ||
- channel == DMA_VIRTUAL_FLOPPY1)
- return 0;
- else
- return -EINVAL;
-}
-
-void arch_free_dma(dmach_t channel, dma_t *dma)
-{
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
-{
- printk("arch_enable_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
- switch (channel) {
-#ifdef CONFIG_BLK_DEV_FD1772
- case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
- switch (dma->dma_mode) {
- case DMA_MODE_READ: /* read */
- {
- extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
- extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
- unsigned long flags;
-#ifdef DEBUG
- printk("enable_dma fdc1772 data read\n");
-#endif
- save_flags(flags);
- cliIF();
+ DPRINTK("arc_floppy_data_enable_dma\n");
+ switch (dma->dma_mode) {
+ case DMA_MODE_READ: { /* read */
+ extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
+ extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
+ unsigned long flags;
+ DPRINTK("enable_dma fdc1772 data read\n");
+ save_flags(flags);
+ cliIF();
- memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
- &fdc1772_dma_read_end - &fdc1772_dma_read);
- fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
- enable_irq (64);
- restore_flags(flags);
- }
- break;
-
- case DMA_MODE_WRITE: /* write */
- {
- extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
- extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
- unsigned long flags;
-
-#ifdef DEBUG
- printk("enable_dma fdc1772 data write\n");
-#endif
- save_flags(flags);
- cliIF();
- memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
- &fdc1772_dma_write_end - &fdc1772_dma_write);
- fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
- enable_irq (64);
-
- restore_flags(flags);
- }
- break;
- default:
- printk ("enable_dma: dma%d not initialised\n", channel);
- return;
- }
- }
- break;
+ memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
+ &fdc1772_dma_read_end - &fdc1772_dma_read);
+ fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
+ enable_irq (64);
+ restore_flags(flags);
+ }
+ break;
- case DMA_VIRTUAL_FLOPPY1: { /* Command end FIQ - actually just sets a flag */
- /* Need to build a branch at the FIQ address */
- extern void fdc1772_comendhandler(void);
+ case DMA_MODE_WRITE: { /* write */
+ extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
+ extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
-
- /*printk("enable_dma fdc1772 command end FIQ\n");*/
+ DPRINTK("enable_dma fdc1772 data write\n");
save_flags(flags);
cliIF();
-
- *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */
+ memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
+ &fdc1772_dma_write_end - &fdc1772_dma_write);
+ fdc1772_setupdma(dma->buf.length, __bus_to_virt(dma->buf.address)); /* Sets data pointer up */
+ enable_irq (64);
restore_flags(flags);
- }
- break;
-#endif
+ }
+ break;
+ default:
+ printk ("enable_dma: dma%d not initialised\n", channel);
}
}
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+static int arc_floppy_data_get_dma_residue(dmach_t channel, dma_t *dma)
{
- switch (channel) {
-#ifdef CONFIG_BLK_DEV_FD1772
- case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
- extern unsigned int fdc1772_bytestogo;
+ extern unsigned int fdc1772_bytestogo;
+
+ /* 10/1/1999 DAG - I presume its the number of bytes left? */
+ return fdc1772_bytestogo;
+}
+
+static void arc_floppy_cmdend_enable_dma(dmach_t channel, dma_t *dma)
+{
+ /* Need to build a branch at the FIQ address */
+ extern void fdc1772_comendhandler(void);
+ unsigned long flags;
+
+ DPRINTK("arc_floppy_cmdend_enable_dma\n");
+ /*printk("enable_dma fdc1772 command end FIQ\n");*/
+ save_flags(flags);
+ cliIF();
+
+ /* B fdc1772_comendhandler */
+ *((unsigned int *)0x1c)=0xea000000 |
+ (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4);
- /* 10/1/1999 DAG - I presume its the number of bytes left? */
- return fdc1772_bytestogo;
- };
- break;
+ restore_flags(flags);
+}
+
+static int arc_floppy_cmdend_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ /* 10/1/1999 DAG - Presume whether there is an outstanding command? */
+ extern unsigned int fdc1772_fdc_int_done;
- case DMA_VIRTUAL_FLOPPY1: { /* Command completed */
- /* 10/1/1999 DAG - Presume whether there is an outstanding command? */
- extern unsigned int fdc1772_fdc_int_done;
+ * Explicit! If the int done is 0 then 1 int to go */
+ return (fdc1772_fdc_int_done==0)?1:0;
+}
- return (fdc1772_fdc_int_done==0)?1:0; /* Explicit! If the int done is 0 then 1 int to go */
- };
- break;
+static void arc_disable_dma(dmach_t channel, dma_t *dma)
+{
+ disable_irq(dma->dma_irq);
+}
+static struct dma_ops arc_floppy_data_dma_ops = {
+ type: "FIQDMA",
+ enable: arc_floppy_data_enable_dma,
+ disable: arc_disable_dma,
+ residue: arc_floppy_data_get_dma_residue,
+};
+
+static struct dma_ops arc_floppy_cmdend_dma_ops = {
+ type: "FIQCMD",
+ enable: arc_floppy_cmdend_enable_dma,
+ disable: arc_disable_dma,
+ residue: arc_floppy_cmdend_get_dma_residue,
+};
#endif
- default:
- printk("dma-arc.c:arch_get_dma_residue called with unknown/unconfigured DMA channel\n");
- return 0;
- };
+#ifdef CONFIG_ARCH_A5K
+static struct fiq_handler fh = {
+ name: "floppydata"
+};
+
+static int a5k_floppy_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+ struct pt_regs regs;
+ get_fiq_regs(&regs);
+ return regs.ARM_r9;
+}
+
+static void a5k_floppy_enable_dma(dmach_t channel, dma_t *dma)
+{
+ struct pt_regs regs;
+ void *fiqhandler_start;
+ unsigned int fiqhandler_length;
+ extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
+ unsigned long port);
+
+ if (dma->dma_mode == DMA_MODE_READ) {
+ extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
+ fiqhandler_start = &floppy_fiqin_start;
+ fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
+ } else {
+ extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
+ fiqhandler_start = &floppy_fiqout_start;
+ fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
+ }
+ if (claim_fiq(&fh)) {
+ printk("floppydma: couldn't claim FIQ.\n");
+ return;
+ }
+ memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
+ regs.ARM_r9 = dma->buf.length;
+ regs.ARM_r10 = __bus_to_virt(dma->buf.address);
+ regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
+ set_fiq_regs(&regs);
+ enable_irq(dma->dma_irq);
}
-void arch_disable_dma(dmach_t channel, dma_t *dma)
+static void a5k_floppy_disable_dma(dmach_t channel, dma_t *dma)
{
- if (channel != DMA_VIRTUAL_FLOPPY0 &&
- channel != DMA_VIRTUAL_FLOPPY1)
- printk("arch_disable_dma: invalid channel %d\n", channel);
- else
- disable_irq(dma->dma_irq);
+ disable_irq(dma->dma_irq);
+ release_fiq(&fh);
}
-int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
+static struct dma_ops a5k_floppy_dma_ops = {
+ type: "FIQDMA",
+ enable: a5k_floppy_enable_dma,
+ disable: a5k_floppy_disable_dma,
+ residue: a5k_floppy_get_dma_residue,
+};
+#endif
+
+/*
+ * This is virtual DMA - we don't need anything here
+ */
+static int sound_enable_disable_dma(dmach_t channel, dma_t *dma)
{
- return 0;
}
+static struct dma_ops sound_dma_ops = {
+ type: "VIRTUAL",
+ enable: sound_enable_disable_dma,
+ disable: sound_enable_disable_dma,
+};
+
void __init arch_dma_init(dma_t *dma)
{
- dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
- dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
+#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
+ if (machine_is_arc()) {
+ dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+ dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops;
+ dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
+ dma[DMA_VIRTUAL_FLOPPY1].d_ops = &arc_floppy_cmdend_dma_ops;
+ }
+#endif
+#ifdef CONFIG_ARCH_A5K
+ if (machine_is_a5k()) {
+ dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
+ dma[DMA_VIRTUAL_FLOPPY].d_ops = &a5k_floppy_dma_ops;
+ }
+#endif
+ dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
}
diff --git a/arch/arm/kernel/dma-dummy.c b/arch/arm/kernel/dma-dummy.c
deleted file mode 100644
index ebb9755c1..000000000
--- a/arch/arm/kernel/dma-dummy.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/kernel/dma-dummy.c
- *
- * Copyright (C) 1998 Philip Blundell
- * Copyright (c) 1998 Russell King
- *
- * Dummy DMA functions
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED;
-
-int request_dma(int channel, const char *device_id)
-{
- return -EINVAL;
-}
-
-int no_dma(void)
-{
- return 0;
-}
-
-#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a)
-GLOBAL_ALIAS(disable_dma, no_dma);
-GLOBAL_ALIAS(enable_dma, no_dma);
-GLOBAL_ALIAS(free_dma, no_dma);
-GLOBAL_ALIAS(get_dma_residue, no_dma);
-GLOBAL_ALIAS(get_dma_list, no_dma);
-GLOBAL_ALIAS(set_dma_mode, no_dma);
-GLOBAL_ALIAS(set_dma_count, no_dma);
-GLOBAL_ALIAS(set_dma_addr, no_dma);
-GLOBAL_ALIAS(init_dma, no_dma);
diff --git a/arch/arm/kernel/dma-footbridge.c b/arch/arm/kernel/dma-footbridge.c
index 1d2ef26c4..b9d4b62fa 100644
--- a/arch/arm/kernel/dma-footbridge.c
+++ b/arch/arm/kernel/dma-footbridge.c
@@ -15,94 +15,44 @@
#include <linux/sched.h>
#include <linux/init.h>
+#include <asm/dec21285.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "dma.h"
-#include "dma-isa.h"
-#ifdef CONFIG_ISA_DMA
-static int has_isa_dma;
-#else
-#define has_isa_dma 0
-#endif
+extern void isa_init_dma(dma_t *dma);
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+#if 0
+static int fb_dma_request(dmach_t channel, dma_t *dma)
{
- switch (channel) {
- case _DC21285_DMA(0):
- case _DC21285_DMA(1): /* 21285 internal channels */
- return 0;
-
- case _ISA_DMA(0) ... _ISA_DMA(7):
- if (has_isa_dma)
- return isa_request_dma(channel - _ISA_DMA(0), dma, dev_name);
- }
-
return -EINVAL;
}
-void arch_free_dma(dmach_t channel, dma_t *dma)
-{
- /* nothing to do */
-}
-
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
-{
- int residue = 0;
-
- switch (channel) {
- case _DC21285_DMA(0):
- case _DC21285_DMA(1):
- break;
-
- case _ISA_DMA(0) ... _ISA_DMA(7):
- if (has_isa_dma)
- residue = isa_get_dma_residue(channel - _ISA_DMA(0), dma);
- }
- return residue;
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
+static void fb_dma_enable(dmach_t channel, dma_t *dma)
{
- switch (channel) {
- case _DC21285_DMA(0):
- case _DC21285_DMA(1):
- /*
- * Not yet implemented
- */
- break;
-
- case _ISA_DMA(0) ... _ISA_DMA(7):
- if (has_isa_dma)
- isa_enable_dma(channel - _ISA_DMA(0), dma);
- }
}
-void arch_disable_dma(dmach_t channel, dma_t *dma)
+static void fb_dma_disable(dmach_t channel, dma_t *dma)
{
- switch (channel) {
- case _DC21285_DMA(0):
- case _DC21285_DMA(1):
- /*
- * Not yet implemented
- */
- break;
-
- case _ISA_DMA(0) ... _ISA_DMA(7):
- if (has_isa_dma)
- isa_disable_dma(channel - _ISA_DMA(0), dma);
- }
}
-int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
-{
- return 0;
-}
+static struct dma_ops fb_dma_ops = {
+ type: "fb",
+ request: fb_dma_request,
+ enable: fb_dma_enable,
+ disable: fb_dma_disable,
+};
+#endif
void __init arch_dma_init(dma_t *dma)
{
+#if 0
+ dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
+ dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops;
+#endif
#ifdef CONFIG_ISA_DMA
- has_isa_dma = isa_init_dma();
+ if (footbridge_cfn_mode())
+ isa_init_dma(dma + _ISA_DMA(0));
#endif
}
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 74967a055..f144d0436 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -1,12 +1,13 @@
/*
* arch/arm/kernel/dma-isa.c: ISA DMA primitives
*
- * Copyright (C) Russell King
+ * Copyright (C) 1999-2000 Russell King
*
* Taken from various sources, including:
* linux/include/asm/dma.h: Defines for using and allocating dma channels.
* Written by Hennus Bergman, 1992.
- * High DMA channel support & info by Hannu Savolainen and John Boyd, Nov. 1992.
+ * High DMA channel support & info by Hannu Savolainen and John Boyd,
+ * Nov. 1992.
* arch/arm/kernel/dma-ebsa285.c
* Copyright (C) 1998 Phil Blundell
*/
@@ -18,7 +19,6 @@
#include <asm/io.h>
#include "dma.h"
-#include "dma-isa.h"
#define ISA_DMA_MODE_READ 0x44
#define ISA_DMA_MODE_WRITE 0x48
@@ -45,17 +45,7 @@ static unsigned int isa_dma_port[8][7] = {
{ 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce }
};
-int isa_request_dma(int channel, dma_t *dma, const char *dev_name)
-{
- return 0;
-}
-
-void isa_free_dma(int channel, dma_t *dma)
-{
- /* nothing to do */
-}
-
-int isa_get_dma_residue(int channel, dma_t *dma)
+static int isa_get_dma_residue(dmach_t channel, dma_t *dma)
{
unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
int count;
@@ -66,7 +56,7 @@ int isa_get_dma_residue(int channel, dma_t *dma)
return channel < 4 ? count : (count << 1);
}
-void isa_enable_dma(int channel, dma_t *dma)
+static void isa_enable_dma(dmach_t channel, dma_t *dma)
{
if (dma->invalid) {
unsigned long address, length;
@@ -121,11 +111,18 @@ void isa_enable_dma(int channel, dma_t *dma)
outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
}
-void isa_disable_dma(int channel, dma_t *dma)
+static void isa_disable_dma(dmach_t channel, dma_t *dma)
{
outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
}
+static struct dma_ops isa_dma_ops = {
+ type: "ISA",
+ enable: isa_enable_dma,
+ disable: isa_disable_dma,
+ residue: isa_get_dma_residue,
+};
+
static struct resource dma_resources[] = {
{ "dma1", 0x0000, 0x000f },
{ "dma low page", 0x0080, 0x008f },
@@ -133,7 +130,7 @@ static struct resource dma_resources[] = {
{ "dma high page", 0x0480, 0x048f }
};
-int __init isa_init_dma(void)
+void __init isa_init_dma(dma_t *dma)
{
int dmac_found;
@@ -148,8 +145,10 @@ int __init isa_init_dma(void)
if (dmac_found) {
int channel, i;
- for (channel = 0; channel < 8; channel++)
+ for (channel = 0; channel < 8; channel++) {
+ dma[channel].d_ops = &isa_dma_ops;
isa_disable_dma(channel, NULL);
+ }
outb(0x40, 0x0b);
outb(0x41, 0x0b);
@@ -167,10 +166,9 @@ int __init isa_init_dma(void)
outb(0x10, 0xd0);
/*
- * Is this correct? According to
- * my documentation, it doesn't
- * appear to be. It should be
- * outb(0x3f, 0x40b); outb(0x3f, 0x4d6);
+ * Is this correct? According to my documentation, it
+ * doesn't appear to be. It should be:
+ * outb(0x3f, 0x40b); outb(0x3f, 0x4d6);
*/
outb(0x30, 0x40b);
outb(0x31, 0x40b);
@@ -185,6 +183,4 @@ int __init isa_init_dma(void)
for (i = 0; i < sizeof(dma_resources) / sizeof(dma_resources[0]); i++)
request_resource(&ioport_resource, dma_resources + i);
}
-
- return dmac_found;
}
diff --git a/arch/arm/kernel/dma-isa.h b/arch/arm/kernel/dma-isa.h
deleted file mode 100644
index 2640f6c3a..000000000
--- a/arch/arm/kernel/dma-isa.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Request an ISA DMA channel
- */
-int isa_request_dma(int channel, dma_t *dma, const char *dev_name);
-
-/*
- * Free an ISA DMA channel
- */
-void isa_free_dma(int channel, dma_t *dma);
-
-/*
- * Get ISA DMA channel residue
- */
-int isa_get_dma_residue(int channel, dma_t *dma);
-
-/*
- * Enable (and set up) an ISA DMA channel
- */
-void isa_enable_dma(int channel, dma_t *dma);
-
-/*
- * Disable an ISA DMA channel
- */
-void isa_disable_dma(int channel, dma_t *dma);
-
-/*
- * Initialise DMA
- */
-int isa_init_dma(void);
diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c
index f4bc97f1d..35e3c35a3 100644
--- a/arch/arm/kernel/dma-rpc.c
+++ b/arch/arm/kernel/dma-rpc.c
@@ -21,10 +21,6 @@
#include "dma.h"
-static struct fiq_handler fh = {
- name: "floppydma"
-};
-
#if 0
typedef enum {
dma_size_8 = 1,
@@ -51,7 +47,7 @@ typedef struct {
#define state_wait_a 1
#define state_wait_b 2
-static void arch_get_next_sg(dmasg_t *sg, dma_t *dma)
+static void iomd_get_next_sg(dmasg_t *sg, dma_t *dma)
{
unsigned long end, offset, flags = 0;
@@ -90,19 +86,19 @@ static void arch_get_next_sg(dmasg_t *sg, dma_t *dma)
sg->length |= flags;
}
-static inline void arch_setup_dma_a(dmasg_t *sg, dma_t *dma)
+static inline void iomd_setup_dma_a(dmasg_t *sg, dma_t *dma)
{
outl_t(sg->address, dma->dma_base + CURA);
outl_t(sg->length, dma->dma_base + ENDA);
}
-static inline void arch_setup_dma_b(dmasg_t *sg, dma_t *dma)
+static inline void iomd_setup_dma_b(dmasg_t *sg, dma_t *dma)
{
outl_t(sg->address, dma->dma_base + CURB);
outl_t(sg->length, dma->dma_base + ENDB);
}
-static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
+static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
{
dma_t *dma = (dma_t *)dev_id;
unsigned int status = 0, no_buffer = dma->sg == NULL;
@@ -110,26 +106,26 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
do {
switch (dma->state) {
case state_prog_a:
- arch_get_next_sg(&dma->cur_sg, dma);
- arch_setup_dma_a(&dma->cur_sg, dma);
+ iomd_get_next_sg(&dma->cur_sg, dma);
+ iomd_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
case state_wait_a:
status = inb_t(dma->dma_base + ST);
switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
case DMA_ST_OFL|DMA_ST_INT:
- arch_get_next_sg(&dma->cur_sg, dma);
- arch_setup_dma_a(&dma->cur_sg, dma);
+ iomd_get_next_sg(&dma->cur_sg, dma);
+ iomd_setup_dma_a(&dma->cur_sg, dma);
break;
case DMA_ST_INT:
- arch_get_next_sg(&dma->cur_sg, dma);
- arch_setup_dma_b(&dma->cur_sg, dma);
+ iomd_get_next_sg(&dma->cur_sg, dma);
+ iomd_setup_dma_b(&dma->cur_sg, dma);
dma->state = state_wait_b;
break;
case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
- arch_setup_dma_b(&dma->cur_sg, dma);
+ iomd_setup_dma_b(&dma->cur_sg, dma);
dma->state = state_wait_b;
break;
}
@@ -139,18 +135,18 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
status = inb_t(dma->dma_base + ST);
switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
- arch_get_next_sg(&dma->cur_sg, dma);
- arch_setup_dma_b(&dma->cur_sg, dma);
+ iomd_get_next_sg(&dma->cur_sg, dma);
+ iomd_setup_dma_b(&dma->cur_sg, dma);
break;
case DMA_ST_INT|DMA_ST_AB:
- arch_get_next_sg(&dma->cur_sg, dma);
- arch_setup_dma_a(&dma->cur_sg, dma);
+ iomd_get_next_sg(&dma->cur_sg, dma);
+ iomd_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
break;
case DMA_ST_OFL|DMA_ST_INT:
- arch_setup_dma_a(&dma->cur_sg, dma);
+ iomd_setup_dma_a(&dma->cur_sg, dma);
dma->state = state_wait_a;
break;
}
@@ -162,167 +158,56 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
disable_irq(irq);
}
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+static int iomd_request_dma(dmach_t channel, dma_t *dma)
{
unsigned long flags;
int ret;
- switch (channel) {
- case DMA_0:
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- save_flags_cli(flags);
- ret = request_irq(dma->dma_irq, arch_dma_handle,
- SA_INTERRUPT, dev_name, dma);
- if (!ret)
- disable_irq(dma->dma_irq);
- restore_flags(flags);
- break;
-
- case DMA_VIRTUAL_FLOPPY:
- case DMA_VIRTUAL_SOUND:
- ret = 0;
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
+ save_flags_cli(flags);
+ ret = request_irq(dma->dma_irq, iomd_dma_handle,
+ SA_INTERRUPT, dma->device_id, dma);
+ if (!ret)
+ disable_irq(dma->dma_irq);
+ restore_flags(flags);
return ret;
}
-void arch_free_dma(dmach_t channel, dma_t *dma)
+static void iomd_free_dma(dmach_t channel, dma_t *dma)
{
- switch (channel) {
- case DMA_0:
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- free_irq(dma->dma_irq, dma);
- break;
-
- default:
- break;
- }
+ free_irq(dma->dma_irq, dma);
}
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
-{
- int residue = 0;
-
- switch (channel) {
- case DMA_0: /* Physical DMA channels */
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- break;
-
- case DMA_VIRTUAL_FLOPPY: {
- struct pt_regs regs;
- get_fiq_regs(&regs);
- return regs.ARM_r9;
- }
- break;
- }
- return residue;
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
+static void iomd_enable_dma(dmach_t channel, dma_t *dma)
{
unsigned long dma_base = dma->dma_base;
- unsigned int ctrl;
-
- switch (channel) {
- case DMA_0: /* Physical DMA channels */
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- ctrl = TRANSFER_SIZE | DMA_CR_E;
+ unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
- if (dma->invalid) {
- dma->invalid = 0;
+ if (dma->invalid) {
+ dma->invalid = 0;
- outb_t(DMA_CR_C, dma_base + CR);
- dma->state = state_prog_a;
- }
+ outb_t(DMA_CR_C, dma_base + CR);
+ dma->state = state_prog_a;
+ }
- if (dma->dma_mode == DMA_MODE_READ)
- ctrl |= DMA_CR_D;
+ if (dma->dma_mode == DMA_MODE_READ)
+ ctrl |= DMA_CR_D;
- outb_t(ctrl, dma_base + CR);
- enable_irq(dma->dma_irq);
- break;
-
- case DMA_VIRTUAL_FLOPPY: {
- void *fiqhandler_start;
- unsigned int fiqhandler_length;
- struct pt_regs regs;
-
- if (dma->dma_mode == DMA_MODE_READ) {
- extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
- fiqhandler_start = &floppy_fiqin_start;
- fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
- } else {
- extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
- fiqhandler_start = &floppy_fiqout_start;
- fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
- }
-
- regs.ARM_r9 = dma->buf.length;
- regs.ARM_r10 = __bus_to_virt(dma->buf.address);
- regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
-
- if (claim_fiq(&fh)) {
- printk("floppydma: couldn't claim FIQ.\n");
- return;
- }
-
- set_fiq_handler(fiqhandler_start, fiqhandler_length);
- set_fiq_regs(&regs);
- enable_irq(dma->dma_irq);
- }
- break;
-
- default:
- break;
- }
+ outb_t(ctrl, dma_base + CR);
+ enable_irq(dma->dma_irq);
}
-void arch_disable_dma(dmach_t channel, dma_t *dma)
+static void iomd_disable_dma(dmach_t channel, dma_t *dma)
{
unsigned long dma_base = dma->dma_base;
unsigned int ctrl;
- switch (channel) {
- case DMA_0: /* Physical DMA channels */
- case DMA_1:
- case DMA_2:
- case DMA_3:
- case DMA_S0:
- case DMA_S1:
- disable_irq(dma->dma_irq);
- ctrl = inb_t(dma_base + CR);
- outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
- break;
-
- case DMA_VIRTUAL_FLOPPY:
- disable_irq(dma->dma_irq);
- release_fiq(&fh);
- break;
- }
+ disable_irq(dma->dma_irq);
+ ctrl = inb_t(dma_base + CR);
+ outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
}
-int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
+static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
{
int tcr, speed;
@@ -364,6 +249,82 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
return speed;
}
+static struct dma_ops iomd_dma_ops = {
+ type: "IOMD",
+ request: iomd_request_dma,
+ free: iomd_free_dma,
+ enable: iomd_enable_dma,
+ disable: iomd_disable_dma,
+ setspeed: iomd_set_dma_speed,
+};
+
+static struct fiq_handler fh = {
+ name: "floppydma"
+};
+
+static void floppy_enable_dma(dmach_t channel, dma_t *dma)
+{
+ void *fiqhandler_start;
+ unsigned int fiqhandler_length;
+ struct pt_regs regs;
+
+ if (dma->dma_mode == DMA_MODE_READ) {
+ extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
+ fiqhandler_start = &floppy_fiqin_start;
+ fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
+ } else {
+ extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
+ fiqhandler_start = &floppy_fiqout_start;
+ fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
+ }
+
+ regs.ARM_r9 = dma->buf.length;
+ regs.ARM_r10 = __bus_to_virt(dma->buf.address);
+ regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
+
+ if (claim_fiq(&fh)) {
+ printk("floppydma: couldn't claim FIQ.\n");
+ return;
+ }
+
+ set_fiq_handler(fiqhandler_start, fiqhandler_length);
+ set_fiq_regs(&regs);
+ enable_irq(dma->dma_irq);
+}
+
+static void floppy_disable_dma(dmach_t channel, dma_t *dma)
+{
+ disable_irq(dma->dma_irq);
+ release_fiq(&fh);
+}
+
+static int floppy_get_residue(dmach_t channel, dma_t *dma)
+{
+ struct pt_regs regs;
+ get_fiq_regs(&regs);
+ return regs.ARM_r9;
+}
+
+static struct dma_ops floppy_dma_ops = {
+ type: "FIQDMA",
+ enable: floppy_enable_dma,
+ disable: floppy_disable_dma,
+ residue: floppy_get_residue,
+};
+
+/*
+ * This is virtual DMA - we don't need anything here.
+ */
+static int sound_enable_disable_dma(dmach_t channel, dma_t *dma)
+{
+}
+
+static struct dma_ops sound_dma_ops = {
+ type: "VIRTUAL",
+ enable: sound_enable_disable_dma,
+ disable: sound_enable_disable_dma,
+};
+
void __init arch_dma_init(dma_t *dma)
{
outb(0, IOMD_IO0CR);
@@ -373,21 +334,30 @@ void __init arch_dma_init(dma_t *dma)
outb(0xa0, IOMD_DMATCR);
- dma[0].dma_base = ioaddr(IOMD_IO0CURA);
- dma[0].dma_irq = IRQ_DMA0;
- dma[1].dma_base = ioaddr(IOMD_IO1CURA);
- dma[1].dma_irq = IRQ_DMA1;
- dma[2].dma_base = ioaddr(IOMD_IO2CURA);
- dma[2].dma_irq = IRQ_DMA2;
- dma[3].dma_base = ioaddr(IOMD_IO3CURA);
- dma[3].dma_irq = IRQ_DMA3;
- dma[4].dma_base = ioaddr(IOMD_SD0CURA);
- dma[4].dma_irq = IRQ_DMAS0;
- dma[5].dma_base = ioaddr(IOMD_SD1CURA);
- dma[5].dma_irq = IRQ_DMAS1;
- dma[6].dma_irq = 64;
-
- /* Setup DMA channels 2,3 to be for podules
+ dma[DMA_0].dma_base = ioaddr(IOMD_IO0CURA);
+ dma[DMA_0].dma_irq = IRQ_DMA0;
+ dma[DMA_0].d_ops = &iomd_dma_ops;
+ dma[DMA_1].dma_base = ioaddr(IOMD_IO1CURA);
+ dma[DMA_1].dma_irq = IRQ_DMA1;
+ dma[DMA_1].d_ops = &iomd_dma_ops;
+ dma[DMA_2].dma_base = ioaddr(IOMD_IO2CURA);
+ dma[DMA_2].dma_irq = IRQ_DMA2;
+ dma[DMA_2].d_ops = &iomd_dma_ops;
+ dma[DMA_3].dma_base = ioaddr(IOMD_IO3CURA);
+ dma[DMA_3].dma_irq = IRQ_DMA3;
+ dma[DMA_3].d_ops = &iomd_dma_ops;
+ dma[DMA_S0].dma_base = ioaddr(IOMD_SD0CURA);
+ dma[DMA_S0].dma_irq = IRQ_DMAS0;
+ dma[DMA_S0].d_ops = &iomd_dma_ops;
+ dma[DMA_S1].dma_base = ioaddr(IOMD_SD1CURA);
+ dma[DMA_S1].dma_irq = IRQ_DMAS1;
+ dma[DMA_S1].d_ops = &iomd_dma_ops;
+ dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
+ dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops;
+ dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
+
+ /*
+ * Setup DMA channels 2,3 to be for podules
* and channels 0,1 for internal devices
*/
outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index ff8322d34..7ed4c28ca 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -1,130 +1,123 @@
/*
* linux/arch/arm/kernel/dma.c
*
- * Copyright (C) 1995-1998 Russell King
+ * Copyright (C) 1995-2000 Russell King
*
- * Front-end to the DMA handling. You must provide the following
- * architecture-specific routines:
- *
- * int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
- * void arch_free_dma(dmach_t channel, dma_t *dma);
- * void arch_enable_dma(dmach_t channel, dma_t *dma);
- * void arch_disable_dma(dmach_t channel, dma_t *dma);
- * int arch_get_dma_residue(dmach_t channel, dma_t *dma);
- *
- * Moved DMA resource allocation here...
+ * Front-end to the DMA handling. This handles the allocation/freeing
+ * of DMA channels, and provides a unified interface to the machines
+ * DMA facilities.
*/
+#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/sched.h>
-#include <linux/module.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
#include <asm/dma.h>
-
-/* A note on resource allocation:
- *
- * All drivers needing DMA channels, should allocate and release them
- * through the public routines `request_dma()' and `free_dma()'.
- *
- * In order to avoid problems, all processes should allocate resources in
- * the same sequence and release them in the reverse order.
- *
- * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
- * When releasing them, first release the DMA, then release the IRQ.
- * If you don't, you may cause allocation requests to fail unnecessarily.
- * This doesn't really matter now, but it will once we get real semaphores
- * in the kernel.
- */
-
+#include "dma.h"
spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED;
-#include "dma.h"
-
-const char dma_str[] = "%s: dma %d not supported\n";
+#if MAX_DMA_CHANNELS > 0
static dma_t dma_chan[MAX_DMA_CHANNELS];
-/* Get dma list
- * for /proc/dma
+/*
+ * Get dma list for /proc/dma
*/
int get_dma_list(char *buf)
{
- int i, len = 0;
+ dma_t *dma;
+ char *p = buf;
+ int i;
- for (i = 0; i < MAX_DMA_CHANNELS; i++) {
- if (dma_chan[i].lock)
- len += sprintf(buf + len, "%2d: %s\n",
- i, dma_chan[i].device_id);
- }
- return len;
+ for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++)
+ if (dma->lock)
+ p += sprintf(p, "%2d: %14s %s\n", i,
+ dma->d_ops->type, dma->device_id);
+
+ return p - buf;
}
-/* Request DMA channel
+/*
+ * Request DMA channel
*
* On certain platforms, we have to allocate an interrupt as well...
*/
int request_dma(dmach_t channel, const char *device_id)
{
- if (channel < MAX_DMA_CHANNELS) {
- int ret;
-
- if (xchg(&dma_chan[channel].lock, 1) != 0)
- return -EBUSY;
-
- ret = arch_request_dma(channel, &dma_chan[channel], device_id);
- if (!ret) {
- dma_chan[channel].device_id = device_id;
- dma_chan[channel].active = 0;
- dma_chan[channel].invalid = 1;
- } else
- xchg(&dma_chan[channel].lock, 0);
-
- return ret;
- } else {
- printk (KERN_ERR "Trying to allocate DMA%d\n", channel);
- return -EINVAL;
- }
+ dma_t *dma = dma_chan + channel;
+ int ret;
+
+ if (channel >= MAX_DMA_CHANNELS || !dma->d_ops)
+ goto bad_dma;
+
+ if (xchg(&dma->lock, 1) != 0)
+ goto busy;
+
+ dma->device_id = device_id;
+ dma->active = 0;
+ dma->invalid = 1;
+
+ ret = 0;
+ if (dma->d_ops->request)
+ ret = dma->d_ops->request(channel, dma);
+
+ if (ret)
+ xchg(&dma->lock, 0);
+
+ return ret;
+
+bad_dma:
+ printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel);
+ return -EINVAL;
+
+busy:
+ return -EBUSY;
}
-/* Free DMA channel
+/*
+ * Free DMA channel
*
* On certain platforms, we have to free interrupt as well...
*/
void free_dma(dmach_t channel)
{
- if (channel >= MAX_DMA_CHANNELS) {
- printk (KERN_ERR "Trying to free DMA%d\n", channel);
- return;
- }
+ dma_t *dma = dma_chan + channel;
+
+ if (channel >= MAX_DMA_CHANNELS || !dma->d_ops)
+ goto bad_dma;
- if (xchg(&dma_chan[channel].lock, 0) == 0) {
- if (dma_chan[channel].active) {
- printk (KERN_ERR "Freeing active DMA%d\n", channel);
- arch_disable_dma(channel, &dma_chan[channel]);
- dma_chan[channel].active = 0;
- }
+ if (dma->active) {
+ printk(KERN_ERR "dma%d: freeing active DMA\n", channel);
+ dma->d_ops->disable(channel, dma);
+ dma->active = 0;
+ }
- printk (KERN_ERR "Trying to free free DMA%d\n", channel);
+ if (xchg(&dma->lock, 0) != 0) {
+ if (dma->d_ops->free)
+ dma->d_ops->free(channel, dma);
return;
}
- arch_free_dma(channel, &dma_chan[channel]);
+
+ printk(KERN_ERR "dma%d: trying to free free DMA\n", channel);
+ return;
+
+bad_dma:
+ printk(KERN_ERR "dma: trying to free DMA%d\n", channel);
}
/* Set DMA Scatter-Gather list
*/
void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg)
{
- dma_chan[channel].sg = sg;
- dma_chan[channel].sgcount = nr_sg;
- dma_chan[channel].invalid = 1;
+ dma_t *dma = dma_chan + channel;
+
+ dma->sg = sg;
+ dma->sgcount = nr_sg;
+ dma->invalid = 1;
}
/* Set DMA address
@@ -133,15 +126,16 @@ void set_dma_sg (dmach_t channel, dmasg_t *sg, int nr_sg)
*/
void set_dma_addr (dmach_t channel, unsigned long physaddr)
{
- if (dma_chan[channel].active)
- printk(KERN_ERR "set_dma_addr: altering DMA%d"
- " address while DMA active\n",
- channel);
-
- dma_chan[channel].sg = &dma_chan[channel].buf;
- dma_chan[channel].sgcount = 1;
- dma_chan[channel].buf.address = physaddr;
- dma_chan[channel].invalid = 1;
+ dma_t *dma = dma_chan + channel;
+
+ if (dma->active)
+ printk(KERN_ERR "dma%d: altering DMA address while "
+ "DMA active\n", channel);
+
+ dma->sg = &dma->buf;
+ dma->sgcount = 1;
+ dma->buf.address = physaddr;
+ dma->invalid = 1;
}
/* Set DMA byte count
@@ -150,78 +144,137 @@ void set_dma_addr (dmach_t channel, unsigned long physaddr)
*/
void set_dma_count (dmach_t channel, unsigned long count)
{
- if (dma_chan[channel].active)
- printk(KERN_ERR "set_dma_count: altering DMA%d"
- " count while DMA active\n",
- channel);
-
- dma_chan[channel].sg = &dma_chan[channel].buf;
- dma_chan[channel].sgcount = 1;
- dma_chan[channel].buf.length = count;
- dma_chan[channel].invalid = 1;
+ dma_t *dma = dma_chan + channel;
+
+ if (dma->active)
+ printk(KERN_ERR "dma%d: altering DMA count while "
+ "DMA active\n", channel);
+
+ dma->sg = &dma->buf;
+ dma->sgcount = 1;
+ dma->buf.length = count;
+ dma->invalid = 1;
}
/* Set DMA direction mode
*/
void set_dma_mode (dmach_t channel, dmamode_t mode)
{
- if (dma_chan[channel].active)
- printk(KERN_ERR "set_dma_mode: altering DMA%d"
- " mode while DMA active\n",
- channel);
+ dma_t *dma = dma_chan + channel;
+
+ if (dma->active)
+ printk(KERN_ERR "dma%d: altering DMA mode while "
+ "DMA active\n", channel);
- dma_chan[channel].dma_mode = mode;
- dma_chan[channel].invalid = 1;
+ dma->dma_mode = mode;
+ dma->invalid = 1;
}
/* Enable DMA channel
*/
void enable_dma (dmach_t channel)
{
- if (dma_chan[channel].lock) {
- if (dma_chan[channel].active == 0) {
- dma_chan[channel].active = 1;
- arch_enable_dma(channel, &dma_chan[channel]);
- }
- } else
- printk (KERN_ERR "Trying to enable free DMA%d\n", channel);
+ dma_t *dma = dma_chan + channel;
+
+ if (!dma->lock)
+ goto free_dma;
+
+ if (dma->active == 0) {
+ dma->active = 1;
+ dma->d_ops->enable(channel, dma);
+ }
+ return;
+
+free_dma:
+ printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel);
+ BUG();
}
/* Disable DMA channel
*/
void disable_dma (dmach_t channel)
{
- if (dma_chan[channel].lock) {
- if (dma_chan[channel].active == 1) {
- dma_chan[channel].active = 0;
- arch_disable_dma(channel, &dma_chan[channel]);
- }
- } else
- printk (KERN_ERR "Trying to disable free DMA%d\n", channel);
+ dma_t *dma = dma_chan + channel;
+
+ if (!dma->lock)
+ goto free_dma;
+
+ if (dma->active == 1) {
+ dma->active = 0;
+ dma->d_ops->disable(channel, dma);
+ }
+ return;
+
+free_dma:
+ printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel);
+ BUG();
+}
+
+void set_dma_page(dmach_t channel, char pagenr)
+{
+ printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel);
}
void set_dma_speed(dmach_t channel, int cycle_ns)
{
- dma_chan[channel].speed =
- arch_set_dma_speed(channel, &dma_chan[channel], cycle_ns);
+ dma_t *dma = dma_chan + channel;
+ int ret = 0;
+
+ if (dma->d_ops->setspeed)
+ ret = dma->d_ops->setspeed(channel, dma, cycle_ns);
+ dma->speed = ret;
}
int get_dma_residue(dmach_t channel)
{
- return arch_get_dma_residue(channel, &dma_chan[channel]);
+ dma_t *dma = dma_chan + channel;
+ int ret = 0;
+
+ if (dma->d_ops->residue)
+ ret = dma->d_ops->residue(channel, dma);
+
+ return ret;
+}
+
+void __init init_dma(void)
+{
+ arch_dma_init(dma_chan);
+}
+
+#else
+
+int request_dma(dmach_t channel, const char *device_id)
+{
+ return -EINVAL;
+}
+
+static int no_dma(void)
+{
+ return 0;
}
-EXPORT_SYMBOL(dma_str);
+#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a)
+GLOBAL_ALIAS(disable_dma, no_dma);
+GLOBAL_ALIAS(enable_dma, no_dma);
+GLOBAL_ALIAS(free_dma, no_dma);
+GLOBAL_ALIAS(get_dma_residue, no_dma);
+GLOBAL_ALIAS(get_dma_list, no_dma);
+GLOBAL_ALIAS(set_dma_mode, no_dma);
+GLOBAL_ALIAS(set_dma_page, no_dma);
+GLOBAL_ALIAS(set_dma_count, no_dma);
+GLOBAL_ALIAS(set_dma_addr, no_dma);
+GLOBAL_ALIAS(set_dma_sg, no_dma);
+GLOBAL_ALIAS(set_dma_speed, no_dma);
+GLOBAL_ALIAS(init_dma, no_dma);
+
+#endif
+
EXPORT_SYMBOL(enable_dma);
EXPORT_SYMBOL(disable_dma);
EXPORT_SYMBOL(set_dma_addr);
EXPORT_SYMBOL(set_dma_count);
EXPORT_SYMBOL(set_dma_mode);
+EXPORT_SYMBOL(set_dma_page);
EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(set_dma_sg);
EXPORT_SYMBOL(set_dma_speed);
-
-void __init init_dma(void)
-{
- arch_dma_init(dma_chan);
-}
diff --git a/arch/arm/kernel/dma.h b/arch/arm/kernel/dma.h
index 33db3b03b..6cd96ed97 100644
--- a/arch/arm/kernel/dma.h
+++ b/arch/arm/kernel/dma.h
@@ -1,13 +1,26 @@
/*
- * arch/arm/kernel/dma.h
+ * linux/arch/arm/kernel/dma.h
*
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998-2000 Russell King
*
* This header file describes the interface between the generic DMA handler
* (dma.c) and the architecture-specific DMA backends (dma-*.c)
*/
-typedef struct {
+struct dma_struct;
+typedef struct dma_struct dma_t;
+
+struct dma_ops {
+ int (*request)(dmach_t, dma_t *); /* optional */
+ void (*free)(dmach_t, dma_t *); /* optional */
+ void (*enable)(dmach_t, dma_t *); /* mandatory */
+ void (*disable)(dmach_t, dma_t *); /* mandatory */
+ int (*residue)(dmach_t, dma_t *); /* optional */
+ int (*setspeed)(dmach_t, dma_t *, int); /* optional */
+ char *type;
+};
+
+struct dma_struct {
dmasg_t buf; /* single DMA */
int sgcount; /* number of DMA SG */
dmasg_t *sg; /* DMA Scatter-Gather List */
@@ -24,54 +37,9 @@ typedef struct {
int dma_irq; /* Controller IRQ */
int state; /* Controller state */
dmasg_t cur_sg; /* Current controller buffer */
-} dma_t;
-
-/* Prototype: int arch_request_dma(channel, dma, dev_id)
- * Purpose : Perform architecture specific claiming of a DMA channel
- * Params : channel - DMA channel number
- * : dma - DMA structure (above) for channel
- * : dev_id - device ID string passed with request
- * Returns : 0 on success, E????? number on error
- */
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id);
-
-/* Prototype: int arch_free_dma(channel, dma)
- * Purpose : Perform architecture specific freeing of a DMA channel
- * Params : channel - DMA channel number
- * : dma - DMA structure for channel
- */
-void arch_free_dma(dmach_t channel, dma_t *dma);
-
-/* Prototype: void arch_enable_dma(channel, dma)
- * Purpose : Enable a claimed DMA channel
- * Params : channel - DMA channel number
- * : dma - DMA structure for channel
- */
-void arch_enable_dma(dmach_t channel, dma_t *dma);
-
-/* Prototype: void arch_disable_dma(channel, dma)
- * Purpose : Disable a claimed DMA channel
- * Params : channel - DMA channel number
- * : dma - DMA structure for channel
- */
-void arch_disable_dma(dmach_t channel, dma_t *dma);
-/* Prototype: int arch_get_dma_residue(channel, dma)
- * Purpose : Return number of bytes left to DMA
- * Params : channel - DMA channel number
- * : dma - DMA structure for channel
- * Returns : Number of bytes left to DMA
- */
-int arch_get_dma_residue(dmach_t channel, dma_t *dma);
-
-/* Prototype: int arch_set_dma_speed(channel, dma, cycle)
- * Purpose : Convert a cycle time to a register setting
- * Params : channel - DMA channel number
- * : dma - DMA structure for channel
- * : cycle - cycle time in NS
- * Returns : setting for 'dma->speed'
- */
-int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle);
+ struct dma_ops *d_ops;
+};
/* Prototype: void arch_dma_init(dma)
* Purpose : Initialise architecture specific DMA
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index b4d38e00f..5acfd9f24 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -44,12 +44,6 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
-#ifdef CONFIG_ARCH_ARC
-#include <asm/arch/oldlatches.h>
-#else
-#define oldlatch_init()
-#endif
-
#ifndef CONFIG_ARCH_RPC
#define HAVE_EXPMASK
#endif
@@ -378,7 +372,8 @@ ecard_call(struct ecard_request *req)
ecard_task_reset(req);
} else {
if (ecard_pid <= 0)
- ecard_pid = kernel_thread(ecard_task, NULL, 0);
+ ecard_pid = kernel_thread(ecard_task, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
ecard_req = req;
@@ -1062,8 +1057,6 @@ void __init ecard_init(void)
{
int slot;
- oldlatch_init();
-
#ifdef CONFIG_CPU_32
init_waitqueue_head(&ecard_wait);
init_waitqueue_head(&ecard_done);
diff --git a/arch/arm/kernel/hw-sa1100.c b/arch/arm/kernel/hw-sa1100.c
index 862c3a2c4..27786cdd2 100644
--- a/arch/arm/kernel/hw-sa1100.c
+++ b/arch/arm/kernel/hw-sa1100.c
@@ -81,6 +81,24 @@ void __init get_assabet_scr(void)
#endif /* CONFIG_SA1100_ASSABET */
+/*
+ * Bitsy has extended, write-only memory-mapped GPIO's
+ */
+#if defined(CONFIG_SA1100_BITSY)
+static int bitsy_egpio = EGPIO_BITSY_RS232_ON;
+void clr_bitsy_egpio(unsigned long x)
+{
+ bitsy_egpio &= ~x;
+ *(volatile int *)0xdc000000 = bitsy_egpio;
+}
+void set_bitsy_egpio(unsigned long x)
+{
+ bitsy_egpio |= x;
+ *(volatile int *)0xdc000000 = bitsy_egpio;
+}
+EXPORT_SYMBOL(clr_bitsy_egpio);
+EXPORT_SYMBOL(set_bitsy_egpio);
+#endif
#ifdef CONFIG_SA1111
diff --git a/arch/arm/kernel/oldlatches.c b/arch/arm/kernel/oldlatches.c
index a908241d2..3d6758ff4 100644
--- a/arch/arm/kernel/oldlatches.c
+++ b/arch/arm/kernel/oldlatches.c
@@ -3,52 +3,53 @@
*
* (c) David Alan Gilbert 1995/1996
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/hardware.h>
-#ifdef LATCHAADDR
-/*
- * They are static so that everyone who accesses them has to go through here
- */
-static unsigned char LatchACopy;
+static unsigned char latch_a_copy;
+static unsigned char latch_b_copy;
/* newval=(oldval & ~mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
{
- LatchACopy=(LatchACopy & ~mask)|newdata;
- outb(LatchACopy, LATCHAADDR);
-#ifdef DEBUG
- printk("oldlatch_A:0x%2x\n",LatchACopy);
-#endif
+ if (machine_is_arc()) {
+ latch_a_copy = (latch_a_copy & ~mask) | newdata;
+
+ printk("Latch: A = 0x%02x\n", latch_a_copy);
+ outb(latch_a_copy, LATCHAADDR);
+ } else
+ BUG();
}
-#endif
-#ifdef LATCHBADDR
-static unsigned char LatchBCopy;
/* newval=(oldval & ~mask)|newdata */
void oldlatch_bupdate(unsigned char mask,unsigned char newdata)
{
- LatchBCopy=(LatchBCopy & ~mask)|newdata;
- outb(LatchBCopy, LATCHBADDR);
-#ifdef DEBUG
- printk("oldlatch_B:0x%2x\n",LatchBCopy);
-#endif
+ if (machine_is_arc()) {
+ latch_b_copy = (latch_b_copy & ~mask) | newdata;
+
+ printk("Latch: B = 0x%02x\n", latch_b_copy);
+
+ outb(latch_b_copy, LATCHBADDR);
+ } else
+ BUG();
}
-#endif
-void __init oldlatch_init(void)
+static void __init oldlatch_init(void)
{
- printk("oldlatch: init\n");
-#ifdef LATCHAADDR
- oldlatch_aupdate(0xff,0xff);
-#endif
-#ifdef LATCHBADDR
- oldlatch_bupdate(0xff,0x8); /* Thats no FDC reset...*/
-#endif
- return ;
+ if (machine_is_arc()) {
+ oldlatch_aupdate(0xff, 0xff);
+ /* Thats no FDC reset...*/
+ oldlatch_bupdate(0xff, LATCHB_FDCRESET);
+ }
}
+
+initcall(oldlatch_init);
+
+EXPORT_SYMBOL(oldlatch_aupdate);
+EXPORT_SYMBOL(oldlatch_bupdate);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index f281f7337..3ef5bc59d 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -67,6 +67,12 @@ __setup("nohlt", nohlt_setup);
__setup("hlt", hlt_setup);
/*
+ * The following aren't currently used.
+ */
+void (*pm_idle)(void);
+void (*pm_power_off)(void);
+
+/*
* The idle thread. We try to conserve power, while trying to keep
* overall latency low. The architecture specific idle is passed
* a value to indicate the level of "idleness" of the system.
@@ -79,7 +85,11 @@ void cpu_idle(void)
current->counter = -100;
while (1) {
- arch_idle();
+ void (*idle)(void) = pm_idle;
+ if (!idle)
+ idle = arch_idle;
+ while (!current->need_resched)
+ idle();
schedule();
#ifndef CONFIG_NO_PGT_CACHE
check_pgt_cache();
@@ -97,6 +107,16 @@ int __init reboot_setup(char *str)
__setup("reboot=", reboot_setup);
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+ if (pm_power_off)
+ pm_power_off();
+}
+
void machine_restart(char * __unused)
{
/*
@@ -125,15 +145,6 @@ void machine_restart(char * __unused)
while (1);
}
-void machine_halt(void)
-{
-}
-
-void machine_power_off(void)
-{
- arch_power_off();
-}
-
void show_regs(struct pt_regs * regs)
{
unsigned long flags;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 3e6cf6cb4..4d489bcf3 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -586,7 +586,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
/* FALLTHRU */
default:
- lock_kernel();
sigaddset(&current->signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 2c3cabadc..6d49e1427 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -11,9 +11,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/malloc.h>
#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index d7f6640eb..da437639f 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -30,7 +30,7 @@
extern int setup_arm_irq(int, struct irqaction *);
extern void setup_timer(void);
extern rwlock_t xtime_lock;
-extern volatile unsigned long lost_ticks;
+extern unsigned long wall_jiffies;
/* change this if you have some constant time drift */
#define USECS_PER_JIFFY (1000000/HZ)
@@ -189,7 +189,7 @@ void do_gettimeofday(struct timeval *tv)
read_lock_irqsave(&xtime_lock, flags);
usec = gettimeoffset();
{
- unsigned long lost = lost_ticks;
+ unsigned long lost = jiffies - wall_jiffies;
if (lost)
usec += lost * USECS_PER_JIFFY;
@@ -218,7 +218,7 @@ void do_settimeofday(struct timeval *tv)
* would have done, and then undo it!
*/
tv->tv_usec -= gettimeoffset();
- tv->tv_usec -= lost_ticks * USECS_PER_JIFFY;
+ tv->tv_usec -= (jiffies - wall_jiffies) * USECS_PER_JIFFY;
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 188f89722..c76a95736 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -37,9 +37,6 @@ char *processor_modes[]=
"UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
};
-/* proc/system.h */
-const char xchg_str[] = "xchg";
-
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
static inline void console_verbose(void)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index e932164bf..991b4a3c8 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -14,8 +14,7 @@ L_OBJS := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
O_TARGET := lib.o
O_OBJS := backtrace.o delay.o
-L_OBJS_arc := io-acorn.o
-L_OBJS_a5k := io-acorn.o floppydma.o
+L_OBJS_arc := io-acorn.o floppydma.o
L_OBJS_rpc := io-acorn.o floppydma.o
L_OBJS_clps7500 := io-acorn.o
L_OBJS_ebsa110 := io-ebsa110.o
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index e269e146c..589653111 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -623,17 +623,31 @@ void free_initmem(void)
}
#ifdef CONFIG_BLK_DEV_INITRD
+
+static int keep_initrd;
+
void free_initrd_mem(unsigned long start, unsigned long end)
{
unsigned long addr;
- for (addr = start; addr < end; addr += PAGE_SIZE) {
- ClearPageReserved(mem_map + MAP_NR(addr));
- set_page_count(mem_map+MAP_NR(addr), 1);
- free_page(addr);
- totalram_pages++;
+
+ if (!keep_initrd) {
+ for (addr = start; addr < end; addr += PAGE_SIZE) {
+ ClearPageReserved(mem_map + MAP_NR(addr));
+ set_page_count(mem_map+MAP_NR(addr), 1);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
}
- printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+ keep_initrd = 1;
+ return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
#endif
void si_meminfo(struct sysinfo *val)
diff --git a/arch/arm/mm/mm-sa1100.c b/arch/arm/mm/mm-sa1100.c
index 328364e56..c1ecf3fb1 100644
--- a/arch/arm/mm/mm-sa1100.c
+++ b/arch/arm/mm/mm-sa1100.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <asm/hardware.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -55,6 +56,7 @@ static struct map_desc assabet_io_desc[] __initdata = {
static struct map_desc bitsy_io_desc[] __initdata = {
#ifdef CONFIG_SA1100_BITSY
{ 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xdc000000, 0x49000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
SA1100_STD_IO_MAPPING
#endif
};
@@ -144,6 +146,7 @@ void __init select_sa1100_io_desc(void)
}
}
+
#ifdef CONFIG_DISCONTIGMEM
/*
@@ -161,3 +164,20 @@ pg_data_t sa1100_node_data[4] =
#endif
+
+/*
+ * On Assabet, we must probe for the Neponset board *before* paging_init()
+ * has occured to actually determine the amount of RAM available. To do so,
+ * we map the appropriate IO section in the page table here in order to
+ * access GPIO registers.
+ */
+void __init map_sa1100_gpio_regs( void )
+{
+ unsigned long phys = _GPLR & PMD_MASK;
+ unsigned long virt = io_p2v(phys);
+ int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
+ pmd_t pmd;
+ pmd_val(pmd) = phys | prot;
+ set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd);
+}
+
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 9d5ee058d..656779195 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -36,6 +36,7 @@ SECTIONS
/DISCARD/ : { /* Exit code and data */
*(.text.exit)
*(.data.exit)
+ *(.exitcall.exit)
}
.text : {
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index 1476ba939..4ef7377bb 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -29,8 +29,9 @@ SECTIONS
}
/DISCARD/ : { /* Exit code and data */
- *(.text.exit)
- *(.data.exit)
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
}
.text : { /* Real text segment */