aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Kconfig2
-rw-r--r--arch/alpha/mm/init.c2
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/avr32/Kconfig196
-rw-r--r--arch/avr32/Kconfig.debug19
-rw-r--r--arch/avr32/Makefile84
-rw-r--r--arch/avr32/boards/atstk1000/Makefile2
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c37
-rw-r--r--arch/avr32/boards/atstk1000/flash.c95
-rw-r--r--arch/avr32/boards/atstk1000/setup.c59
-rw-r--r--arch/avr32/boards/atstk1000/spi.c27
-rw-r--r--arch/avr32/boot/images/Makefile62
-rw-r--r--arch/avr32/boot/u-boot/Makefile3
-rw-r--r--arch/avr32/boot/u-boot/empty.S1
-rw-r--r--arch/avr32/boot/u-boot/head.S60
-rw-r--r--arch/avr32/configs/atstk1002_defconfig754
-rw-r--r--arch/avr32/kernel/Makefile18
-rw-r--r--arch/avr32/kernel/asm-offsets.c25
-rw-r--r--arch/avr32/kernel/avr32_ksyms.c55
-rw-r--r--arch/avr32/kernel/cpu.c327
-rw-r--r--arch/avr32/kernel/entry-avr32b.S678
-rw-r--r--arch/avr32/kernel/head.S45
-rw-r--r--arch/avr32/kernel/init_task.c38
-rw-r--r--arch/avr32/kernel/irq.c71
-rw-r--r--arch/avr32/kernel/kprobes.c270
-rw-r--r--arch/avr32/kernel/module.c324
-rw-r--r--arch/avr32/kernel/process.c276
-rw-r--r--arch/avr32/kernel/ptrace.c371
-rw-r--r--arch/avr32/kernel/semaphore.c148
-rw-r--r--arch/avr32/kernel/setup.c335
-rw-r--r--arch/avr32/kernel/signal.c328
-rw-r--r--arch/avr32/kernel/switch_to.S35
-rw-r--r--arch/avr32/kernel/sys_avr32.c51
-rw-r--r--arch/avr32/kernel/syscall-stubs.S102
-rw-r--r--arch/avr32/kernel/syscall_table.S289
-rw-r--r--arch/avr32/kernel/time.c238
-rw-r--r--arch/avr32/kernel/traps.c425
-rw-r--r--arch/avr32/kernel/vmlinux.lds.c139
-rw-r--r--arch/avr32/lib/Makefile10
-rw-r--r--arch/avr32/lib/__avr32_asr64.S31
-rw-r--r--arch/avr32/lib/__avr32_lsl64.S31
-rw-r--r--arch/avr32/lib/__avr32_lsr64.S31
-rw-r--r--arch/avr32/lib/clear_user.S76
-rw-r--r--arch/avr32/lib/copy_user.S119
-rw-r--r--arch/avr32/lib/csum_partial.S47
-rw-r--r--arch/avr32/lib/csum_partial_copy_generic.S99
-rw-r--r--arch/avr32/lib/delay.c55
-rw-r--r--arch/avr32/lib/findbit.S154
-rw-r--r--arch/avr32/lib/io-readsl.S24
-rw-r--r--arch/avr32/lib/io-readsw.S43
-rw-r--r--arch/avr32/lib/io-writesl.S20
-rw-r--r--arch/avr32/lib/io-writesw.S38
-rw-r--r--arch/avr32/lib/libgcc.h33
-rw-r--r--arch/avr32/lib/longlong.h98
-rw-r--r--arch/avr32/lib/memcpy.S62
-rw-r--r--arch/avr32/lib/memset.S72
-rw-r--r--arch/avr32/lib/strncpy_from_user.S60
-rw-r--r--arch/avr32/lib/strnlen_user.S67
-rw-r--r--arch/avr32/mach-at32ap/Makefile2
-rw-r--r--arch/avr32/mach-at32ap/at32ap.c90
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c876
-rw-r--r--arch/avr32/mach-at32ap/clock.c148
-rw-r--r--arch/avr32/mach-at32ap/clock.h30
-rw-r--r--arch/avr32/mach-at32ap/extint.c171
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c164
-rw-r--r--arch/avr32/mach-at32ap/hsmc.h127
-rw-r--r--arch/avr32/mach-at32ap/intc.c133
-rw-r--r--arch/avr32/mach-at32ap/intc.h327
-rw-r--r--arch/avr32/mach-at32ap/pio.c118
-rw-r--r--arch/avr32/mach-at32ap/pio.h178
-rw-r--r--arch/avr32/mach-at32ap/sm.c289
-rw-r--r--arch/avr32/mach-at32ap/sm.h240
-rw-r--r--arch/avr32/mm/Makefile6
-rw-r--r--arch/avr32/mm/cache.c150
-rw-r--r--arch/avr32/mm/clear_page.S25
-rw-r--r--arch/avr32/mm/copy_page.S28
-rw-r--r--arch/avr32/mm/dma-coherent.c139
-rw-r--r--arch/avr32/mm/fault.c315
-rw-r--r--arch/avr32/mm/init.c480
-rw-r--r--arch/avr32/mm/ioremap.c197
-rw-r--r--arch/avr32/mm/tlb.c378
-rw-r--r--arch/frv/Kconfig12
-rw-r--r--arch/frv/kernel/Makefile5
-rw-r--r--arch/frv/kernel/irq-mb93091.c157
-rw-r--r--arch/frv/kernel/irq-mb93093.c115
-rw-r--r--arch/frv/kernel/irq-mb93493.c160
-rw-r--r--arch/frv/kernel/irq-routing.c291
-rw-r--r--arch/frv/kernel/irq.c741
-rw-r--r--arch/frv/kernel/setup.c1
-rw-r--r--arch/frv/kernel/time.c1
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c1
-rw-r--r--arch/frv/mm/init.c2
-rw-r--r--arch/h8300/mm/init.c2
-rw-r--r--arch/i386/Kconfig4
-rw-r--r--arch/i386/kernel/apm.c26
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c4
-rw-r--r--arch/i386/kernel/efi_stub.S1
-rw-r--r--arch/i386/kernel/reboot.c12
-rw-r--r--arch/i386/kernel/setup.c23
-rw-r--r--arch/i386/kernel/smp.c66
-rw-r--r--arch/i386/kernel/srat.c5
-rw-r--r--arch/i386/kernel/time.c50
-rw-r--r--arch/i386/kernel/time_hpet.c37
-rw-r--r--arch/i386/kernel/traps.c11
-rw-r--r--arch/i386/kernel/vmlinux.lds.S12
-rw-r--r--arch/i386/mach-voyager/voyager_thread.c1
-rw-r--r--arch/i386/mm/discontig.c33
-rw-r--r--arch/i386/mm/init.c44
-rw-r--r--arch/i386/mm/pgtable.c30
-rw-r--r--arch/i386/power/swsusp.S2
-rw-r--r--arch/ia64/Kconfig9
-rw-r--r--arch/ia64/kernel/perfmon.c1
-rw-r--r--arch/ia64/kernel/uncached.c2
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c3
-rw-r--r--arch/m32r/mm/init.c2
-rw-r--r--arch/m68knommu/mm/init.c2
-rw-r--r--arch/mips/au1000/common/dbdma.c10
-rw-r--r--arch/mips/mm/init.c4
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c3
-rw-r--r--arch/parisc/mm/init.c4
-rw-r--r--arch/powerpc/kernel/swsusp_32.S4
-rw-r--r--arch/s390/appldata/appldata_mem.c3
-rw-r--r--arch/s390/mm/cmm.c205
-rw-r--r--arch/sh/mm/cache-sh7705.c2
-rw-r--r--arch/sh64/mm/init.c2
-rw-r--r--arch/sparc/mm/srmmu.c2
-rw-r--r--arch/sparc/mm/sun4c.c2
-rw-r--r--arch/um/drivers/chan_kern.c2
-rw-r--r--arch/um/drivers/mconsole_kern.c2
-rw-r--r--arch/um/drivers/mconsole_user.c7
-rw-r--r--arch/um/drivers/net_kern.c14
-rw-r--r--arch/um/drivers/pcap_kern.c2
-rw-r--r--arch/um/include/kern_util.h1
-rw-r--r--arch/um/include/longjmp.h5
-rw-r--r--arch/um/include/net_user.h1
-rw-r--r--arch/um/include/os.h5
-rw-r--r--arch/um/include/registers.h3
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h19
-rw-r--r--arch/um/include/sysdep-i386/signal.h27
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h21
-rw-r--r--arch/um/include/sysdep-x86_64/signal.h29
-rw-r--r--arch/um/kernel/exec.c4
-rw-r--r--arch/um/kernel/irq.c34
-rw-r--r--arch/um/kernel/mem.c7
-rw-r--r--arch/um/kernel/process_kern.c3
-rw-r--r--arch/um/kernel/reboot.c13
-rw-r--r--arch/um/kernel/skas/mmu.c2
-rw-r--r--arch/um/kernel/time.c12
-rw-r--r--arch/um/kernel/tlb.c370
-rw-r--r--arch/um/kernel/trap.c11
-rw-r--r--arch/um/os-Linux/helper.c22
-rw-r--r--arch/um/os-Linux/irq.c2
-rw-r--r--arch/um/os-Linux/main.c34
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/process.c13
-rw-r--r--arch/um/os-Linux/sigio.c103
-rw-r--r--arch/um/os-Linux/signal.c38
-rw-r--r--arch/um/os-Linux/skas/process.c26
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c17
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c15
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c17
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c16
-rw-r--r--arch/um/os-Linux/time.c22
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/uaccess.c3
-rw-r--r--arch/um/os-Linux/util.c5
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/bugs.c9
-rw-r--r--arch/um/sys-i386/ldt.c3
-rw-r--r--arch/um/sys-i386/ptrace_user.c5
-rw-r--r--arch/um/sys-i386/setjmp.S58
-rw-r--r--arch/um/sys-x86_64/Makefile4
-rw-r--r--arch/um/sys-x86_64/setjmp.S54
-rw-r--r--arch/x86_64/Kconfig4
-rw-r--r--arch/x86_64/kernel/e820.c48
-rw-r--r--arch/x86_64/kernel/setup.c1
-rw-r--r--arch/x86_64/kernel/smpboot.c3
-rw-r--r--arch/x86_64/kernel/suspend_asm.S2
-rw-r--r--arch/x86_64/kernel/time.c37
-rw-r--r--arch/x86_64/mm/fault.c6
-rw-r--r--arch/x86_64/mm/init.c2
184 files changed, 13317 insertions, 1743 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 213c7850d5fb..2b36afd8e969 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -381,7 +381,7 @@ config ALPHA_EV56
381 381
382config ALPHA_EV56 382config ALPHA_EV56
383 prompt "EV56 CPU (speed >= 333MHz)?" 383 prompt "EV56 CPU (speed >= 333MHz)?"
384 depends on ALPHA_NORITAKE && ALPHA_PRIMO 384 depends on ALPHA_NORITAKE || ALPHA_PRIMO
385 385
386config ALPHA_EV56 386config ALPHA_EV56
387 prompt "EV56 CPU (speed >= 400MHz)?" 387 prompt "EV56 CPU (speed >= 400MHz)?"
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 917dad1b74c8..550f4907d613 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -270,7 +270,7 @@ callback_init(void * kernel_end)
270void 270void
271paging_init(void) 271paging_init(void)
272{ 272{
273 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 273 unsigned long zones_size[MAX_NR_ZONES] = {0, };
274 unsigned long dma_pfn, high_pfn; 274 unsigned long dma_pfn, high_pfn;
275 275
276 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; 276 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 88a999df0ab3..591fc3187c7f 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -177,7 +177,7 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
177 * Free the page table, if there was one. 177 * Free the page table, if there was one.
178 */ 178 */
179 if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) 179 if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
180 pte_free_kernel(pmd_page_kernel(pmd)); 180 pte_free_kernel(pmd_page_vaddr(pmd));
181 } 181 }
182 182
183 addr += PGDIR_SIZE; 183 addr += PGDIR_SIZE;
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
new file mode 100644
index 000000000000..5f1694eea842
--- /dev/null
+++ b/arch/avr32/Kconfig
@@ -0,0 +1,196 @@
1#
2# For a description of the syntax of this configuration file,
3# see Documentation/kbuild/kconfig-language.txt.
4#
5
6mainmenu "Linux Kernel Configuration"
7
8config AVR32
9 bool
10 default y
11 # With EMBEDDED=n, we get lots of stuff automatically selected
12 # that we usually don't need on AVR32.
13 select EMBEDDED
14 help
15 AVR32 is a high-performance 32-bit RISC microprocessor core,
16 designed for cost-sensitive embedded applications, with particular
17 emphasis on low power consumption and high code density.
18
19 There is an AVR32 Linux project with a web page at
20 http://avr32linux.org/.
21
22config UID16
23 bool
24
25config GENERIC_HARDIRQS
26 bool
27 default y
28
29config HARDIRQS_SW_RESEND
30 bool
31 default y
32
33config GENERIC_IRQ_PROBE
34 bool
35 default y
36
37config RWSEM_GENERIC_SPINLOCK
38 bool
39 default y
40
41config GENERIC_TIME
42 bool
43 default y
44
45config RWSEM_XCHGADD_ALGORITHM
46 bool
47
48config GENERIC_BUST_SPINLOCK
49 bool
50
51config GENERIC_HWEIGHT
52 bool
53 default y
54
55config GENERIC_CALIBRATE_DELAY
56 bool
57 default y
58
59source "init/Kconfig"
60
61menu "System Type and features"
62
63config SUBARCH_AVR32B
64 bool
65config MMU
66 bool
67config PERFORMANCE_COUNTERS
68 bool
69
70config PLATFORM_AT32AP
71 bool
72 select SUBARCH_AVR32B
73 select MMU
74 select PERFORMANCE_COUNTERS
75
76choice
77 prompt "AVR32 CPU type"
78 default CPU_AT32AP7000
79
80config CPU_AT32AP7000
81 bool "AT32AP7000"
82 select PLATFORM_AT32AP
83endchoice
84
85#
86# CPU Daughterboards for ATSTK1000
87config BOARD_ATSTK1002
88 bool
89
90choice
91 prompt "AVR32 board type"
92 default BOARD_ATSTK1000
93
94config BOARD_ATSTK1000
95 bool "ATSTK1000 evaluation board"
96 select BOARD_ATSTK1002 if CPU_AT32AP7000
97endchoice
98
99choice
100 prompt "Boot loader type"
101 default LOADER_U_BOOT
102
103config LOADER_U_BOOT
104 bool "U-Boot (or similar) bootloader"
105endchoice
106
107config LOAD_ADDRESS
108 hex
109 default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
110
111config ENTRY_ADDRESS
112 hex
113 default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
114
115config PHYS_OFFSET
116 hex
117 default 0x10000000 if CPU_AT32AP7000=y
118
119source "kernel/Kconfig.preempt"
120
121config HAVE_ARCH_BOOTMEM_NODE
122 bool
123 default n
124
125config ARCH_HAVE_MEMORY_PRESENT
126 bool
127 default n
128
129config NEED_NODE_MEMMAP_SIZE
130 bool
131 default n
132
133config ARCH_FLATMEM_ENABLE
134 bool
135 default y
136
137config ARCH_DISCONTIGMEM_ENABLE
138 bool
139 default n
140
141config ARCH_SPARSEMEM_ENABLE
142 bool
143 default n
144
145source "mm/Kconfig"
146
147config OWNERSHIP_TRACE
148 bool "Ownership trace support"
149 default y
150 help
151 Say Y to generate an Ownership Trace message on every context switch,
152 enabling Nexus-compliant debuggers to keep track of the PID of the
153 currently executing task.
154
155# FPU emulation goes here
156
157source "kernel/Kconfig.hz"
158
159config CMDLINE
160 string "Default kernel command line"
161 default ""
162 help
163 If you don't have a boot loader capable of passing a command line string
164 to the kernel, you may specify one here. As a minimum, you should specify
165 the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
166
167endmenu
168
169menu "Bus options"
170
171config PCI
172 bool
173
174source "drivers/pci/Kconfig"
175
176source "drivers/pcmcia/Kconfig"
177
178endmenu
179
180menu "Executable file formats"
181source "fs/Kconfig.binfmt"
182endmenu
183
184source "net/Kconfig"
185
186source "drivers/Kconfig"
187
188source "fs/Kconfig"
189
190source "arch/avr32/Kconfig.debug"
191
192source "security/Kconfig"
193
194source "crypto/Kconfig"
195
196source "lib/Kconfig"
diff --git a/arch/avr32/Kconfig.debug b/arch/avr32/Kconfig.debug
new file mode 100644
index 000000000000..64ace00fe6cb
--- /dev/null
+++ b/arch/avr32/Kconfig.debug
@@ -0,0 +1,19 @@
1menu "Kernel hacking"
2
3config TRACE_IRQFLAGS_SUPPORT
4 bool
5 default y
6
7source "lib/Kconfig.debug"
8
9config KPROBES
10 bool "Kprobes"
11 depends on DEBUG_KERNEL
12 help
13 Kprobes allows you to trap at almost any kernel address and
14 execute a callback function. register_kprobe() establishes
15 a probepoint and specifies the callback. Kprobes is useful
16 for kernel debugging, non-intrusive instrumentation and testing.
17 If in doubt, say "N".
18
19endmenu
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
new file mode 100644
index 000000000000..cefc95a73980
--- /dev/null
+++ b/arch/avr32/Makefile
@@ -0,0 +1,84 @@
1#
2# This file is subject to the terms and conditions of the GNU General Public
3# License. See the file "COPYING" in the main directory of this archive
4# for more details.
5#
6# Copyright (C) 2004-2006 Atmel Corporation.
7
8# Default target when executing plain make
9.PHONY: all
10all: uImage vmlinux.elf linux.lst
11
12KBUILD_DEFCONFIG := atstk1002_defconfig
13
14CFLAGS += -pipe -fno-builtin -mno-pic
15AFLAGS += -mrelax -mno-pic
16CFLAGS_MODULE += -mno-relax
17LDFLAGS_vmlinux += --relax
18
19cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000
20
21CFLAGS += $(cpuflags-y)
22AFLAGS += $(cpuflags-y)
23
24CHECKFLAGS += -D__avr32__
25
26LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
27
28head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o
29head-y += arch/avr32/kernel/head.o
30core-$(CONFIG_PLATFORM_AT32AP) += arch/avr32/mach-at32ap/
31core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
32core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
33core-y += arch/avr32/kernel/
34core-y += arch/avr32/mm/
35libs-y += arch/avr32/lib/ #$(LIBGCC)
36
37archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap
38
39include/asm-avr32/.arch: $(wildcard include/config/platform/*.h) include/config/auto.conf
40 @echo ' SYMLINK include/asm-avr32/arch -> include/asm-avr32/$(archincdir-y)'
41ifneq ($(KBUILD_SRC),)
42 $(Q)mkdir -p include/asm-avr32
43 $(Q)ln -fsn $(srctree)/include/asm-avr32/$(archincdir-y) include/asm-avr32/arch
44else
45 $(Q)ln -fsn $(archincdir-y) include/asm-avr32/arch
46endif
47 @touch $@
48
49archprepare: include/asm-avr32/.arch
50
51BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
52
53.PHONY: $(BOOT_TARGETS) install
54
55boot := arch/$(ARCH)/boot/images
56
57 KBUILD_IMAGE := $(boot)/uImage
58vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf
59vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso
60uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec
61uImage: KBUILD_IMAGE := $(boot)/uImage
62
63quiet_cmd_listing = LST $@
64 cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@
65quiet_cmd_disasm = DIS $@
66 cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@
67
68vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux
69 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
70
71install: vmlinux
72 $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
73
74linux.s: vmlinux
75 $(call if_changed,disasm)
76
77linux.lst: vmlinux
78 $(call if_changed,listing)
79
80define archhelp
81 @echo '* vmlinux.elf - ELF image with load address 0'
82 @echo ' vmlinux.cso - PathFinder CSO image'
83 @echo ' uImage - Create a bootable image for U-Boot'
84endef
diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile
new file mode 100644
index 000000000000..df9499480530
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/Makefile
@@ -0,0 +1,2 @@
1obj-y += setup.o spi.o flash.o
2obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
new file mode 100644
index 000000000000..49164e9aadd6
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -0,0 +1,37 @@
1/*
2 * ATSTK1002 daughterboard-specific init code
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/init.h>
11
12#include <asm/arch/board.h>
13
14struct eth_platform_data __initdata eth0_data = {
15 .valid = 1,
16 .mii_phy_addr = 0x10,
17 .is_rmii = 0,
18 .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
19};
20
21extern struct lcdc_platform_data atstk1000_fb0_data;
22
23static int __init atstk1002_init(void)
24{
25 at32_add_system_devices();
26
27 at32_add_device_usart(1); /* /dev/ttyS0 */
28 at32_add_device_usart(2); /* /dev/ttyS1 */
29 at32_add_device_usart(3); /* /dev/ttyS2 */
30
31 at32_add_device_eth(0, &eth0_data);
32 at32_add_device_spi(0);
33 at32_add_device_lcdc(0, &atstk1000_fb0_data);
34
35 return 0;
36}
37postcore_initcall(atstk1002_init);
diff --git a/arch/avr32/boards/atstk1000/flash.c b/arch/avr32/boards/atstk1000/flash.c
new file mode 100644
index 000000000000..aac4300cca12
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/flash.c
@@ -0,0 +1,95 @@
1/*
2 * ATSTK1000 board-specific flash initialization
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/partitions.h>
14#include <linux/mtd/physmap.h>
15
16#include <asm/arch/smc.h>
17
18static struct smc_config flash_config __initdata = {
19 .ncs_read_setup = 0,
20 .nrd_setup = 40,
21 .ncs_write_setup = 0,
22 .nwe_setup = 10,
23
24 .ncs_read_pulse = 80,
25 .nrd_pulse = 40,
26 .ncs_write_pulse = 65,
27 .nwe_pulse = 55,
28
29 .read_cycle = 120,
30 .write_cycle = 120,
31
32 .bus_width = 2,
33 .nrd_controlled = 1,
34 .nwe_controlled = 1,
35 .byte_write = 1,
36};
37
38static struct mtd_partition flash_parts[] = {
39 {
40 .name = "u-boot",
41 .offset = 0x00000000,
42 .size = 0x00020000, /* 128 KiB */
43 .mask_flags = MTD_WRITEABLE,
44 },
45 {
46 .name = "root",
47 .offset = 0x00020000,
48 .size = 0x007d0000,
49 },
50 {
51 .name = "env",
52 .offset = 0x007f0000,
53 .size = 0x00010000,
54 .mask_flags = MTD_WRITEABLE,
55 },
56};
57
58static struct physmap_flash_data flash_data = {
59 .width = 2,
60 .nr_parts = ARRAY_SIZE(flash_parts),
61 .parts = flash_parts,
62};
63
64static struct resource flash_resource = {
65 .start = 0x00000000,
66 .end = 0x007fffff,
67 .flags = IORESOURCE_MEM,
68};
69
70static struct platform_device flash_device = {
71 .name = "physmap-flash",
72 .id = 0,
73 .resource = &flash_resource,
74 .num_resources = 1,
75 .dev = {
76 .platform_data = &flash_data,
77 },
78};
79
80/* This needs to be called after the SMC has been initialized */
81static int __init atstk1000_flash_init(void)
82{
83 int ret;
84
85 ret = smc_set_configuration(0, &flash_config);
86 if (ret < 0) {
87 printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
88 return ret;
89 }
90
91 platform_device_register(&flash_device);
92
93 return 0;
94}
95device_initcall(atstk1000_flash_init);
diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c
new file mode 100644
index 000000000000..191ab85de9a3
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/setup.c
@@ -0,0 +1,59 @@
1/*
2 * ATSTK1000 board-specific setup code.
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/bootmem.h>
11#include <linux/init.h>
12#include <linux/types.h>
13#include <linux/linkage.h>
14
15#include <asm/setup.h>
16
17#include <asm/arch/board.h>
18
19/* Initialized by bootloader-specific startup code. */
20struct tag *bootloader_tags __initdata;
21
22struct lcdc_platform_data __initdata atstk1000_fb0_data;
23
24asmlinkage void __init board_early_init(void)
25{
26 extern void sdram_init(void);
27
28#ifdef CONFIG_LOADER_STANDALONE
29 sdram_init();
30#endif
31}
32
33void __init board_setup_fbmem(unsigned long fbmem_start,
34 unsigned long fbmem_size)
35{
36 if (!fbmem_size)
37 return;
38
39 if (!fbmem_start) {
40 void *fbmem;
41
42 fbmem = alloc_bootmem_low_pages(fbmem_size);
43 fbmem_start = __pa(fbmem);
44 } else {
45 pg_data_t *pgdat;
46
47 for_each_online_pgdat(pgdat) {
48 if (fbmem_start >= pgdat->bdata->node_boot_start
49 && fbmem_start <= pgdat->bdata->node_low_pfn)
50 reserve_bootmem_node(pgdat, fbmem_start,
51 fbmem_size);
52 }
53 }
54
55 printk("%luKiB framebuffer memory at address 0x%08lx\n",
56 fbmem_size >> 10, fbmem_start);
57 atstk1000_fb0_data.fbmem_start = fbmem_start;
58 atstk1000_fb0_data.fbmem_size = fbmem_size;
59}
diff --git a/arch/avr32/boards/atstk1000/spi.c b/arch/avr32/boards/atstk1000/spi.c
new file mode 100644
index 000000000000..567726c82c6e
--- /dev/null
+++ b/arch/avr32/boards/atstk1000/spi.c
@@ -0,0 +1,27 @@
1/*
2 * ATSTK1000 SPI devices
3 *
4 * Copyright (C) 2005 Atmel Norway
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/device.h>
11#include <linux/spi/spi.h>
12
13static struct spi_board_info spi_board_info[] __initdata = {
14 {
15 .modalias = "ltv350qv",
16 .max_speed_hz = 16000000,
17 .bus_num = 0,
18 .chip_select = 1,
19 },
20};
21
22static int board_init_spi(void)
23{
24 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
25 return 0;
26}
27arch_initcall(board_init_spi);
diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile
new file mode 100644
index 000000000000..ccd74eeecec3
--- /dev/null
+++ b/arch/avr32/boot/images/Makefile
@@ -0,0 +1,62 @@
1#
2# Copyright (C) 2004-2006 Atmel Corporation
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8
9MKIMAGE := $(srctree)/scripts/mkuboot.sh
10
11extra-y := vmlinux.bin vmlinux.gz
12
13OBJCOPYFLAGS_vmlinux.bin := -O binary
14$(obj)/vmlinux.bin: vmlinux FORCE
15 $(call if_changed,objcopy)
16
17$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
18 $(call if_changed,gzip)
19
20quiet_cmd_uimage = UIMAGE $@
21 cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A avr32 -O linux -T kernel \
22 -C gzip -a $(CONFIG_LOAD_ADDRESS) -e $(CONFIG_ENTRY_ADDRESS) \
23 -n 'Linux-$(KERNELRELEASE)' -d $< $@
24
25targets += uImage uImage.srec
26$(obj)/uImage: $(obj)/vmlinux.gz
27 $(call if_changed,uimage)
28 @echo ' Image $@ is ready'
29
30OBJCOPYFLAGS_uImage.srec := -I binary -O srec
31$(obj)/uImage.srec: $(obj)/uImage
32 $(call if_changed,objcopy)
33
34OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \
35 --change-section-lma __ex_table-0x80000000 \
36 --change-section-lma .rodata-0x80000000 \
37 --change-section-lma .data-0x80000000 \
38 --change-section-lma .init-0x80000000 \
39 --change-section-lma .bss-0x80000000 \
40 --change-section-lma .initrd-0x80000000 \
41 --change-section-lma __param-0x80000000 \
42 --change-section-lma __ksymtab-0x80000000 \
43 --change-section-lma __ksymtab_gpl-0x80000000 \
44 --change-section-lma __kcrctab-0x80000000 \
45 --change-section-lma __kcrctab_gpl-0x80000000 \
46 --change-section-lma __ksymtab_strings-0x80000000 \
47 --change-section-lma .got-0x80000000 \
48 --set-start 0xa0000000
49$(obj)/vmlinux.elf: vmlinux FORCE
50 $(call if_changed,objcopy)
51
52quiet_cmd_sfdwarf = SFDWARF $@
53 cmd_sfdwarf = sfdwarf $< TO $@ GNUAVR IW $(SFDWARF_FLAGS) > $(obj)/sfdwarf.log
54
55$(obj)/vmlinux.cso: $(obj)/vmlinux.elf FORCE
56 $(call if_changed,sfdwarf)
57
58install: $(BOOTIMAGE)
59 sh $(srctree)/install-kernel.sh $<
60
61# Generated files to be removed upon make clean
62clean-files := vmlinux* uImage uImage.srec
diff --git a/arch/avr32/boot/u-boot/Makefile b/arch/avr32/boot/u-boot/Makefile
new file mode 100644
index 000000000000..125ddc96c275
--- /dev/null
+++ b/arch/avr32/boot/u-boot/Makefile
@@ -0,0 +1,3 @@
1extra-y := head.o
2
3obj-y := empty.o
diff --git a/arch/avr32/boot/u-boot/empty.S b/arch/avr32/boot/u-boot/empty.S
new file mode 100644
index 000000000000..8ac91a5f12f0
--- /dev/null
+++ b/arch/avr32/boot/u-boot/empty.S
@@ -0,0 +1 @@
/* Empty file */
diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S
new file mode 100644
index 000000000000..4488fa27fe94
--- /dev/null
+++ b/arch/avr32/boot/u-boot/head.S
@@ -0,0 +1,60 @@
1/*
2 * Startup code for use with the u-boot bootloader.
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <asm/setup.h>
11
12 /*
13 * The kernel is loaded where we want it to be and all caches
14 * have just been flushed. We get two parameters from u-boot:
15 *
16 * r12 contains a magic number (ATAG_MAGIC)
17 * r11 points to a tag table providing information about
18 * the system.
19 */
20 .section .init.text,"ax"
21 .global _start
22_start:
23 /* Check if the boot loader actually provided a tag table */
24 lddpc r0, magic_number
25 cp.w r12, r0
26 brne no_tag_table
27
28 /* Initialize .bss */
29 lddpc r2, bss_start_addr
30 lddpc r3, end_addr
31 mov r0, 0
32 mov r1, 0
331: st.d r2++, r0
34 cp r2, r3
35 brlo 1b
36
37 /*
38 * Save the tag table address for later use. This must be done
39 * _after_ .bss has been initialized...
40 */
41 lddpc r0, tag_table_addr
42 st.w r0[0], r11
43
44 /* Jump to loader-independent setup code */
45 rjmp kernel_entry
46
47 .align 2
48magic_number:
49 .long ATAG_MAGIC
50tag_table_addr:
51 .long bootloader_tags
52bss_start_addr:
53 .long __bss_start
54end_addr:
55 .long _end
56
57no_tag_table:
58 sub r12, pc, (. - 2f)
59 bral panic
602: .asciz "Boot loader didn't provide correct magic number\n"
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
new file mode 100644
index 000000000000..1d22255009fd
--- /dev/null
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -0,0 +1,754 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.18-rc1
4# Tue Jul 11 12:41:36 2006
5#
6CONFIG_AVR32=y
7CONFIG_GENERIC_HARDIRQS=y
8CONFIG_HARDIRQS_SW_RESEND=y
9CONFIG_GENERIC_IRQ_PROBE=y
10CONFIG_RWSEM_GENERIC_SPINLOCK=y
11CONFIG_GENERIC_HWEIGHT=y
12CONFIG_GENERIC_CALIBRATE_DELAY=y
13CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
14
15#
16# Code maturity level options
17#
18CONFIG_EXPERIMENTAL=y
19CONFIG_BROKEN_ON_SMP=y
20CONFIG_INIT_ENV_ARG_LIMIT=32
21
22#
23# General setup
24#
25CONFIG_LOCALVERSION=""
26# CONFIG_LOCALVERSION_AUTO is not set
27CONFIG_SWAP=y
28# CONFIG_SYSVIPC is not set
29# CONFIG_POSIX_MQUEUE is not set
30# CONFIG_BSD_PROCESS_ACCT is not set
31CONFIG_SYSCTL=y
32# CONFIG_AUDIT is not set
33# CONFIG_IKCONFIG is not set
34# CONFIG_RELAY is not set
35CONFIG_INITRAMFS_SOURCE=""
36CONFIG_CC_OPTIMIZE_FOR_SIZE=y
37CONFIG_EMBEDDED=y
38CONFIG_KALLSYMS=y
39# CONFIG_KALLSYMS_ALL is not set
40# CONFIG_KALLSYMS_EXTRA_PASS is not set
41CONFIG_HOTPLUG=y
42CONFIG_PRINTK=y
43CONFIG_BUG=y
44CONFIG_ELF_CORE=y
45# CONFIG_BASE_FULL is not set
46# CONFIG_FUTEX is not set
47# CONFIG_EPOLL is not set
48CONFIG_SHMEM=y
49# CONFIG_SLAB is not set
50# CONFIG_VM_EVENT_COUNTERS is not set
51# CONFIG_TINY_SHMEM is not set
52CONFIG_BASE_SMALL=1
53CONFIG_SLOB=y
54
55#
56# Loadable module support
57#
58CONFIG_MODULES=y
59CONFIG_MODULE_UNLOAD=y
60# CONFIG_MODULE_FORCE_UNLOAD is not set
61# CONFIG_MODVERSIONS is not set
62# CONFIG_MODULE_SRCVERSION_ALL is not set
63# CONFIG_KMOD is not set
64
65#
66# Block layer
67#
68# CONFIG_BLK_DEV_IO_TRACE is not set
69
70#
71# IO Schedulers
72#
73CONFIG_IOSCHED_NOOP=y
74# CONFIG_IOSCHED_AS is not set
75# CONFIG_IOSCHED_DEADLINE is not set
76# CONFIG_IOSCHED_CFQ is not set
77# CONFIG_DEFAULT_AS is not set
78# CONFIG_DEFAULT_DEADLINE is not set
79# CONFIG_DEFAULT_CFQ is not set
80CONFIG_DEFAULT_NOOP=y
81CONFIG_DEFAULT_IOSCHED="noop"
82
83#
84# System Type and features
85#
86CONFIG_SUBARCH_AVR32B=y
87CONFIG_MMU=y
88CONFIG_PERFORMANCE_COUNTERS=y
89CONFIG_PLATFORM_AT32AP=y
90CONFIG_CPU_AT32AP7000=y
91CONFIG_BOARD_ATSTK1002=y
92CONFIG_BOARD_ATSTK1000=y
93CONFIG_LOADER_U_BOOT=y
94CONFIG_LOAD_ADDRESS=0x10000000
95CONFIG_ENTRY_ADDRESS=0x90000000
96CONFIG_PHYS_OFFSET=0x10000000
97CONFIG_PREEMPT_NONE=y
98# CONFIG_PREEMPT_VOLUNTARY is not set
99# CONFIG_PREEMPT is not set
100# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set
101# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set
102# CONFIG_NEED_NODE_MEMMAP_SIZE is not set
103CONFIG_ARCH_FLATMEM_ENABLE=y
104# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
105# CONFIG_ARCH_SPARSEMEM_ENABLE is not set
106CONFIG_SELECT_MEMORY_MODEL=y
107CONFIG_FLATMEM_MANUAL=y
108# CONFIG_DISCONTIGMEM_MANUAL is not set
109# CONFIG_SPARSEMEM_MANUAL is not set
110CONFIG_FLATMEM=y
111CONFIG_FLAT_NODE_MEM_MAP=y
112# CONFIG_SPARSEMEM_STATIC is not set
113CONFIG_SPLIT_PTLOCK_CPUS=4
114# CONFIG_RESOURCES_64BIT is not set
115# CONFIG_OWNERSHIP_TRACE is not set
116# CONFIG_HZ_100 is not set
117CONFIG_HZ_250=y
118# CONFIG_HZ_1000 is not set
119CONFIG_HZ=250
120CONFIG_CMDLINE=""
121
122#
123# Bus options
124#
125
126#
127# PCCARD (PCMCIA/CardBus) support
128#
129# CONFIG_PCCARD is not set
130
131#
132# Executable file formats
133#
134CONFIG_BINFMT_ELF=y
135# CONFIG_BINFMT_MISC is not set
136
137#
138# Networking
139#
140CONFIG_NET=y
141
142#
143# Networking options
144#
145# CONFIG_NETDEBUG is not set
146CONFIG_PACKET=y
147CONFIG_PACKET_MMAP=y
148CONFIG_UNIX=y
149# CONFIG_NET_KEY is not set
150CONFIG_INET=y
151# CONFIG_IP_MULTICAST is not set
152# CONFIG_IP_ADVANCED_ROUTER is not set
153CONFIG_IP_FIB_HASH=y
154CONFIG_IP_PNP=y
155CONFIG_IP_PNP_DHCP=y
156# CONFIG_IP_PNP_BOOTP is not set
157# CONFIG_IP_PNP_RARP is not set
158# CONFIG_NET_IPIP is not set
159# CONFIG_NET_IPGRE is not set
160# CONFIG_ARPD is not set
161# CONFIG_SYN_COOKIES is not set
162# CONFIG_INET_AH is not set
163# CONFIG_INET_ESP is not set
164# CONFIG_INET_IPCOMP is not set
165# CONFIG_INET_XFRM_TUNNEL is not set
166# CONFIG_INET_TUNNEL is not set
167# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
168# CONFIG_INET_XFRM_MODE_TUNNEL is not set
169CONFIG_INET_DIAG=y
170CONFIG_INET_TCP_DIAG=y
171# CONFIG_TCP_CONG_ADVANCED is not set
172CONFIG_TCP_CONG_BIC=y
173# CONFIG_IPV6 is not set
174# CONFIG_INET6_XFRM_TUNNEL is not set
175# CONFIG_INET6_TUNNEL is not set
176# CONFIG_NETWORK_SECMARK is not set
177# CONFIG_NETFILTER is not set
178
179#
180# DCCP Configuration (EXPERIMENTAL)
181#
182# CONFIG_IP_DCCP is not set
183
184#
185# SCTP Configuration (EXPERIMENTAL)
186#
187# CONFIG_IP_SCTP is not set
188
189#
190# TIPC Configuration (EXPERIMENTAL)
191#
192# CONFIG_TIPC is not set
193# CONFIG_ATM is not set
194# CONFIG_BRIDGE is not set
195# CONFIG_VLAN_8021Q is not set
196# CONFIG_DECNET is not set
197# CONFIG_LLC2 is not set
198# CONFIG_IPX is not set
199# CONFIG_ATALK is not set
200# CONFIG_X25 is not set
201# CONFIG_LAPB is not set
202# CONFIG_NET_DIVERT is not set
203# CONFIG_ECONET is not set
204# CONFIG_WAN_ROUTER is not set
205
206#
207# QoS and/or fair queueing
208#
209# CONFIG_NET_SCHED is not set
210
211#
212# Network testing
213#
214# CONFIG_NET_PKTGEN is not set
215# CONFIG_NET_TCPPROBE is not set
216# CONFIG_HAMRADIO is not set
217# CONFIG_IRDA is not set
218# CONFIG_BT is not set
219# CONFIG_IEEE80211 is not set
220
221#
222# Device Drivers
223#
224
225#
226# Generic Driver Options
227#
228CONFIG_STANDALONE=y
229# CONFIG_PREVENT_FIRMWARE_BUILD is not set
230# CONFIG_FW_LOADER is not set
231# CONFIG_DEBUG_DRIVER is not set
232# CONFIG_SYS_HYPERVISOR is not set
233
234#
235# Connector - unified userspace <-> kernelspace linker
236#
237# CONFIG_CONNECTOR is not set
238
239#
240# Memory Technology Devices (MTD)
241#
242# CONFIG_MTD is not set
243
244#
245# Parallel port support
246#
247# CONFIG_PARPORT is not set
248
249#
250# Plug and Play support
251#
252
253#
254# Block devices
255#
256# CONFIG_BLK_DEV_COW_COMMON is not set
257CONFIG_BLK_DEV_LOOP=m
258# CONFIG_BLK_DEV_CRYPTOLOOP is not set
259CONFIG_BLK_DEV_NBD=m
260CONFIG_BLK_DEV_RAM=m
261CONFIG_BLK_DEV_RAM_COUNT=16
262CONFIG_BLK_DEV_RAM_SIZE=4096
263CONFIG_BLK_DEV_INITRD=y
264# CONFIG_CDROM_PKTCDVD is not set
265# CONFIG_ATA_OVER_ETH is not set
266
267#
268# ATA/ATAPI/MFM/RLL support
269#
270# CONFIG_IDE is not set
271
272#
273# SCSI device support
274#
275# CONFIG_RAID_ATTRS is not set
276# CONFIG_SCSI is not set
277
278#
279# Multi-device support (RAID and LVM)
280#
281# CONFIG_MD is not set
282
283#
284# Fusion MPT device support
285#
286# CONFIG_FUSION is not set
287
288#
289# IEEE 1394 (FireWire) support
290#
291
292#
293# I2O device support
294#
295
296#
297# Network device support
298#
299CONFIG_NETDEVICES=y
300CONFIG_DUMMY=y
301# CONFIG_BONDING is not set
302# CONFIG_EQUALIZER is not set
303CONFIG_TUN=m
304
305#
306# PHY device support
307#
308# CONFIG_PHYLIB is not set
309
310#
311# Ethernet (10 or 100Mbit)
312#
313CONFIG_NET_ETHERNET=y
314CONFIG_MII=y
315CONFIG_MACB=y
316
317#
318# Ethernet (1000 Mbit)
319#
320
321#
322# Ethernet (10000 Mbit)
323#
324
325#
326# Token Ring devices
327#
328
329#
330# Wireless LAN (non-hamradio)
331#
332# CONFIG_NET_RADIO is not set
333
334#
335# Wan interfaces
336#
337# CONFIG_WAN is not set
338CONFIG_PPP=m
339# CONFIG_PPP_MULTILINK is not set
340# CONFIG_PPP_FILTER is not set
341CONFIG_PPP_ASYNC=m
342# CONFIG_PPP_SYNC_TTY is not set
343CONFIG_PPP_DEFLATE=m
344# CONFIG_PPP_BSDCOMP is not set
345# CONFIG_PPP_MPPE is not set
346# CONFIG_PPPOE is not set
347# CONFIG_SLIP is not set
348# CONFIG_SHAPER is not set
349# CONFIG_NETCONSOLE is not set
350# CONFIG_NETPOLL is not set
351# CONFIG_NET_POLL_CONTROLLER is not set
352
353#
354# ISDN subsystem
355#
356# CONFIG_ISDN is not set
357
358#
359# Telephony Support
360#
361# CONFIG_PHONE is not set
362
363#
364# Input device support
365#
366# CONFIG_INPUT is not set
367
368#
369# Hardware I/O ports
370#
371# CONFIG_SERIO is not set
372# CONFIG_GAMEPORT is not set
373
374#
375# Character devices
376#
377# CONFIG_VT is not set
378# CONFIG_SERIAL_NONSTANDARD is not set
379
380#
381# Serial drivers
382#
383# CONFIG_SERIAL_8250 is not set
384
385#
386# Non-8250 serial port support
387#
388CONFIG_SERIAL_AT91=y
389CONFIG_SERIAL_AT91_CONSOLE=y
390# CONFIG_SERIAL_AT91_TTYAT is not set
391CONFIG_SERIAL_CORE=y
392CONFIG_SERIAL_CORE_CONSOLE=y
393CONFIG_UNIX98_PTYS=y
394# CONFIG_LEGACY_PTYS is not set
395
396#
397# IPMI
398#
399# CONFIG_IPMI_HANDLER is not set
400
401#
402# Watchdog Cards
403#
404# CONFIG_WATCHDOG is not set
405# CONFIG_HW_RANDOM is not set
406# CONFIG_RTC is not set
407# CONFIG_GEN_RTC is not set
408# CONFIG_DTLK is not set
409# CONFIG_R3964 is not set
410
411#
412# Ftape, the floppy tape device driver
413#
414# CONFIG_RAW_DRIVER is not set
415
416#
417# TPM devices
418#
419# CONFIG_TCG_TPM is not set
420# CONFIG_TELCLOCK is not set
421
422#
423# I2C support
424#
425# CONFIG_I2C is not set
426
427#
428# SPI support
429#
430CONFIG_SPI=y
431# CONFIG_SPI_DEBUG is not set
432CONFIG_SPI_MASTER=y
433
434#
435# SPI Master Controller Drivers
436#
437CONFIG_SPI_ATMEL=m
438# CONFIG_SPI_BITBANG is not set
439
440#
441# SPI Protocol Masters
442#
443
444#
445# Dallas's 1-wire bus
446#
447
448#
449# Hardware Monitoring support
450#
451# CONFIG_HWMON is not set
452# CONFIG_HWMON_VID is not set
453
454#
455# Misc devices
456#
457
458#
459# Multimedia devices
460#
461# CONFIG_VIDEO_DEV is not set
462CONFIG_VIDEO_V4L2=y
463
464#
465# Digital Video Broadcasting Devices
466#
467# CONFIG_DVB is not set
468
469#
470# Graphics support
471#
472# CONFIG_FIRMWARE_EDID is not set
473CONFIG_FB=m
474CONFIG_FB_CFB_FILLRECT=m
475CONFIG_FB_CFB_COPYAREA=m
476CONFIG_FB_CFB_IMAGEBLIT=m
477# CONFIG_FB_MACMODES is not set
478# CONFIG_FB_BACKLIGHT is not set
479# CONFIG_FB_MODE_HELPERS is not set
480# CONFIG_FB_TILEBLITTING is not set
481CONFIG_FB_SIDSA=m
482CONFIG_FB_SIDSA_DEFAULT_BPP=24
483# CONFIG_FB_S1D13XXX is not set
484# CONFIG_FB_VIRTUAL is not set
485
486#
487# Logo configuration
488#
489# CONFIG_LOGO is not set
490CONFIG_BACKLIGHT_LCD_SUPPORT=y
491# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
492CONFIG_LCD_CLASS_DEVICE=m
493CONFIG_LCD_DEVICE=y
494CONFIG_LCD_LTV350QV=m
495
496#
497# Sound
498#
499# CONFIG_SOUND is not set
500
501#
502# USB support
503#
504# CONFIG_USB_ARCH_HAS_HCD is not set
505# CONFIG_USB_ARCH_HAS_OHCI is not set
506# CONFIG_USB_ARCH_HAS_EHCI is not set
507
508#
509# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
510#
511
512#
513# USB Gadget Support
514#
515# CONFIG_USB_GADGET is not set
516
517#
518# MMC/SD Card support
519#
520# CONFIG_MMC is not set
521
522#
523# LED devices
524#
525# CONFIG_NEW_LEDS is not set
526
527#
528# LED drivers
529#
530
531#
532# LED Triggers
533#
534
535#
536# InfiniBand support
537#
538
539#
540# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
541#
542
543#
544# Real Time Clock
545#
546# CONFIG_RTC_CLASS is not set
547
548#
549# DMA Engine support
550#
551# CONFIG_DMA_ENGINE is not set
552
553#
554# DMA Clients
555#
556
557#
558# DMA Devices
559#
560
561#
562# File systems
563#
564CONFIG_EXT2_FS=y
565# CONFIG_EXT2_FS_XATTR is not set
566# CONFIG_EXT2_FS_XIP is not set
567# CONFIG_EXT3_FS is not set
568# CONFIG_REISERFS_FS is not set
569# CONFIG_JFS_FS is not set
570# CONFIG_FS_POSIX_ACL is not set
571# CONFIG_XFS_FS is not set
572# CONFIG_OCFS2_FS is not set
573CONFIG_MINIX_FS=m
574CONFIG_ROMFS_FS=m
575# CONFIG_INOTIFY is not set
576# CONFIG_QUOTA is not set
577# CONFIG_DNOTIFY is not set
578# CONFIG_AUTOFS_FS is not set
579# CONFIG_AUTOFS4_FS is not set
580# CONFIG_FUSE_FS is not set
581
582#
583# CD-ROM/DVD Filesystems
584#
585# CONFIG_ISO9660_FS is not set
586# CONFIG_UDF_FS is not set
587
588#
589# DOS/FAT/NT Filesystems
590#
591CONFIG_FAT_FS=m
592CONFIG_MSDOS_FS=m
593CONFIG_VFAT_FS=m
594CONFIG_FAT_DEFAULT_CODEPAGE=437
595CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
596# CONFIG_NTFS_FS is not set
597
598#
599# Pseudo filesystems
600#
601CONFIG_PROC_FS=y
602CONFIG_PROC_KCORE=y
603CONFIG_SYSFS=y
604CONFIG_TMPFS=y
605# CONFIG_HUGETLB_PAGE is not set
606CONFIG_RAMFS=y
607CONFIG_CONFIGFS_FS=m
608
609#
610# Miscellaneous filesystems
611#
612# CONFIG_ADFS_FS is not set
613# CONFIG_AFFS_FS is not set
614# CONFIG_HFS_FS is not set
615# CONFIG_HFSPLUS_FS is not set
616# CONFIG_BEFS_FS is not set
617# CONFIG_BFS_FS is not set
618# CONFIG_EFS_FS is not set
619# CONFIG_CRAMFS is not set
620# CONFIG_VXFS_FS is not set
621# CONFIG_HPFS_FS is not set
622# CONFIG_QNX4FS_FS is not set
623# CONFIG_SYSV_FS is not set
624# CONFIG_UFS_FS is not set
625
626#
627# Network File Systems
628#
629CONFIG_NFS_FS=y
630CONFIG_NFS_V3=y
631# CONFIG_NFS_V3_ACL is not set
632# CONFIG_NFS_V4 is not set
633# CONFIG_NFS_DIRECTIO is not set
634# CONFIG_NFSD is not set
635CONFIG_ROOT_NFS=y
636CONFIG_LOCKD=y
637CONFIG_LOCKD_V4=y
638CONFIG_NFS_COMMON=y
639CONFIG_SUNRPC=y
640# CONFIG_RPCSEC_GSS_KRB5 is not set
641# CONFIG_RPCSEC_GSS_SPKM3 is not set
642# CONFIG_SMB_FS is not set
643CONFIG_CIFS=m
644# CONFIG_CIFS_STATS is not set
645# CONFIG_CIFS_WEAK_PW_HASH is not set
646# CONFIG_CIFS_XATTR is not set
647# CONFIG_CIFS_DEBUG2 is not set
648# CONFIG_CIFS_EXPERIMENTAL is not set
649# CONFIG_NCP_FS is not set
650# CONFIG_CODA_FS is not set
651# CONFIG_AFS_FS is not set
652# CONFIG_9P_FS is not set
653
654#
655# Partition Types
656#
657# CONFIG_PARTITION_ADVANCED is not set
658CONFIG_MSDOS_PARTITION=y
659
660#
661# Native Language Support
662#
663CONFIG_NLS=m
664CONFIG_NLS_DEFAULT="iso8859-1"
665CONFIG_NLS_CODEPAGE_437=m
666# CONFIG_NLS_CODEPAGE_737 is not set
667# CONFIG_NLS_CODEPAGE_775 is not set
668CONFIG_NLS_CODEPAGE_850=m
669# CONFIG_NLS_CODEPAGE_852 is not set
670# CONFIG_NLS_CODEPAGE_855 is not set
671# CONFIG_NLS_CODEPAGE_857 is not set
672# CONFIG_NLS_CODEPAGE_860 is not set
673# CONFIG_NLS_CODEPAGE_861 is not set
674# CONFIG_NLS_CODEPAGE_862 is not set
675# CONFIG_NLS_CODEPAGE_863 is not set
676# CONFIG_NLS_CODEPAGE_864 is not set
677# CONFIG_NLS_CODEPAGE_865 is not set
678# CONFIG_NLS_CODEPAGE_866 is not set
679# CONFIG_NLS_CODEPAGE_869 is not set
680# CONFIG_NLS_CODEPAGE_936 is not set
681# CONFIG_NLS_CODEPAGE_950 is not set
682# CONFIG_NLS_CODEPAGE_932 is not set
683# CONFIG_NLS_CODEPAGE_949 is not set
684# CONFIG_NLS_CODEPAGE_874 is not set
685# CONFIG_NLS_ISO8859_8 is not set
686# CONFIG_NLS_CODEPAGE_1250 is not set
687# CONFIG_NLS_CODEPAGE_1251 is not set
688# CONFIG_NLS_ASCII is not set
689CONFIG_NLS_ISO8859_1=m
690# CONFIG_NLS_ISO8859_2 is not set
691# CONFIG_NLS_ISO8859_3 is not set
692# CONFIG_NLS_ISO8859_4 is not set
693# CONFIG_NLS_ISO8859_5 is not set
694# CONFIG_NLS_ISO8859_6 is not set
695# CONFIG_NLS_ISO8859_7 is not set
696# CONFIG_NLS_ISO8859_9 is not set
697# CONFIG_NLS_ISO8859_13 is not set
698# CONFIG_NLS_ISO8859_14 is not set
699# CONFIG_NLS_ISO8859_15 is not set
700# CONFIG_NLS_KOI8_R is not set
701# CONFIG_NLS_KOI8_U is not set
702CONFIG_NLS_UTF8=m
703
704#
705# Kernel hacking
706#
707CONFIG_TRACE_IRQFLAGS_SUPPORT=y
708CONFIG_PRINTK_TIME=y
709CONFIG_MAGIC_SYSRQ=y
710# CONFIG_UNUSED_SYMBOLS is not set
711CONFIG_DEBUG_KERNEL=y
712CONFIG_LOG_BUF_SHIFT=14
713CONFIG_DETECT_SOFTLOCKUP=y
714# CONFIG_SCHEDSTATS is not set
715# CONFIG_DEBUG_SPINLOCK is not set
716# CONFIG_DEBUG_MUTEXES is not set
717# CONFIG_DEBUG_RWSEMS is not set
718# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
719# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
720# CONFIG_DEBUG_KOBJECT is not set
721CONFIG_DEBUG_BUGVERBOSE=y
722# CONFIG_DEBUG_INFO is not set
723CONFIG_DEBUG_FS=y
724# CONFIG_DEBUG_VM is not set
725CONFIG_FRAME_POINTER=y
726# CONFIG_UNWIND_INFO is not set
727CONFIG_FORCED_INLINING=y
728# CONFIG_RCU_TORTURE_TEST is not set
729CONFIG_KPROBES=y
730
731#
732# Security options
733#
734# CONFIG_KEYS is not set
735# CONFIG_SECURITY is not set
736
737#
738# Cryptographic options
739#
740# CONFIG_CRYPTO is not set
741
742#
743# Hardware crypto devices
744#
745
746#
747# Library routines
748#
749CONFIG_CRC_CCITT=m
750# CONFIG_CRC16 is not set
751CONFIG_CRC32=m
752# CONFIG_LIBCRC32C is not set
753CONFIG_ZLIB_INFLATE=m
754CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
new file mode 100644
index 000000000000..90e5afff54a2
--- /dev/null
+++ b/arch/avr32/kernel/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the Linux/AVR32 kernel.
3#
4
5extra-y := head.o vmlinux.lds
6
7obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
8obj-y += syscall_table.o syscall-stubs.o irq.o
9obj-y += setup.o traps.o semaphore.o ptrace.o
10obj-y += signal.o sys_avr32.o process.o time.o
11obj-y += init_task.o switch_to.o cpu.o
12obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
13obj-$(CONFIG_KPROBES) += kprobes.o
14
15USE_STANDARD_AS_RULE := true
16
17%.lds: %.lds.c FORCE
18 $(call if_changed_dep,cpp_lds_S)
diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c
new file mode 100644
index 000000000000..97d865865667
--- /dev/null
+++ b/arch/avr32/kernel/asm-offsets.c
@@ -0,0 +1,25 @@
1/*
2 * Generate definitions needed by assembly language modules.
3 * This code generates raw asm output which is post-processed
4 * to extract and format the required data.
5 */
6
7#include <linux/thread_info.h>
8
9#define DEFINE(sym, val) \
10 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
11
12#define BLANK() asm volatile("\n->" : : )
13
14#define OFFSET(sym, str, mem) \
15 DEFINE(sym, offsetof(struct str, mem));
16
17void foo(void)
18{
19 OFFSET(TI_task, thread_info, task);
20 OFFSET(TI_exec_domain, thread_info, exec_domain);
21 OFFSET(TI_flags, thread_info, flags);
22 OFFSET(TI_cpu, thread_info, cpu);
23 OFFSET(TI_preempt_count, thread_info, preempt_count);
24 OFFSET(TI_restart_block, thread_info, restart_block);
25}
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
new file mode 100644
index 000000000000..04f767a272b7
--- /dev/null
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -0,0 +1,55 @@
1/*
2 * Export AVR32-specific functions for loadable modules.
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/module.h>
11
12#include <asm/checksum.h>
13#include <asm/uaccess.h>
14#include <asm/delay.h>
15
16/*
17 * GCC functions
18 */
19extern unsigned long long __avr32_lsl64(unsigned long long u, unsigned long b);
20extern unsigned long long __avr32_lsr64(unsigned long long u, unsigned long b);
21extern unsigned long long __avr32_asr64(unsigned long long u, unsigned long b);
22EXPORT_SYMBOL(__avr32_lsl64);
23EXPORT_SYMBOL(__avr32_lsr64);
24EXPORT_SYMBOL(__avr32_asr64);
25
26/*
27 * String functions
28 */
29EXPORT_SYMBOL(memset);
30EXPORT_SYMBOL(memcpy);
31
32/*
33 * Userspace access stuff.
34 */
35EXPORT_SYMBOL(copy_from_user);
36EXPORT_SYMBOL(copy_to_user);
37EXPORT_SYMBOL(__copy_user);
38EXPORT_SYMBOL(strncpy_from_user);
39EXPORT_SYMBOL(__strncpy_from_user);
40EXPORT_SYMBOL(clear_user);
41EXPORT_SYMBOL(__clear_user);
42EXPORT_SYMBOL(csum_partial);
43EXPORT_SYMBOL(csum_partial_copy_generic);
44
45/* Delay loops (lib/delay.S) */
46EXPORT_SYMBOL(__ndelay);
47EXPORT_SYMBOL(__udelay);
48EXPORT_SYMBOL(__const_udelay);
49
50/* Bit operations (lib/findbit.S) */
51EXPORT_SYMBOL(find_first_zero_bit);
52EXPORT_SYMBOL(find_next_zero_bit);
53EXPORT_SYMBOL(find_first_bit);
54EXPORT_SYMBOL(find_next_bit);
55EXPORT_SYMBOL(generic_find_next_zero_le_bit);
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
new file mode 100644
index 000000000000..342452ba2049
--- /dev/null
+++ b/arch/avr32/kernel/cpu.c
@@ -0,0 +1,327 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/init.h>
9#include <linux/sysdev.h>
10#include <linux/seq_file.h>
11#include <linux/cpu.h>
12#include <linux/percpu.h>
13#include <linux/param.h>
14#include <linux/errno.h>
15
16#include <asm/setup.h>
17#include <asm/sysreg.h>
18
19static DEFINE_PER_CPU(struct cpu, cpu_devices);
20
21#ifdef CONFIG_PERFORMANCE_COUNTERS
22
23/*
24 * XXX: If/when a SMP-capable implementation of AVR32 will ever be
25 * made, we must make sure that the code executes on the correct CPU.
26 */
27static ssize_t show_pc0event(struct sys_device *dev, char *buf)
28{
29 unsigned long pccr;
30
31 pccr = sysreg_read(PCCR);
32 return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
33}
34static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
35 size_t count)
36{
37 unsigned long val;
38 char *endp;
39
40 val = simple_strtoul(buf, &endp, 0);
41 if (endp == buf || val > 0x3f)
42 return -EINVAL;
43 val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff);
44 sysreg_write(PCCR, val);
45 return count;
46}
47static ssize_t show_pc0count(struct sys_device *dev, char *buf)
48{
49 unsigned long pcnt0;
50
51 pcnt0 = sysreg_read(PCNT0);
52 return sprintf(buf, "%lu\n", pcnt0);
53}
54static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
55 size_t count)
56{
57 unsigned long val;
58 char *endp;
59
60 val = simple_strtoul(buf, &endp, 0);
61 if (endp == buf)
62 return -EINVAL;
63 sysreg_write(PCNT0, val);
64
65 return count;
66}
67
68static ssize_t show_pc1event(struct sys_device *dev, char *buf)
69{
70 unsigned long pccr;
71
72 pccr = sysreg_read(PCCR);
73 return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
74}
75static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
76 size_t count)
77{
78 unsigned long val;
79 char *endp;
80
81 val = simple_strtoul(buf, &endp, 0);
82 if (endp == buf || val > 0x3f)
83 return -EINVAL;
84 val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff);
85 sysreg_write(PCCR, val);
86 return count;
87}
88static ssize_t show_pc1count(struct sys_device *dev, char *buf)
89{
90 unsigned long pcnt1;
91
92 pcnt1 = sysreg_read(PCNT1);
93 return sprintf(buf, "%lu\n", pcnt1);
94}
95static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
96 size_t count)
97{
98 unsigned long val;
99 char *endp;
100
101 val = simple_strtoul(buf, &endp, 0);
102 if (endp == buf)
103 return -EINVAL;
104 sysreg_write(PCNT1, val);
105
106 return count;
107}
108
109static ssize_t show_pccycles(struct sys_device *dev, char *buf)
110{
111 unsigned long pccnt;
112
113 pccnt = sysreg_read(PCCNT);
114 return sprintf(buf, "%lu\n", pccnt);
115}
116static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
117 size_t count)
118{
119 unsigned long val;
120 char *endp;
121
122 val = simple_strtoul(buf, &endp, 0);
123 if (endp == buf)
124 return -EINVAL;
125 sysreg_write(PCCNT, val);
126
127 return count;
128}
129
130static ssize_t show_pcenable(struct sys_device *dev, char *buf)
131{
132 unsigned long pccr;
133
134 pccr = sysreg_read(PCCR);
135 return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
136}
137static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
138 size_t count)
139{
140 unsigned long pccr, val;
141 char *endp;
142
143 val = simple_strtoul(buf, &endp, 0);
144 if (endp == buf)
145 return -EINVAL;
146 if (val)
147 val = 1;
148
149 pccr = sysreg_read(PCCR);
150 pccr = (pccr & ~1UL) | val;
151 sysreg_write(PCCR, pccr);
152
153 return count;
154}
155
156static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
157static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
158static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
159static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
160static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
161static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
162
163#endif /* CONFIG_PERFORMANCE_COUNTERS */
164
165static int __init topology_init(void)
166{
167 int cpu;
168
169 for_each_possible_cpu(cpu) {
170 struct cpu *c = &per_cpu(cpu_devices, cpu);
171
172 register_cpu(c, cpu);
173
174#ifdef CONFIG_PERFORMANCE_COUNTERS
175 sysdev_create_file(&c->sysdev, &attr_pc0event);
176 sysdev_create_file(&c->sysdev, &attr_pc0count);
177 sysdev_create_file(&c->sysdev, &attr_pc1event);
178 sysdev_create_file(&c->sysdev, &attr_pc1count);
179 sysdev_create_file(&c->sysdev, &attr_pccycles);
180 sysdev_create_file(&c->sysdev, &attr_pcenable);
181#endif
182 }
183
184 return 0;
185}
186
187subsys_initcall(topology_init);
188
189static const char *cpu_names[] = {
190 "Morgan",
191 "AP7000",
192};
193#define NR_CPU_NAMES ARRAY_SIZE(cpu_names)
194
195static const char *arch_names[] = {
196 "AVR32A",
197 "AVR32B",
198};
199#define NR_ARCH_NAMES ARRAY_SIZE(arch_names)
200
201static const char *mmu_types[] = {
202 "No MMU",
203 "ITLB and DTLB",
204 "Shared TLB",
205 "MPU"
206};
207
208void __init setup_processor(void)
209{
210 unsigned long config0, config1;
211 unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type;
212 unsigned tmp;
213
214 config0 = sysreg_read(CONFIG0); /* 0x0000013e; */
215 config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */
216 cpu_id = config0 >> 24;
217 cpu_rev = (config0 >> 16) & 0xff;
218 arch_id = (config0 >> 13) & 0x07;
219 arch_rev = (config0 >> 10) & 0x07;
220 mmu_type = (config0 >> 7) & 0x03;
221
222 boot_cpu_data.arch_type = arch_id;
223 boot_cpu_data.cpu_type = cpu_id;
224 boot_cpu_data.arch_revision = arch_rev;
225 boot_cpu_data.cpu_revision = cpu_rev;
226 boot_cpu_data.tlb_config = mmu_type;
227
228 tmp = (config1 >> 13) & 0x07;
229 if (tmp) {
230 boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07);
231 boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f);
232 boot_cpu_data.icache.linesz = 1 << (tmp + 1);
233 }
234 tmp = (config1 >> 3) & 0x07;
235 if (tmp) {
236 boot_cpu_data.dcache.ways = 1 << (config1 & 0x07);
237 boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f);
238 boot_cpu_data.dcache.linesz = 1 << (tmp + 1);
239 }
240
241 if ((cpu_id >= NR_CPU_NAMES) || (arch_id >= NR_ARCH_NAMES)) {
242 printk ("Unknown CPU configuration (ID %02x, arch %02x), "
243 "continuing anyway...\n",
244 cpu_id, arch_id);
245 return;
246 }
247
248 printk ("CPU: %s [%02x] revision %d (%s revision %d)\n",
249 cpu_names[cpu_id], cpu_id, cpu_rev,
250 arch_names[arch_id], arch_rev);
251 printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]);
252 printk ("CPU: features:");
253 if (config0 & (1 << 6))
254 printk(" fpu");
255 if (config0 & (1 << 5))
256 printk(" java");
257 if (config0 & (1 << 4))
258 printk(" perfctr");
259 if (config0 & (1 << 3))
260 printk(" ocd");
261 printk("\n");
262}
263
264#ifdef CONFIG_PROC_FS
265static int c_show(struct seq_file *m, void *v)
266{
267 unsigned int icache_size, dcache_size;
268 unsigned int cpu = smp_processor_id();
269
270 icache_size = boot_cpu_data.icache.ways *
271 boot_cpu_data.icache.sets *
272 boot_cpu_data.icache.linesz;
273 dcache_size = boot_cpu_data.dcache.ways *
274 boot_cpu_data.dcache.sets *
275 boot_cpu_data.dcache.linesz;
276
277 seq_printf(m, "processor\t: %d\n", cpu);
278
279 if (boot_cpu_data.arch_type < NR_ARCH_NAMES)
280 seq_printf(m, "cpu family\t: %s revision %d\n",
281 arch_names[boot_cpu_data.arch_type],
282 boot_cpu_data.arch_revision);
283 if (boot_cpu_data.cpu_type < NR_CPU_NAMES)
284 seq_printf(m, "cpu type\t: %s revision %d\n",
285 cpu_names[boot_cpu_data.cpu_type],
286 boot_cpu_data.cpu_revision);
287
288 seq_printf(m, "i-cache\t\t: %dK (%u ways x %u sets x %u)\n",
289 icache_size >> 10,
290 boot_cpu_data.icache.ways,
291 boot_cpu_data.icache.sets,
292 boot_cpu_data.icache.linesz);
293 seq_printf(m, "d-cache\t\t: %dK (%u ways x %u sets x %u)\n",
294 dcache_size >> 10,
295 boot_cpu_data.dcache.ways,
296 boot_cpu_data.dcache.sets,
297 boot_cpu_data.dcache.linesz);
298 seq_printf(m, "bogomips\t: %lu.%02lu\n",
299 boot_cpu_data.loops_per_jiffy / (500000/HZ),
300 (boot_cpu_data.loops_per_jiffy / (5000/HZ)) % 100);
301
302 return 0;
303}
304
305static void *c_start(struct seq_file *m, loff_t *pos)
306{
307 return *pos < 1 ? (void *)1 : NULL;
308}
309
310static void *c_next(struct seq_file *m, void *v, loff_t *pos)
311{
312 ++*pos;
313 return NULL;
314}
315
316static void c_stop(struct seq_file *m, void *v)
317{
318
319}
320
321struct seq_operations cpuinfo_op = {
322 .start = c_start,
323 .next = c_next,
324 .stop = c_stop,
325 .show = c_show
326};
327#endif /* CONFIG_PROC_FS */
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
new file mode 100644
index 000000000000..eeb66792bc37
--- /dev/null
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -0,0 +1,678 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/*
10 * This file contains the low-level entry-points into the kernel, that is,
11 * exception handlers, debug trap handlers, interrupt handlers and the
12 * system call handler.
13 */
14#include <linux/errno.h>
15
16#include <asm/asm.h>
17#include <asm/hardirq.h>
18#include <asm/irq.h>
19#include <asm/ocd.h>
20#include <asm/page.h>
21#include <asm/pgtable.h>
22#include <asm/ptrace.h>
23#include <asm/sysreg.h>
24#include <asm/thread_info.h>
25#include <asm/unistd.h>
26
27#ifdef CONFIG_PREEMPT
28# define preempt_stop mask_interrupts
29#else
30# define preempt_stop
31# define fault_resume_kernel fault_restore_all
32#endif
33
34#define __MASK(x) ((1 << (x)) - 1)
35#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
36 (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
37
38 .section .ex.text,"ax",@progbits
39 .align 2
40exception_vectors:
41 bral handle_critical
42 .align 2
43 bral handle_critical
44 .align 2
45 bral do_bus_error_write
46 .align 2
47 bral do_bus_error_read
48 .align 2
49 bral do_nmi_ll
50 .align 2
51 bral handle_address_fault
52 .align 2
53 bral handle_protection_fault
54 .align 2
55 bral handle_debug
56 .align 2
57 bral do_illegal_opcode_ll
58 .align 2
59 bral do_illegal_opcode_ll
60 .align 2
61 bral do_illegal_opcode_ll
62 .align 2
63 bral do_fpe_ll
64 .align 2
65 bral do_illegal_opcode_ll
66 .align 2
67 bral handle_address_fault
68 .align 2
69 bral handle_address_fault
70 .align 2
71 bral handle_protection_fault
72 .align 2
73 bral handle_protection_fault
74 .align 2
75 bral do_dtlb_modified
76
77 /*
78 * r0 : PGD/PT/PTE
79 * r1 : Offending address
80 * r2 : Scratch register
81 * r3 : Cause (5, 12 or 13)
82 */
83#define tlbmiss_save pushm r0-r3
84#define tlbmiss_restore popm r0-r3
85
86 .section .tlbx.ex.text,"ax",@progbits
87 .global itlb_miss
88itlb_miss:
89 tlbmiss_save
90 rjmp tlb_miss_common
91
92 .section .tlbr.ex.text,"ax",@progbits
93dtlb_miss_read:
94 tlbmiss_save
95 rjmp tlb_miss_common
96
97 .section .tlbw.ex.text,"ax",@progbits
98dtlb_miss_write:
99 tlbmiss_save
100
101 .global tlb_miss_common
102tlb_miss_common:
103 mfsr r0, SYSREG_PTBR
104 mfsr r1, SYSREG_TLBEAR
105
106 /* Is it the vmalloc space? */
107 bld r1, 31
108 brcs handle_vmalloc_miss
109
110 /* First level lookup */
111pgtbl_lookup:
112 lsr r2, r1, PGDIR_SHIFT
113 ld.w r0, r0[r2 << 2]
114 bld r0, _PAGE_BIT_PRESENT
115 brcc page_table_not_present
116
117 /* TODO: Check access rights on page table if necessary */
118
119 /* Translate to virtual address in P1. */
120 andl r0, 0xf000
121 sbr r0, 31
122
123 /* Second level lookup */
124 lsl r1, (32 - PGDIR_SHIFT)
125 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
126 add r2, r0, r1 << 2
127 ld.w r1, r2[0]
128 bld r1, _PAGE_BIT_PRESENT
129 brcc page_not_present
130
131 /* Mark the page as accessed */
132 sbr r1, _PAGE_BIT_ACCESSED
133 st.w r2[0], r1
134
135 /* Drop software flags */
136 andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
137 mtsr SYSREG_TLBELO, r1
138
139 /* Figure out which entry we want to replace */
140 mfsr r0, SYSREG_TLBARLO
141 clz r2, r0
142 brcc 1f
143 mov r1, -1 /* All entries have been accessed, */
144 mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
145 mov r2, 0 /* and start at 0 */
1461: mfsr r1, SYSREG_MMUCR
147 lsl r2, 14
148 andl r1, 0x3fff, COH
149 or r1, r2
150 mtsr SYSREG_MMUCR, r1
151
152 tlbw
153
154 tlbmiss_restore
155 rete
156
157handle_vmalloc_miss:
158 /* Simply do the lookup in init's page table */
159 mov r0, lo(swapper_pg_dir)
160 orh r0, hi(swapper_pg_dir)
161 rjmp pgtbl_lookup
162
163
164 /* --- System Call --- */
165
166 .section .scall.text,"ax",@progbits
167system_call:
168 pushm r12 /* r12_orig */
169 stmts --sp, r0-lr
170 zero_fp
171 mfsr r0, SYSREG_RAR_SUP
172 mfsr r1, SYSREG_RSR_SUP
173 stm --sp, r0-r1
174
175 /* check for syscall tracing */
176 get_thread_info r0
177 ld.w r1, r0[TI_flags]
178 bld r1, TIF_SYSCALL_TRACE
179 brcs syscall_trace_enter
180
181syscall_trace_cont:
182 cp.w r8, NR_syscalls
183 brhs syscall_badsys
184
185 lddpc lr, syscall_table_addr
186 ld.w lr, lr[r8 << 2]
187 mov r8, r5 /* 5th argument (6th is pushed by stub) */
188 icall lr
189
190 .global syscall_return
191syscall_return:
192 get_thread_info r0
193 mask_interrupts /* make sure we don't miss an interrupt
194 setting need_resched or sigpending
195 between sampling and the rets */
196
197 /* Store the return value so that the correct value is loaded below */
198 stdsp sp[REG_R12], r12
199
200 ld.w r1, r0[TI_flags]
201 andl r1, _TIF_ALLWORK_MASK, COH
202 brne syscall_exit_work
203
204syscall_exit_cont:
205 popm r8-r9
206 mtsr SYSREG_RAR_SUP, r8
207 mtsr SYSREG_RSR_SUP, r9
208 ldmts sp++, r0-lr
209 sub sp, -4 /* r12_orig */
210 rets
211
212 .align 2
213syscall_table_addr:
214 .long sys_call_table
215
216syscall_badsys:
217 mov r12, -ENOSYS
218 rjmp syscall_return
219
220 .global ret_from_fork
221ret_from_fork:
222 rcall schedule_tail
223
224 /* check for syscall tracing */
225 get_thread_info r0
226 ld.w r1, r0[TI_flags]
227 andl r1, _TIF_ALLWORK_MASK, COH
228 brne syscall_exit_work
229 rjmp syscall_exit_cont
230
231syscall_trace_enter:
232 pushm r8-r12
233 rcall syscall_trace
234 popm r8-r12
235 rjmp syscall_trace_cont
236
237syscall_exit_work:
238 bld r1, TIF_SYSCALL_TRACE
239 brcc 1f
240 unmask_interrupts
241 rcall syscall_trace
242 mask_interrupts
243 ld.w r1, r0[TI_flags]
244
2451: bld r1, TIF_NEED_RESCHED
246 brcc 2f
247 unmask_interrupts
248 rcall schedule
249 mask_interrupts
250 ld.w r1, r0[TI_flags]
251 rjmp 1b
252
2532: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
254 tst r1, r2
255 breq 3f
256 unmask_interrupts
257 mov r12, sp
258 mov r11, r0
259 rcall do_notify_resume
260 mask_interrupts
261 ld.w r1, r0[TI_flags]
262 rjmp 1b
263
2643: bld r1, TIF_BREAKPOINT
265 brcc syscall_exit_cont
266 mfsr r3, SYSREG_TLBEHI
267 lddsp r2, sp[REG_PC]
268 andl r3, 0xff, COH
269 lsl r3, 1
270 sbr r3, 30
271 sbr r3, 0
272 mtdr DBGREG_BWA2A, r2
273 mtdr DBGREG_BWC2A, r3
274 rjmp syscall_exit_cont
275
276
277 /* The slow path of the TLB miss handler */
278page_table_not_present:
279page_not_present:
280 tlbmiss_restore
281 sub sp, 4
282 stmts --sp, r0-lr
283 rcall save_full_context_ex
284 mfsr r12, SYSREG_ECR
285 mov r11, sp
286 rcall do_page_fault
287 rjmp ret_from_exception
288
289 /* This function expects to find offending PC in SYSREG_RAR_EX */
290save_full_context_ex:
291 mfsr r8, SYSREG_RSR_EX
292 mov r12, r8
293 andh r8, (MODE_MASK >> 16), COH
294 mfsr r11, SYSREG_RAR_EX
295 brne 2f
296
2971: pushm r11, r12 /* PC and SR */
298 unmask_exceptions
299 ret r12
300
3012: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
302 stdsp sp[4], r10 /* replace saved SP */
303 rjmp 1b
304
305 /* Low-level exception handlers */
306handle_critical:
307 pushm r12
308 pushm r0-r12
309 rcall save_full_context_ex
310 mfsr r12, SYSREG_ECR
311 mov r11, sp
312 rcall do_critical_exception
313
314 /* We should never get here... */
315bad_return:
316 sub r12, pc, (. - 1f)
317 bral panic
318 .align 2
3191: .asciz "Return from critical exception!"
320
321 .align 1
322do_bus_error_write:
323 sub sp, 4
324 stmts --sp, r0-lr
325 rcall save_full_context_ex
326 mov r11, 1
327 rjmp 1f
328
329do_bus_error_read:
330 sub sp, 4
331 stmts --sp, r0-lr
332 rcall save_full_context_ex
333 mov r11, 0
3341: mfsr r12, SYSREG_BEAR
335 mov r10, sp
336 rcall do_bus_error
337 rjmp ret_from_exception
338
339 .align 1
340do_nmi_ll:
341 sub sp, 4
342 stmts --sp, r0-lr
343 /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
344 rcall save_full_context_ex
345 mfsr r12, SYSREG_ECR
346 mov r11, sp
347 rcall do_nmi
348 rjmp bad_return
349
350handle_address_fault:
351 sub sp, 4
352 stmts --sp, r0-lr
353 rcall save_full_context_ex
354 mfsr r12, SYSREG_ECR
355 mov r11, sp
356 rcall do_address_exception
357 rjmp ret_from_exception
358
359handle_protection_fault:
360 sub sp, 4
361 stmts --sp, r0-lr
362 rcall save_full_context_ex
363 mfsr r12, SYSREG_ECR
364 mov r11, sp
365 rcall do_page_fault
366 rjmp ret_from_exception
367
368 .align 1
369do_illegal_opcode_ll:
370 sub sp, 4
371 stmts --sp, r0-lr
372 rcall save_full_context_ex
373 mfsr r12, SYSREG_ECR
374 mov r11, sp
375 rcall do_illegal_opcode
376 rjmp ret_from_exception
377
378do_dtlb_modified:
379 pushm r0-r3
380 mfsr r1, SYSREG_TLBEAR
381 mfsr r0, SYSREG_PTBR
382 lsr r2, r1, PGDIR_SHIFT
383 ld.w r0, r0[r2 << 2]
384 lsl r1, (32 - PGDIR_SHIFT)
385 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
386
387 /* Translate to virtual address in P1 */
388 andl r0, 0xf000
389 sbr r0, 31
390 add r2, r0, r1 << 2
391 ld.w r3, r2[0]
392 sbr r3, _PAGE_BIT_DIRTY
393 mov r0, r3
394 st.w r2[0], r3
395
396 /* The page table is up-to-date. Update the TLB entry as well */
397 andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
398 mtsr SYSREG_TLBELO, r0
399
400 /* MMUCR[DRP] is updated automatically, so let's go... */
401 tlbw
402
403 popm r0-r3
404 rete
405
406do_fpe_ll:
407 sub sp, 4
408 stmts --sp, r0-lr
409 rcall save_full_context_ex
410 unmask_interrupts
411 mov r12, 26
412 mov r11, sp
413 rcall do_fpe
414 rjmp ret_from_exception
415
416ret_from_exception:
417 mask_interrupts
418 lddsp r4, sp[REG_SR]
419 andh r4, (MODE_MASK >> 16), COH
420 brne fault_resume_kernel
421
422 get_thread_info r0
423 ld.w r1, r0[TI_flags]
424 andl r1, _TIF_WORK_MASK, COH
425 brne fault_exit_work
426
427fault_resume_user:
428 popm r8-r9
429 mask_exceptions
430 mtsr SYSREG_RAR_EX, r8
431 mtsr SYSREG_RSR_EX, r9
432 ldmts sp++, r0-lr
433 sub sp, -4
434 rete
435
436fault_resume_kernel:
437#ifdef CONFIG_PREEMPT
438 get_thread_info r0
439 ld.w r2, r0[TI_preempt_count]
440 cp.w r2, 0
441 brne 1f
442 ld.w r1, r0[TI_flags]
443 bld r1, TIF_NEED_RESCHED
444 brcc 1f
445 lddsp r4, sp[REG_SR]
446 bld r4, SYSREG_GM_OFFSET
447 brcs 1f
448 rcall preempt_schedule_irq
4491:
450#endif
451
452 popm r8-r9
453 mask_exceptions
454 mfsr r1, SYSREG_SR
455 mtsr SYSREG_RAR_EX, r8
456 mtsr SYSREG_RSR_EX, r9
457 popm lr
458 sub sp, -4 /* ignore SP */
459 popm r0-r12
460 sub sp, -4 /* ignore r12_orig */
461 rete
462
463irq_exit_work:
464 /* Switch to exception mode so that we can share the same code. */
465 mfsr r8, SYSREG_SR
466 cbr r8, SYSREG_M0_OFFSET
467 orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
468 mtsr SYSREG_SR, r8
469 sub pc, -2
470 get_thread_info r0
471 ld.w r1, r0[TI_flags]
472
473fault_exit_work:
474 bld r1, TIF_NEED_RESCHED
475 brcc 1f
476 unmask_interrupts
477 rcall schedule
478 mask_interrupts
479 ld.w r1, r0[TI_flags]
480 rjmp fault_exit_work
481
4821: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
483 tst r1, r2
484 breq 2f
485 unmask_interrupts
486 mov r12, sp
487 mov r11, r0
488 rcall do_notify_resume
489 mask_interrupts
490 ld.w r1, r0[TI_flags]
491 rjmp fault_exit_work
492
4932: bld r1, TIF_BREAKPOINT
494 brcc fault_resume_user
495 mfsr r3, SYSREG_TLBEHI
496 lddsp r2, sp[REG_PC]
497 andl r3, 0xff, COH
498 lsl r3, 1
499 sbr r3, 30
500 sbr r3, 0
501 mtdr DBGREG_BWA2A, r2
502 mtdr DBGREG_BWC2A, r3
503 rjmp fault_resume_user
504
505 /* If we get a debug trap from privileged context we end up here */
506handle_debug_priv:
507 /* Fix up LR and SP in regs. r11 contains the mode we came from */
508 mfsr r8, SYSREG_SR
509 mov r9, r8
510 andh r8, hi(~MODE_MASK)
511 or r8, r11
512 mtsr SYSREG_SR, r8
513 sub pc, -2
514 stdsp sp[REG_LR], lr
515 mtsr SYSREG_SR, r9
516 sub pc, -2
517 sub r10, sp, -FRAME_SIZE_FULL
518 stdsp sp[REG_SP], r10
519 mov r12, sp
520 rcall do_debug_priv
521
522 /* Now, put everything back */
523 ssrf SR_EM_BIT
524 popm r10, r11
525 mtsr SYSREG_RAR_DBG, r10
526 mtsr SYSREG_RSR_DBG, r11
527 mfsr r8, SYSREG_SR
528 mov r9, r8
529 andh r8, hi(~MODE_MASK)
530 andh r11, hi(MODE_MASK)
531 or r8, r11
532 mtsr SYSREG_SR, r8
533 sub pc, -2
534 popm lr
535 mtsr SYSREG_SR, r9
536 sub pc, -2
537 sub sp, -4 /* skip SP */
538 popm r0-r12
539 sub sp, -4
540 retd
541
542 /*
543 * At this point, everything is masked, that is, interrupts,
544 * exceptions and debugging traps. We might get called from
545 * interrupt or exception context in some rare cases, but this
546 * will be taken care of by do_debug(), so we're not going to
547 * do a 100% correct context save here.
548 */
549handle_debug:
550 sub sp, 4 /* r12_orig */
551 stmts --sp, r0-lr
552 mfsr r10, SYSREG_RAR_DBG
553 mfsr r11, SYSREG_RSR_DBG
554 unmask_exceptions
555 pushm r10,r11
556 andh r11, (MODE_MASK >> 16), COH
557 brne handle_debug_priv
558
559 mov r12, sp
560 rcall do_debug
561
562 lddsp r10, sp[REG_SR]
563 andh r10, (MODE_MASK >> 16), COH
564 breq debug_resume_user
565
566debug_restore_all:
567 popm r10,r11
568 mask_exceptions
569 mtsr SYSREG_RSR_DBG, r11
570 mtsr SYSREG_RAR_DBG, r10
571 ldmts sp++, r0-lr
572 sub sp, -4
573 retd
574
575debug_resume_user:
576 get_thread_info r0
577 mask_interrupts
578
579 ld.w r1, r0[TI_flags]
580 andl r1, _TIF_DBGWORK_MASK, COH
581 breq debug_restore_all
582
5831: bld r1, TIF_NEED_RESCHED
584 brcc 2f
585 unmask_interrupts
586 rcall schedule
587 mask_interrupts
588 ld.w r1, r0[TI_flags]
589 rjmp 1b
590
5912: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
592 tst r1, r2
593 breq 3f
594 unmask_interrupts
595 mov r12, sp
596 mov r11, r0
597 rcall do_notify_resume
598 mask_interrupts
599 ld.w r1, r0[TI_flags]
600 rjmp 1b
601
6023: bld r1, TIF_SINGLE_STEP
603 brcc debug_restore_all
604 mfdr r2, DBGREG_DC
605 sbr r2, DC_SS_BIT
606 mtdr DBGREG_DC, r2
607 rjmp debug_restore_all
608
609 .set rsr_int0, SYSREG_RSR_INT0
610 .set rsr_int1, SYSREG_RSR_INT1
611 .set rsr_int2, SYSREG_RSR_INT2
612 .set rsr_int3, SYSREG_RSR_INT3
613 .set rar_int0, SYSREG_RAR_INT0
614 .set rar_int1, SYSREG_RAR_INT1
615 .set rar_int2, SYSREG_RAR_INT2
616 .set rar_int3, SYSREG_RAR_INT3
617
618 .macro IRQ_LEVEL level
619 .type irq_level\level, @function
620irq_level\level:
621 sub sp, 4 /* r12_orig */
622 stmts --sp,r0-lr
623 mfsr r8, rar_int\level
624 mfsr r9, rsr_int\level
625 pushm r8-r9
626
627 mov r11, sp
628 mov r12, \level
629
630 rcall do_IRQ
631
632 lddsp r4, sp[REG_SR]
633 andh r4, (MODE_MASK >> 16), COH
634#ifdef CONFIG_PREEMPT
635 brne 2f
636#else
637 brne 1f
638#endif
639
640 get_thread_info r0
641 ld.w r1, r0[TI_flags]
642 andl r1, _TIF_WORK_MASK, COH
643 brne irq_exit_work
644
6451: popm r8-r9
646 mtsr rar_int\level, r8
647 mtsr rsr_int\level, r9
648 ldmts sp++,r0-lr
649 sub sp, -4 /* ignore r12_orig */
650 rete
651
652#ifdef CONFIG_PREEMPT
6532:
654 get_thread_info r0
655 ld.w r2, r0[TI_preempt_count]
656 cp.w r2, 0
657 brne 1b
658 ld.w r1, r0[TI_flags]
659 bld r1, TIF_NEED_RESCHED
660 brcc 1b
661 lddsp r4, sp[REG_SR]
662 bld r4, SYSREG_GM_OFFSET
663 brcs 1b
664 rcall preempt_schedule_irq
665 rjmp 1b
666#endif
667 .endm
668
669 .section .irq.text,"ax",@progbits
670
671 .global irq_level0
672 .global irq_level1
673 .global irq_level2
674 .global irq_level3
675 IRQ_LEVEL 0
676 IRQ_LEVEL 1
677 IRQ_LEVEL 2
678 IRQ_LEVEL 3
diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S
new file mode 100644
index 000000000000..773b7ad87be9
--- /dev/null
+++ b/arch/avr32/kernel/head.S
@@ -0,0 +1,45 @@
1/*
2 * Non-board-specific low-level startup code
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11
12#include <asm/page.h>
13#include <asm/thread_info.h>
14#include <asm/sysreg.h>
15
16 .section .init.text,"ax"
17 .global kernel_entry
18kernel_entry:
19 /* Initialize status register */
20 lddpc r0, init_sr
21 mtsr SYSREG_SR, r0
22
23 /* Set initial stack pointer */
24 lddpc sp, stack_addr
25 sub sp, -THREAD_SIZE
26
27#ifdef CONFIG_FRAME_POINTER
28 /* Mark last stack frame */
29 mov lr, 0
30 mov r7, 0
31#endif
32
33 /* Set up the PIO, SDRAM controller, early printk, etc. */
34 rcall board_early_init
35
36 /* Start the show */
37 lddpc pc, kernel_start_addr
38
39 .align 2
40init_sr:
41 .long 0x007f0000 /* Supervisor mode, everything masked */
42stack_addr:
43 .long init_thread_union
44kernel_start_addr:
45 .long start_kernel
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c
new file mode 100644
index 000000000000..effcacf9d1a2
--- /dev/null
+++ b/arch/avr32/kernel/init_task.c
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/module.h>
9#include <linux/fs.h>
10#include <linux/sched.h>
11#include <linux/init_task.h>
12#include <linux/mqueue.h>
13
14#include <asm/pgtable.h>
15
16static struct fs_struct init_fs = INIT_FS;
17static struct files_struct init_files = INIT_FILES;
18static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
19static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
20struct mm_struct init_mm = INIT_MM(init_mm);
21
22EXPORT_SYMBOL(init_mm);
23
24/*
25 * Initial thread structure. Must be aligned on an 8192-byte boundary.
26 */
27union thread_union init_thread_union
28 __attribute__((__section__(".data.init_task"))) =
29 { INIT_THREAD_INFO(init_task) };
30
31/*
32 * Initial task structure.
33 *
34 * All other task structs will be allocated on slabs in fork.c
35 */
36struct task_struct init_task = INIT_TASK(init_task);
37
38EXPORT_SYMBOL(init_task);
diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c
new file mode 100644
index 000000000000..856f3548e664
--- /dev/null
+++ b/arch/avr32/kernel/irq.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on arch/i386/kernel/irq.c
5 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This file contains the code used by various IRQ handling routines:
12 * asking for different IRQ's should be done through these routines
13 * instead of just grabbing them. Thus setups with different IRQ numbers
14 * shouldn't result in any weird surprises, and installing new handlers
15 * should be easier.
16 *
17 * IRQ's are in fact implemented a bit like signal handlers for the kernel.
18 * Naturally it's not a 1:1 relation, but there are similarities.
19 */
20
21#include <linux/interrupt.h>
22#include <linux/irq.h>
23#include <linux/kernel_stat.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26#include <linux/sysdev.h>
27
28/*
29 * 'what should we do if we get a hw irq event on an illegal vector'.
30 * each architecture has to answer this themselves.
31 */
32void ack_bad_irq(unsigned int irq)
33{
34 printk("unexpected IRQ %u\n", irq);
35}
36
37#ifdef CONFIG_PROC_FS
38int show_interrupts(struct seq_file *p, void *v)
39{
40 int i = *(loff_t *)v, cpu;
41 struct irqaction *action;
42 unsigned long flags;
43
44 if (i == 0) {
45 seq_puts(p, " ");
46 for_each_online_cpu(cpu)
47 seq_printf(p, "CPU%d ", cpu);
48 seq_putc(p, '\n');
49 }
50
51 if (i < NR_IRQS) {
52 spin_lock_irqsave(&irq_desc[i].lock, flags);
53 action = irq_desc[i].action;
54 if (!action)
55 goto unlock;
56
57 seq_printf(p, "%3d: ", i);
58 for_each_online_cpu(cpu)
59 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
60 seq_printf(p, " %s", action->name);
61 for (action = action->next; action; action = action->next)
62 seq_printf(p, ", %s", action->name);
63
64 seq_putc(p, '\n');
65 unlock:
66 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
67 }
68
69 return 0;
70}
71#endif
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c
new file mode 100644
index 000000000000..6caf9e8d8080
--- /dev/null
+++ b/arch/avr32/kernel/kprobes.c
@@ -0,0 +1,270 @@
1/*
2 * Kernel Probes (KProbes)
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * Based on arch/ppc64/kernel/kprobes.c
7 * Copyright (C) IBM Corporation, 2002, 2004
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kprobes.h>
15#include <linux/ptrace.h>
16
17#include <asm/cacheflush.h>
18#include <asm/kdebug.h>
19#include <asm/ocd.h>
20
21DEFINE_PER_CPU(struct kprobe *, current_kprobe);
22static unsigned long kprobe_status;
23static struct pt_regs jprobe_saved_regs;
24
25int __kprobes arch_prepare_kprobe(struct kprobe *p)
26{
27 int ret = 0;
28
29 if ((unsigned long)p->addr & 0x01) {
30 printk("Attempt to register kprobe at an unaligned address\n");
31 ret = -EINVAL;
32 }
33
34 /* XXX: Might be a good idea to check if p->addr is a valid
35 * kernel address as well... */
36
37 if (!ret) {
38 pr_debug("copy kprobe at %p\n", p->addr);
39 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
40 p->opcode = *p->addr;
41 }
42
43 return ret;
44}
45
46void __kprobes arch_arm_kprobe(struct kprobe *p)
47{
48 pr_debug("arming kprobe at %p\n", p->addr);
49 *p->addr = BREAKPOINT_INSTRUCTION;
50 flush_icache_range((unsigned long)p->addr,
51 (unsigned long)p->addr + sizeof(kprobe_opcode_t));
52}
53
54void __kprobes arch_disarm_kprobe(struct kprobe *p)
55{
56 pr_debug("disarming kprobe at %p\n", p->addr);
57 *p->addr = p->opcode;
58 flush_icache_range((unsigned long)p->addr,
59 (unsigned long)p->addr + sizeof(kprobe_opcode_t));
60}
61
62static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
63{
64 unsigned long dc;
65
66 pr_debug("preparing to singlestep over %p (PC=%08lx)\n",
67 p->addr, regs->pc);
68
69 BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D)));
70
71 dc = __mfdr(DBGREG_DC);
72 dc |= DC_SS;
73 __mtdr(DBGREG_DC, dc);
74
75 /*
76 * We must run the instruction from its original location
77 * since it may actually reference PC.
78 *
79 * TODO: Do the instruction replacement directly in icache.
80 */
81 *p->addr = p->opcode;
82 flush_icache_range((unsigned long)p->addr,
83 (unsigned long)p->addr + sizeof(kprobe_opcode_t));
84}
85
86static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
87{
88 unsigned long dc;
89
90 pr_debug("resuming execution at PC=%08lx\n", regs->pc);
91
92 dc = __mfdr(DBGREG_DC);
93 dc &= ~DC_SS;
94 __mtdr(DBGREG_DC, dc);
95
96 *p->addr = BREAKPOINT_INSTRUCTION;
97 flush_icache_range((unsigned long)p->addr,
98 (unsigned long)p->addr + sizeof(kprobe_opcode_t));
99}
100
101static void __kprobes set_current_kprobe(struct kprobe *p)
102{
103 __get_cpu_var(current_kprobe) = p;
104}
105
106static int __kprobes kprobe_handler(struct pt_regs *regs)
107{
108 struct kprobe *p;
109 void *addr = (void *)regs->pc;
110 int ret = 0;
111
112 pr_debug("kprobe_handler: kprobe_running=%d\n",
113 kprobe_running());
114
115 /*
116 * We don't want to be preempted for the entire
117 * duration of kprobe processing
118 */
119 preempt_disable();
120
121 /* Check that we're not recursing */
122 if (kprobe_running()) {
123 p = get_kprobe(addr);
124 if (p) {
125 if (kprobe_status == KPROBE_HIT_SS) {
126 printk("FIXME: kprobe hit while single-stepping!\n");
127 goto no_kprobe;
128 }
129
130 printk("FIXME: kprobe hit while handling another kprobe\n");
131 goto no_kprobe;
132 } else {
133 p = kprobe_running();
134 if (p->break_handler && p->break_handler(p, regs))
135 goto ss_probe;
136 }
137 /* If it's not ours, can't be delete race, (we hold lock). */
138 goto no_kprobe;
139 }
140
141 p = get_kprobe(addr);
142 if (!p)
143 goto no_kprobe;
144
145 kprobe_status = KPROBE_HIT_ACTIVE;
146 set_current_kprobe(p);
147 if (p->pre_handler && p->pre_handler(p, regs))
148 /* handler has already set things up, so skip ss setup */
149 return 1;
150
151ss_probe:
152 prepare_singlestep(p, regs);
153 kprobe_status = KPROBE_HIT_SS;
154 return 1;
155
156no_kprobe:
157 return ret;
158}
159
160static int __kprobes post_kprobe_handler(struct pt_regs *regs)
161{
162 struct kprobe *cur = kprobe_running();
163
164 pr_debug("post_kprobe_handler, cur=%p\n", cur);
165
166 if (!cur)
167 return 0;
168
169 if (cur->post_handler) {
170 kprobe_status = KPROBE_HIT_SSDONE;
171 cur->post_handler(cur, regs, 0);
172 }
173
174 resume_execution(cur, regs);
175 reset_current_kprobe();
176 preempt_enable_no_resched();
177
178 return 1;
179}
180
181static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
182{
183 struct kprobe *cur = kprobe_running();
184
185 pr_debug("kprobe_fault_handler: trapnr=%d\n", trapnr);
186
187 if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
188 return 1;
189
190 if (kprobe_status & KPROBE_HIT_SS) {
191 resume_execution(cur, regs);
192 preempt_enable_no_resched();
193 }
194 return 0;
195}
196
197/*
198 * Wrapper routine to for handling exceptions.
199 */
200int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
201 unsigned long val, void *data)
202{
203 struct die_args *args = (struct die_args *)data;
204 int ret = NOTIFY_DONE;
205
206 pr_debug("kprobe_exceptions_notify: val=%lu, data=%p\n",
207 val, data);
208
209 switch (val) {
210 case DIE_BREAKPOINT:
211 if (kprobe_handler(args->regs))
212 ret = NOTIFY_STOP;
213 break;
214 case DIE_SSTEP:
215 if (post_kprobe_handler(args->regs))
216 ret = NOTIFY_STOP;
217 break;
218 case DIE_FAULT:
219 if (kprobe_running()
220 && kprobe_fault_handler(args->regs, args->trapnr))
221 ret = NOTIFY_STOP;
222 break;
223 default:
224 break;
225 }
226
227 return ret;
228}
229
230int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
231{
232 struct jprobe *jp = container_of(p, struct jprobe, kp);
233
234 memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
235
236 /*
237 * TODO: We should probably save some of the stack here as
238 * well, since gcc may pass arguments on the stack for certain
239 * functions (lots of arguments, large aggregates, varargs)
240 */
241
242 /* setup return addr to the jprobe handler routine */
243 regs->pc = (unsigned long)jp->entry;
244 return 1;
245}
246
247void __kprobes jprobe_return(void)
248{
249 asm volatile("breakpoint" ::: "memory");
250}
251
252int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
253{
254 /*
255 * FIXME - we should ideally be validating that we got here 'cos
256 * of the "trap" in jprobe_return() above, before restoring the
257 * saved regs...
258 */
259 memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
260 return 1;
261}
262
263int __init arch_init_kprobes(void)
264{
265 printk("KPROBES: Enabling monitor mode (MM|DBE)...\n");
266 __mtdr(DBGREG_DC, DC_MM | DC_DBE);
267
268 /* TODO: Register kretprobe trampoline */
269 return 0;
270}
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
new file mode 100644
index 000000000000..dfc32f2817b6
--- /dev/null
+++ b/arch/avr32/kernel/module.c
@@ -0,0 +1,324 @@
1/*
2 * AVR32-specific kernel module loader
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * GOT initialization parts are based on the s390 version
7 * Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH,
8 * IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/moduleloader.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/elf.h>
19#include <linux/vmalloc.h>
20
21void *module_alloc(unsigned long size)
22{
23 if (size == 0)
24 return NULL;
25 return vmalloc(size);
26}
27
28void module_free(struct module *mod, void *module_region)
29{
30 vfree(mod->arch.syminfo);
31 mod->arch.syminfo = NULL;
32
33 vfree(module_region);
34 /* FIXME: if module_region == mod->init_region, trim exception
35 * table entries. */
36}
37
38static inline int check_rela(Elf32_Rela *rela, struct module *module,
39 char *strings, Elf32_Sym *symbols)
40{
41 struct mod_arch_syminfo *info;
42
43 info = module->arch.syminfo + ELF32_R_SYM(rela->r_info);
44 switch (ELF32_R_TYPE(rela->r_info)) {
45 case R_AVR32_GOT32:
46 case R_AVR32_GOT16:
47 case R_AVR32_GOT8:
48 case R_AVR32_GOT21S:
49 case R_AVR32_GOT18SW: /* mcall */
50 case R_AVR32_GOT16S: /* ld.w */
51 if (rela->r_addend != 0) {
52 printk(KERN_ERR
53 "GOT relocation against %s at offset %u with addend\n",
54 strings + symbols[ELF32_R_SYM(rela->r_info)].st_name,
55 rela->r_offset);
56 return -ENOEXEC;
57 }
58 if (info->got_offset == -1UL) {
59 info->got_offset = module->arch.got_size;
60 module->arch.got_size += sizeof(void *);
61 }
62 pr_debug("GOT[%3lu] %s\n", info->got_offset,
63 strings + symbols[ELF32_R_SYM(rela->r_info)].st_name);
64 break;
65 }
66
67 return 0;
68}
69
70int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
71 char *secstrings, struct module *module)
72{
73 Elf32_Shdr *symtab;
74 Elf32_Sym *symbols;
75 Elf32_Rela *rela;
76 char *strings;
77 int nrela, i, j;
78 int ret;
79
80 /* Find the symbol table */
81 symtab = NULL;
82 for (i = 0; i < hdr->e_shnum; i++)
83 switch (sechdrs[i].sh_type) {
84 case SHT_SYMTAB:
85 symtab = &sechdrs[i];
86 break;
87 }
88 if (!symtab) {
89 printk(KERN_ERR "module %s: no symbol table\n", module->name);
90 return -ENOEXEC;
91 }
92
93 /* Allocate room for one syminfo structure per symbol. */
94 module->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
95 module->arch.syminfo = vmalloc(module->arch.nsyms
96 * sizeof(struct mod_arch_syminfo));
97 if (!module->arch.syminfo)
98 return -ENOMEM;
99
100 symbols = (void *)hdr + symtab->sh_offset;
101 strings = (void *)hdr + sechdrs[symtab->sh_link].sh_offset;
102 for (i = 0; i < module->arch.nsyms; i++) {
103 if (symbols[i].st_shndx == SHN_UNDEF &&
104 strcmp(strings + symbols[i].st_name,
105 "_GLOBAL_OFFSET_TABLE_") == 0)
106 /* "Define" it as absolute. */
107 symbols[i].st_shndx = SHN_ABS;
108 module->arch.syminfo[i].got_offset = -1UL;
109 module->arch.syminfo[i].got_initialized = 0;
110 }
111
112 /* Allocate GOT entries for symbols that need it. */
113 module->arch.got_size = 0;
114 for (i = 0; i < hdr->e_shnum; i++) {
115 if (sechdrs[i].sh_type != SHT_RELA)
116 continue;
117 nrela = sechdrs[i].sh_size / sizeof(Elf32_Rela);
118 rela = (void *)hdr + sechdrs[i].sh_offset;
119 for (j = 0; j < nrela; j++) {
120 ret = check_rela(rela + j, module,
121 strings, symbols);
122 if (ret)
123 goto out_free_syminfo;
124 }
125 }
126
127 /*
128 * Increase core size to make room for GOT and set start
129 * offset for GOT.
130 */
131 module->core_size = ALIGN(module->core_size, 4);
132 module->arch.got_offset = module->core_size;
133 module->core_size += module->arch.got_size;
134
135 return 0;
136
137out_free_syminfo:
138 vfree(module->arch.syminfo);
139 module->arch.syminfo = NULL;
140
141 return ret;
142}
143
144static inline int reloc_overflow(struct module *module, const char *reloc_name,
145 Elf32_Addr relocation)
146{
147 printk(KERN_ERR "module %s: Value %lx does not fit relocation %s\n",
148 module->name, (unsigned long)relocation, reloc_name);
149 return -ENOEXEC;
150}
151
152#define get_u16(loc) (*((uint16_t *)loc))
153#define put_u16(loc, val) (*((uint16_t *)loc) = (val))
154
155int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
156 unsigned int symindex, unsigned int relindex,
157 struct module *module)
158{
159 Elf32_Shdr *symsec = sechdrs + symindex;
160 Elf32_Shdr *relsec = sechdrs + relindex;
161 Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
162 Elf32_Rela *rel = (void *)relsec->sh_addr;
163 unsigned int i;
164 int ret = 0;
165
166 for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
167 struct mod_arch_syminfo *info;
168 Elf32_Sym *sym;
169 Elf32_Addr relocation;
170 uint32_t *location;
171 uint32_t value;
172
173 location = (void *)dstsec->sh_addr + rel->r_offset;
174 sym = (Elf32_Sym *)symsec->sh_addr + ELF32_R_SYM(rel->r_info);
175 relocation = sym->st_value + rel->r_addend;
176
177 info = module->arch.syminfo + ELF32_R_SYM(rel->r_info);
178
179 /* Initialize GOT entry if necessary */
180 switch (ELF32_R_TYPE(rel->r_info)) {
181 case R_AVR32_GOT32:
182 case R_AVR32_GOT16:
183 case R_AVR32_GOT8:
184 case R_AVR32_GOT21S:
185 case R_AVR32_GOT18SW:
186 case R_AVR32_GOT16S:
187 if (!info->got_initialized) {
188 Elf32_Addr *gotent;
189
190 gotent = (module->module_core
191 + module->arch.got_offset
192 + info->got_offset);
193 *gotent = relocation;
194 info->got_initialized = 1;
195 }
196
197 relocation = info->got_offset;
198 break;
199 }
200
201 switch (ELF32_R_TYPE(rel->r_info)) {
202 case R_AVR32_32:
203 case R_AVR32_32_CPENT:
204 *location = relocation;
205 break;
206 case R_AVR32_22H_PCREL:
207 relocation -= (Elf32_Addr)location;
208 if ((relocation & 0xffe00001) != 0
209 && (relocation & 0xffc00001) != 0xffc00000)
210 return reloc_overflow(module,
211 "R_AVR32_22H_PCREL",
212 relocation);
213 relocation >>= 1;
214
215 value = *location;
216 value = ((value & 0xe1ef0000)
217 | (relocation & 0xffff)
218 | ((relocation & 0x10000) << 4)
219 | ((relocation & 0x1e0000) << 8));
220 *location = value;
221 break;
222 case R_AVR32_11H_PCREL:
223 relocation -= (Elf32_Addr)location;
224 if ((relocation & 0xfffffc01) != 0
225 && (relocation & 0xfffff801) != 0xfffff800)
226 return reloc_overflow(module,
227 "R_AVR32_11H_PCREL",
228 relocation);
229 value = get_u16(location);
230 value = ((value & 0xf00c)
231 | ((relocation & 0x1fe) << 3)
232 | ((relocation & 0x600) >> 9));
233 put_u16(location, value);
234 break;
235 case R_AVR32_9H_PCREL:
236 relocation -= (Elf32_Addr)location;
237 if ((relocation & 0xffffff01) != 0
238 && (relocation & 0xfffffe01) != 0xfffffe00)
239 return reloc_overflow(module,
240 "R_AVR32_9H_PCREL",
241 relocation);
242 value = get_u16(location);
243 value = ((value & 0xf00f)
244 | ((relocation & 0x1fe) << 3));
245 put_u16(location, value);
246 break;
247 case R_AVR32_9UW_PCREL:
248 relocation -= ((Elf32_Addr)location) & 0xfffffffc;
249 if ((relocation & 0xfffffc03) != 0)
250 return reloc_overflow(module,
251 "R_AVR32_9UW_PCREL",
252 relocation);
253 value = get_u16(location);
254 value = ((value & 0xf80f)
255 | ((relocation & 0x1fc) << 2));
256 put_u16(location, value);
257 break;
258 case R_AVR32_GOTPC:
259 /*
260 * R6 = PC - (PC - GOT)
261 *
262 * At this point, relocation contains the
263 * value of PC. Just subtract the value of
264 * GOT, and we're done.
265 */
266 pr_debug("GOTPC: PC=0x%lx, got_offset=0x%lx, core=0x%p\n",
267 relocation, module->arch.got_offset,
268 module->module_core);
269 relocation -= ((unsigned long)module->module_core
270 + module->arch.got_offset);
271 *location = relocation;
272 break;
273 case R_AVR32_GOT18SW:
274 if ((relocation & 0xfffe0003) != 0
275 && (relocation & 0xfffc0003) != 0xffff0000)
276 return reloc_overflow(module, "R_AVR32_GOT18SW",
277 relocation);
278 relocation >>= 2;
279 /* fall through */
280 case R_AVR32_GOT16S:
281 if ((relocation & 0xffff8000) != 0
282 && (relocation & 0xffff0000) != 0xffff0000)
283 return reloc_overflow(module, "R_AVR32_GOT16S",
284 relocation);
285 pr_debug("GOT reloc @ 0x%lx -> %lu\n",
286 rel->r_offset, relocation);
287 value = *location;
288 value = ((value & 0xffff0000)
289 | (relocation & 0xffff));
290 *location = value;
291 break;
292
293 default:
294 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
295 module->name, ELF32_R_TYPE(rel->r_info));
296 return -ENOEXEC;
297 }
298 }
299
300 return ret;
301}
302
303int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
304 unsigned int symindex, unsigned int relindex,
305 struct module *module)
306{
307 printk(KERN_ERR "module %s: REL relocations are not supported\n",
308 module->name);
309 return -ENOEXEC;
310}
311
312int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
313 struct module *module)
314{
315 vfree(module->arch.syminfo);
316 module->arch.syminfo = NULL;
317
318 return 0;
319}
320
321void module_arch_cleanup(struct module *module)
322{
323
324}
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
new file mode 100644
index 000000000000..317dc50945f2
--- /dev/null
+++ b/arch/avr32/kernel/process.c
@@ -0,0 +1,276 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/sched.h>
9#include <linux/module.h>
10#include <linux/kallsyms.h>
11#include <linux/fs.h>
12#include <linux/ptrace.h>
13#include <linux/reboot.h>
14#include <linux/unistd.h>
15
16#include <asm/sysreg.h>
17#include <asm/ocd.h>
18
19void (*pm_power_off)(void) = NULL;
20EXPORT_SYMBOL(pm_power_off);
21
22/*
23 * This file handles the architecture-dependent parts of process handling..
24 */
25
26void cpu_idle(void)
27{
28 /* endless idle loop with no priority at all */
29 while (1) {
30 /* TODO: Enter sleep mode */
31 while (!need_resched())
32 cpu_relax();
33 preempt_enable_no_resched();
34 schedule();
35 preempt_disable();
36 }
37}
38
39void machine_halt(void)
40{
41}
42
43void machine_power_off(void)
44{
45}
46
47void machine_restart(char *cmd)
48{
49 __mtdr(DBGREG_DC, DC_DBE);
50 __mtdr(DBGREG_DC, DC_RES);
51 while (1) ;
52}
53
54/*
55 * PC is actually discarded when returning from a system call -- the
56 * return address must be stored in LR. This function will make sure
57 * LR points to do_exit before starting the thread.
58 *
59 * Also, when returning from fork(), r12 is 0, so we must copy the
60 * argument as well.
61 *
62 * r0 : The argument to the main thread function
63 * r1 : The address of do_exit
64 * r2 : The address of the main thread function
65 */
66asmlinkage extern void kernel_thread_helper(void);
67__asm__(" .type kernel_thread_helper, @function\n"
68 "kernel_thread_helper:\n"
69 " mov r12, r0\n"
70 " mov lr, r2\n"
71 " mov pc, r1\n"
72 " .size kernel_thread_helper, . - kernel_thread_helper");
73
74int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
75{
76 struct pt_regs regs;
77
78 memset(&regs, 0, sizeof(regs));
79
80 regs.r0 = (unsigned long)arg;
81 regs.r1 = (unsigned long)fn;
82 regs.r2 = (unsigned long)do_exit;
83 regs.lr = (unsigned long)kernel_thread_helper;
84 regs.pc = (unsigned long)kernel_thread_helper;
85 regs.sr = MODE_SUPERVISOR;
86
87 return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
88 0, &regs, 0, NULL, NULL);
89}
90EXPORT_SYMBOL(kernel_thread);
91
92/*
93 * Free current thread data structures etc
94 */
95void exit_thread(void)
96{
97 /* nothing to do */
98}
99
100void flush_thread(void)
101{
102 /* nothing to do */
103}
104
105void release_thread(struct task_struct *dead_task)
106{
107 /* do nothing */
108}
109
110static const char *cpu_modes[] = {
111 "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
112 "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
113};
114
115void show_regs(struct pt_regs *regs)
116{
117 unsigned long sp = regs->sp;
118 unsigned long lr = regs->lr;
119 unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
120
121 if (!user_mode(regs))
122 sp = (unsigned long)regs + FRAME_SIZE_FULL;
123
124 print_symbol("PC is at %s\n", instruction_pointer(regs));
125 print_symbol("LR is at %s\n", lr);
126 printk("pc : [<%08lx>] lr : [<%08lx>] %s\n"
127 "sp : %08lx r12: %08lx r11: %08lx\n",
128 instruction_pointer(regs),
129 lr, print_tainted(), sp, regs->r12, regs->r11);
130 printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
131 regs->r10, regs->r9, regs->r8);
132 printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
133 regs->r7, regs->r6, regs->r5, regs->r4);
134 printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
135 regs->r3, regs->r2, regs->r1, regs->r0);
136 printk("Flags: %c%c%c%c%c\n",
137 regs->sr & SR_Q ? 'Q' : 'q',
138 regs->sr & SR_V ? 'V' : 'v',
139 regs->sr & SR_N ? 'N' : 'n',
140 regs->sr & SR_Z ? 'Z' : 'z',
141 regs->sr & SR_C ? 'C' : 'c');
142 printk("Mode bits: %c%c%c%c%c%c%c%c%c\n",
143 regs->sr & SR_H ? 'H' : 'h',
144 regs->sr & SR_R ? 'R' : 'r',
145 regs->sr & SR_J ? 'J' : 'j',
146 regs->sr & SR_EM ? 'E' : 'e',
147 regs->sr & SR_I3M ? '3' : '.',
148 regs->sr & SR_I2M ? '2' : '.',
149 regs->sr & SR_I1M ? '1' : '.',
150 regs->sr & SR_I0M ? '0' : '.',
151 regs->sr & SR_GM ? 'G' : 'g');
152 printk("CPU Mode: %s\n", cpu_modes[mode]);
153
154 show_trace(NULL, (unsigned long *)sp, regs);
155}
156EXPORT_SYMBOL(show_regs);
157
158/* Fill in the fpu structure for a core dump. This is easy -- we don't have any */
159int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
160{
161 /* Not valid */
162 return 0;
163}
164
165asmlinkage void ret_from_fork(void);
166
167int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
168 unsigned long unused,
169 struct task_struct *p, struct pt_regs *regs)
170{
171 struct pt_regs *childregs;
172
173 childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1;
174 *childregs = *regs;
175
176 if (user_mode(regs))
177 childregs->sp = usp;
178 else
179 childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE;
180
181 childregs->r12 = 0; /* Set return value for child */
182
183 p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
184 p->thread.cpu_context.ksp = (unsigned long)childregs;
185 p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
186
187 return 0;
188}
189
190/* r12-r8 are dummy parameters to force the compiler to use the stack */
191asmlinkage int sys_fork(struct pt_regs *regs)
192{
193 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
194}
195
196asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
197 unsigned long parent_tidptr,
198 unsigned long child_tidptr, struct pt_regs *regs)
199{
200 if (!newsp)
201 newsp = regs->sp;
202 return do_fork(clone_flags, newsp, regs, 0,
203 (int __user *)parent_tidptr,
204 (int __user *)child_tidptr);
205}
206
207asmlinkage int sys_vfork(struct pt_regs *regs)
208{
209 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,
210 0, NULL, NULL);
211}
212
213asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv,
214 char __user *__user *uenvp, struct pt_regs *regs)
215{
216 int error;
217 char *filename;
218
219 filename = getname(ufilename);
220 error = PTR_ERR(filename);
221 if (IS_ERR(filename))
222 goto out;
223
224 error = do_execve(filename, uargv, uenvp, regs);
225 if (error == 0)
226 current->ptrace &= ~PT_DTRACE;
227 putname(filename);
228
229out:
230 return error;
231}
232
233
234/*
235 * This function is supposed to answer the question "who called
236 * schedule()?"
237 */
238unsigned long get_wchan(struct task_struct *p)
239{
240 unsigned long pc;
241 unsigned long stack_page;
242
243 if (!p || p == current || p->state == TASK_RUNNING)
244 return 0;
245
246 stack_page = (unsigned long)p->thread_info;
247 BUG_ON(!stack_page);
248
249 /*
250 * The stored value of PC is either the address right after
251 * the call to __switch_to() or ret_from_fork.
252 */
253 pc = thread_saved_pc(p);
254 if (in_sched_functions(pc)) {
255#ifdef CONFIG_FRAME_POINTER
256 unsigned long fp = p->thread.cpu_context.r7;
257 BUG_ON(fp < stack_page || fp > (THREAD_SIZE + stack_page));
258 pc = *(unsigned long *)fp;
259#else
260 /*
261 * We depend on the frame size of schedule here, which
262 * is actually quite ugly. It might be possible to
263 * determine the frame size automatically at build
264 * time by doing this:
265 * - compile sched.c
266 * - disassemble the resulting sched.o
267 * - look for 'sub sp,??' shortly after '<schedule>:'
268 */
269 unsigned long sp = p->thread.cpu_context.ksp + 16;
270 BUG_ON(sp < stack_page || sp > (THREAD_SIZE + stack_page));
271 pc = *(unsigned long *)sp;
272#endif
273 }
274
275 return pc;
276}
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
new file mode 100644
index 000000000000..3c89e59029ab
--- /dev/null
+++ b/arch/avr32/kernel/ptrace.c
@@ -0,0 +1,371 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#undef DEBUG
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/mm.h>
12#include <linux/smp_lock.h>
13#include <linux/ptrace.h>
14#include <linux/errno.h>
15#include <linux/user.h>
16#include <linux/security.h>
17#include <linux/unistd.h>
18#include <linux/notifier.h>
19
20#include <asm/traps.h>
21#include <asm/uaccess.h>
22#include <asm/ocd.h>
23#include <asm/mmu_context.h>
24#include <asm/kdebug.h>
25
26static struct pt_regs *get_user_regs(struct task_struct *tsk)
27{
28 return (struct pt_regs *)((unsigned long) tsk->thread_info +
29 THREAD_SIZE - sizeof(struct pt_regs));
30}
31
32static void ptrace_single_step(struct task_struct *tsk)
33{
34 pr_debug("ptrace_single_step: pid=%u, SR=0x%08lx\n",
35 tsk->pid, tsk->thread.cpu_context.sr);
36 if (!(tsk->thread.cpu_context.sr & SR_D)) {
37 /*
38 * Set a breakpoint at the current pc to force the
39 * process into debug mode. The syscall/exception
40 * exit code will set a breakpoint at the return
41 * address when this flag is set.
42 */
43 pr_debug("ptrace_single_step: Setting TIF_BREAKPOINT\n");
44 set_tsk_thread_flag(tsk, TIF_BREAKPOINT);
45 }
46
47 /* The monitor code will do the actual step for us */
48 set_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
49}
50
51/*
52 * Called by kernel/ptrace.c when detaching
53 *
54 * Make sure any single step bits, etc. are not set
55 */
56void ptrace_disable(struct task_struct *child)
57{
58 clear_tsk_thread_flag(child, TIF_SINGLE_STEP);
59}
60
61/*
62 * Handle hitting a breakpoint
63 */
64static void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
65{
66 siginfo_t info;
67
68 info.si_signo = SIGTRAP;
69 info.si_errno = 0;
70 info.si_code = TRAP_BRKPT;
71 info.si_addr = (void __user *)instruction_pointer(regs);
72
73 pr_debug("ptrace_break: Sending SIGTRAP to PID %u (pc = 0x%p)\n",
74 tsk->pid, info.si_addr);
75 force_sig_info(SIGTRAP, &info, tsk);
76}
77
78/*
79 * Read the word at offset "offset" into the task's "struct user". We
80 * actually access the pt_regs struct stored on the kernel stack.
81 */
82static int ptrace_read_user(struct task_struct *tsk, unsigned long offset,
83 unsigned long __user *data)
84{
85 unsigned long *regs;
86 unsigned long value;
87
88 pr_debug("ptrace_read_user(%p, %#lx, %p)\n",
89 tsk, offset, data);
90
91 if (offset & 3 || offset >= sizeof(struct user)) {
92 printk("ptrace_read_user: invalid offset 0x%08lx\n", offset);
93 return -EIO;
94 }
95
96 regs = (unsigned long *)get_user_regs(tsk);
97
98 value = 0;
99 if (offset < sizeof(struct pt_regs))
100 value = regs[offset / sizeof(regs[0])];
101
102 return put_user(value, data);
103}
104
105/*
106 * Write the word "value" to offset "offset" into the task's "struct
107 * user". We actually access the pt_regs struct stored on the kernel
108 * stack.
109 */
110static int ptrace_write_user(struct task_struct *tsk, unsigned long offset,
111 unsigned long value)
112{
113 unsigned long *regs;
114
115 if (offset & 3 || offset >= sizeof(struct user)) {
116 printk("ptrace_write_user: invalid offset 0x%08lx\n", offset);
117 return -EIO;
118 }
119
120 if (offset >= sizeof(struct pt_regs))
121 return 0;
122
123 regs = (unsigned long *)get_user_regs(tsk);
124 regs[offset / sizeof(regs[0])] = value;
125
126 return 0;
127}
128
129static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
130{
131 struct pt_regs *regs = get_user_regs(tsk);
132
133 return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0;
134}
135
136static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
137{
138 struct pt_regs newregs;
139 int ret;
140
141 ret = -EFAULT;
142 if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) {
143 struct pt_regs *regs = get_user_regs(tsk);
144
145 ret = -EINVAL;
146 if (valid_user_regs(&newregs)) {
147 *regs = newregs;
148 ret = 0;
149 }
150 }
151
152 return ret;
153}
154
155long arch_ptrace(struct task_struct *child, long request, long addr, long data)
156{
157 unsigned long tmp;
158 int ret;
159
160 pr_debug("arch_ptrace(%ld, %ld, %#lx, %#lx)\n",
161 request, child->pid, addr, data);
162
163 pr_debug("ptrace: Enabling monitor mode...\n");
164 __mtdr(DBGREG_DC, __mfdr(DBGREG_DC) | DC_MM | DC_DBE);
165
166 switch (request) {
167 /* Read the word at location addr in the child process */
168 case PTRACE_PEEKTEXT:
169 case PTRACE_PEEKDATA:
170 ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
171 if (ret == sizeof(tmp))
172 ret = put_user(tmp, (unsigned long __user *)data);
173 else
174 ret = -EIO;
175 break;
176
177 case PTRACE_PEEKUSR:
178 ret = ptrace_read_user(child, addr,
179 (unsigned long __user *)data);
180 break;
181
182 /* Write the word in data at location addr */
183 case PTRACE_POKETEXT:
184 case PTRACE_POKEDATA:
185 ret = access_process_vm(child, addr, &data, sizeof(data), 1);
186 if (ret == sizeof(data))
187 ret = 0;
188 else
189 ret = -EIO;
190 break;
191
192 case PTRACE_POKEUSR:
193 ret = ptrace_write_user(child, addr, data);
194 break;
195
196 /* continue and stop at next (return from) syscall */
197 case PTRACE_SYSCALL:
198 /* restart after signal */
199 case PTRACE_CONT:
200 ret = -EIO;
201 if (!valid_signal(data))
202 break;
203 if (request == PTRACE_SYSCALL)
204 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
205 else
206 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
207 child->exit_code = data;
208 /* XXX: Are we sure no breakpoints are active here? */
209 wake_up_process(child);
210 ret = 0;
211 break;
212
213 /*
214 * Make the child exit. Best I can do is send it a
215 * SIGKILL. Perhaps it should be put in the status that it
216 * wants to exit.
217 */
218 case PTRACE_KILL:
219 ret = 0;
220 if (child->exit_state == EXIT_ZOMBIE)
221 break;
222 child->exit_code = SIGKILL;
223 wake_up_process(child);
224 break;
225
226 /*
227 * execute single instruction.
228 */
229 case PTRACE_SINGLESTEP:
230 ret = -EIO;
231 if (!valid_signal(data))
232 break;
233 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
234 ptrace_single_step(child);
235 child->exit_code = data;
236 wake_up_process(child);
237 ret = 0;
238 break;
239
240 /* Detach a process that was attached */
241 case PTRACE_DETACH:
242 ret = ptrace_detach(child, data);
243 break;
244
245 case PTRACE_GETREGS:
246 ret = ptrace_getregs(child, (void __user *)data);
247 break;
248
249 case PTRACE_SETREGS:
250 ret = ptrace_setregs(child, (const void __user *)data);
251 break;
252
253 default:
254 ret = ptrace_request(child, request, addr, data);
255 break;
256 }
257
258 pr_debug("sys_ptrace returning %d (DC = 0x%08lx)\n", ret, __mfdr(DBGREG_DC));
259 return ret;
260}
261
262asmlinkage void syscall_trace(void)
263{
264 pr_debug("syscall_trace called\n");
265 if (!test_thread_flag(TIF_SYSCALL_TRACE))
266 return;
267 if (!(current->ptrace & PT_PTRACED))
268 return;
269
270 pr_debug("syscall_trace: notifying parent\n");
271 /* The 0x80 provides a way for the tracing parent to
272 * distinguish between a syscall stop and SIGTRAP delivery */
273 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
274 ? 0x80 : 0));
275
276 /*
277 * this isn't the same as continuing with a signal, but it
278 * will do for normal use. strace only continues with a
279 * signal if the stopping signal is not SIGTRAP. -brl
280 */
281 if (current->exit_code) {
282 pr_debug("syscall_trace: sending signal %d to PID %u\n",
283 current->exit_code, current->pid);
284 send_sig(current->exit_code, current, 1);
285 current->exit_code = 0;
286 }
287}
288
289asmlinkage void do_debug_priv(struct pt_regs *regs)
290{
291 unsigned long dc, ds;
292 unsigned long die_val;
293
294 ds = __mfdr(DBGREG_DS);
295
296 pr_debug("do_debug_priv: pc = %08lx, ds = %08lx\n", regs->pc, ds);
297
298 if (ds & DS_SSS)
299 die_val = DIE_SSTEP;
300 else
301 die_val = DIE_BREAKPOINT;
302
303 if (notify_die(die_val, regs, 0, SIGTRAP) == NOTIFY_STOP)
304 return;
305
306 if (likely(ds & DS_SSS)) {
307 extern void itlb_miss(void);
308 extern void tlb_miss_common(void);
309 struct thread_info *ti;
310
311 dc = __mfdr(DBGREG_DC);
312 dc &= ~DC_SS;
313 __mtdr(DBGREG_DC, dc);
314
315 ti = current_thread_info();
316 ti->flags |= _TIF_BREAKPOINT;
317
318 /* The TLB miss handlers don't check thread flags */
319 if ((regs->pc >= (unsigned long)&itlb_miss)
320 && (regs->pc <= (unsigned long)&tlb_miss_common)) {
321 __mtdr(DBGREG_BWA2A, sysreg_read(RAR_EX));
322 __mtdr(DBGREG_BWC2A, 0x40000001 | (get_asid() << 1));
323 }
324
325 /*
326 * If we're running in supervisor mode, the breakpoint
327 * will take us where we want directly, no need to
328 * single step.
329 */
330 if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR)
331 ti->flags |= TIF_SINGLE_STEP;
332 } else {
333 panic("Unable to handle debug trap at pc = %08lx\n",
334 regs->pc);
335 }
336}
337
338/*
339 * Handle breakpoints, single steps and other debuggy things. To keep
340 * things simple initially, we run with interrupts and exceptions
341 * disabled all the time.
342 */
343asmlinkage void do_debug(struct pt_regs *regs)
344{
345 unsigned long dc, ds;
346
347 ds = __mfdr(DBGREG_DS);
348 pr_debug("do_debug: pc = %08lx, ds = %08lx\n", regs->pc, ds);
349
350 if (test_thread_flag(TIF_BREAKPOINT)) {
351 pr_debug("TIF_BREAKPOINT set\n");
352 /* We're taking care of it */
353 clear_thread_flag(TIF_BREAKPOINT);
354 __mtdr(DBGREG_BWC2A, 0);
355 }
356
357 if (test_thread_flag(TIF_SINGLE_STEP)) {
358 pr_debug("TIF_SINGLE_STEP set, ds = 0x%08lx\n", ds);
359 if (ds & DS_SSS) {
360 dc = __mfdr(DBGREG_DC);
361 dc &= ~DC_SS;
362 __mtdr(DBGREG_DC, dc);
363
364 clear_thread_flag(TIF_SINGLE_STEP);
365 ptrace_break(current, regs);
366 }
367 } else {
368 /* regular breakpoint */
369 ptrace_break(current, regs);
370 }
371}
diff --git a/arch/avr32/kernel/semaphore.c b/arch/avr32/kernel/semaphore.c
new file mode 100644
index 000000000000..1e2705a05016
--- /dev/null
+++ b/arch/avr32/kernel/semaphore.c
@@ -0,0 +1,148 @@
1/*
2 * AVR32 sempahore implementation.
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * Based on linux/arch/i386/kernel/semaphore.c
7 * Copyright (C) 1999 Linus Torvalds
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/sched.h>
15#include <linux/errno.h>
16#include <linux/module.h>
17
18#include <asm/semaphore.h>
19#include <asm/atomic.h>
20
21/*
22 * Semaphores are implemented using a two-way counter:
23 * The "count" variable is decremented for each process
24 * that tries to acquire the semaphore, while the "sleeping"
25 * variable is a count of such acquires.
26 *
27 * Notably, the inline "up()" and "down()" functions can
28 * efficiently test if they need to do any extra work (up
29 * needs to do something only if count was negative before
30 * the increment operation.
31 *
32 * "sleeping" and the contention routine ordering is protected
33 * by the spinlock in the semaphore's waitqueue head.
34 *
35 * Note that these functions are only called when there is
36 * contention on the lock, and as such all this is the
37 * "non-critical" part of the whole semaphore business. The
38 * critical part is the inline stuff in <asm/semaphore.h>
39 * where we want to avoid any extra jumps and calls.
40 */
41
42/*
43 * Logic:
44 * - only on a boundary condition do we need to care. When we go
45 * from a negative count to a non-negative, we wake people up.
46 * - when we go from a non-negative count to a negative do we
47 * (a) synchronize with the "sleeper" count and (b) make sure
48 * that we're on the wakeup list before we synchronize so that
49 * we cannot lose wakeup events.
50 */
51
52void __up(struct semaphore *sem)
53{
54 wake_up(&sem->wait);
55}
56EXPORT_SYMBOL(__up);
57
58void __sched __down(struct semaphore *sem)
59{
60 struct task_struct *tsk = current;
61 DECLARE_WAITQUEUE(wait, tsk);
62 unsigned long flags;
63
64 tsk->state = TASK_UNINTERRUPTIBLE;
65 spin_lock_irqsave(&sem->wait.lock, flags);
66 add_wait_queue_exclusive_locked(&sem->wait, &wait);
67
68 sem->sleepers++;
69 for (;;) {
70 int sleepers = sem->sleepers;
71
72 /*
73 * Add "everybody else" into it. They aren't
74 * playing, because we own the spinlock in
75 * the wait_queue_head.
76 */
77 if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
78 sem->sleepers = 0;
79 break;
80 }
81 sem->sleepers = 1; /* us - see -1 above */
82 spin_unlock_irqrestore(&sem->wait.lock, flags);
83
84 schedule();
85
86 spin_lock_irqsave(&sem->wait.lock, flags);
87 tsk->state = TASK_UNINTERRUPTIBLE;
88 }
89 remove_wait_queue_locked(&sem->wait, &wait);
90 wake_up_locked(&sem->wait);
91 spin_unlock_irqrestore(&sem->wait.lock, flags);
92 tsk->state = TASK_RUNNING;
93}
94EXPORT_SYMBOL(__down);
95
96int __sched __down_interruptible(struct semaphore *sem)
97{
98 int retval = 0;
99 struct task_struct *tsk = current;
100 DECLARE_WAITQUEUE(wait, tsk);
101 unsigned long flags;
102
103 tsk->state = TASK_INTERRUPTIBLE;
104 spin_lock_irqsave(&sem->wait.lock, flags);
105 add_wait_queue_exclusive_locked(&sem->wait, &wait);
106
107 sem->sleepers++;
108 for (;;) {
109 int sleepers = sem->sleepers;
110
111 /*
112 * With signals pending, this turns into the trylock
113 * failure case - we won't be sleeping, and we can't
114 * get the lock as it has contention. Just correct the
115 * count and exit.
116 */
117 if (signal_pending(current)) {
118 retval = -EINTR;
119 sem->sleepers = 0;
120 atomic_add(sleepers, &sem->count);
121 break;
122 }
123
124 /*
125 * Add "everybody else" into it. They aren't
126 * playing, because we own the spinlock in
127 * the wait_queue_head.
128 */
129 if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
130 sem->sleepers = 0;
131 break;
132 }
133 sem->sleepers = 1; /* us - see -1 above */
134 spin_unlock_irqrestore(&sem->wait.lock, flags);
135
136 schedule();
137
138 spin_lock_irqsave(&sem->wait.lock, flags);
139 tsk->state = TASK_INTERRUPTIBLE;
140 }
141 remove_wait_queue_locked(&sem->wait, &wait);
142 wake_up_locked(&sem->wait);
143 spin_unlock_irqrestore(&sem->wait.lock, flags);
144
145 tsk->state = TASK_RUNNING;
146 return retval;
147}
148EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
new file mode 100644
index 000000000000..5d68f3c6990b
--- /dev/null
+++ b/arch/avr32/kernel/setup.c
@@ -0,0 +1,335 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/init.h>
11#include <linux/sched.h>
12#include <linux/console.h>
13#include <linux/ioport.h>
14#include <linux/bootmem.h>
15#include <linux/fs.h>
16#include <linux/module.h>
17#include <linux/root_dev.h>
18#include <linux/cpu.h>
19
20#include <asm/sections.h>
21#include <asm/processor.h>
22#include <asm/pgtable.h>
23#include <asm/setup.h>
24#include <asm/sysreg.h>
25
26#include <asm/arch/board.h>
27#include <asm/arch/init.h>
28
29extern int root_mountflags;
30
31/*
32 * Bootloader-provided information about physical memory
33 */
34struct tag_mem_range *mem_phys;
35struct tag_mem_range *mem_reserved;
36struct tag_mem_range *mem_ramdisk;
37
38/*
39 * Initialize loops_per_jiffy as 5000000 (500MIPS).
40 * Better make it too large than too small...
41 */
42struct avr32_cpuinfo boot_cpu_data = {
43 .loops_per_jiffy = 5000000
44};
45EXPORT_SYMBOL(boot_cpu_data);
46
47static char command_line[COMMAND_LINE_SIZE];
48
49/*
50 * Should be more than enough, but if you have a _really_ complex
51 * setup, you might need to increase the size of this...
52 */
53static struct tag_mem_range __initdata mem_range_cache[32];
54static unsigned mem_range_next_free;
55
56/*
57 * Standard memory resources
58 */
59static struct resource mem_res[] = {
60 {
61 .name = "Kernel code",
62 .start = 0,
63 .end = 0,
64 .flags = IORESOURCE_MEM
65 },
66 {
67 .name = "Kernel data",
68 .start = 0,
69 .end = 0,
70 .flags = IORESOURCE_MEM,
71 },
72};
73
74#define kernel_code mem_res[0]
75#define kernel_data mem_res[1]
76
77/*
78 * Early framebuffer allocation. Works as follows:
79 * - If fbmem_size is zero, nothing will be allocated or reserved.
80 * - If fbmem_start is zero when setup_bootmem() is called,
81 * fbmem_size bytes will be allocated from the bootmem allocator.
82 * - If fbmem_start is nonzero, an area of size fbmem_size will be
83 * reserved at the physical address fbmem_start if necessary. If
84 * the area isn't in a memory region known to the kernel, it will
85 * be left alone.
86 *
87 * Board-specific code may use these variables to set up platform data
88 * for the framebuffer driver if fbmem_size is nonzero.
89 */
90static unsigned long __initdata fbmem_start;
91static unsigned long __initdata fbmem_size;
92
93/*
94 * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for
95 * use as framebuffer.
96 *
97 * "fbmem=xxx[kKmM]@yyy[kKmM]" defines a memory region of size xxx and
98 * starting at yyy to be reserved for use as framebuffer.
99 *
100 * The kernel won't verify that the memory region starting at yyy
101 * actually contains usable RAM.
102 */
103static int __init early_parse_fbmem(char *p)
104{
105 fbmem_size = memparse(p, &p);
106 if (*p == '@')
107 fbmem_start = memparse(p, &p);
108 return 0;
109}
110early_param("fbmem", early_parse_fbmem);
111
112static inline void __init resource_init(void)
113{
114 struct tag_mem_range *region;
115
116 kernel_code.start = __pa(init_mm.start_code);
117 kernel_code.end = __pa(init_mm.end_code - 1);
118 kernel_data.start = __pa(init_mm.end_code);
119 kernel_data.end = __pa(init_mm.brk - 1);
120
121 for (region = mem_phys; region; region = region->next) {
122 struct resource *res;
123 unsigned long phys_start, phys_end;
124
125 if (region->size == 0)
126 continue;
127
128 phys_start = region->addr;
129 phys_end = phys_start + region->size - 1;
130
131 res = alloc_bootmem_low(sizeof(*res));
132 res->name = "System RAM";
133 res->start = phys_start;
134 res->end = phys_end;
135 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
136
137 request_resource (&iomem_resource, res);
138
139 if (kernel_code.start >= res->start &&
140 kernel_code.end <= res->end)
141 request_resource (res, &kernel_code);
142 if (kernel_data.start >= res->start &&
143 kernel_data.end <= res->end)
144 request_resource (res, &kernel_data);
145 }
146}
147
148static int __init parse_tag_core(struct tag *tag)
149{
150 if (tag->hdr.size > 2) {
151 if ((tag->u.core.flags & 1) == 0)
152 root_mountflags &= ~MS_RDONLY;
153 ROOT_DEV = new_decode_dev(tag->u.core.rootdev);
154 }
155 return 0;
156}
157__tagtable(ATAG_CORE, parse_tag_core);
158
159static int __init parse_tag_mem_range(struct tag *tag,
160 struct tag_mem_range **root)
161{
162 struct tag_mem_range *cur, **pprev;
163 struct tag_mem_range *new;
164
165 /*
166 * Ignore zero-sized entries. If we're running standalone, the
167 * SDRAM code may emit such entries if something goes
168 * wrong...
169 */
170 if (tag->u.mem_range.size == 0)
171 return 0;
172
173 /*
174 * Copy the data so the bootmem init code doesn't need to care
175 * about it.
176 */
177 if (mem_range_next_free >=
178 (sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
179 panic("Physical memory map too complex!\n");
180
181 new = &mem_range_cache[mem_range_next_free++];
182 *new = tag->u.mem_range;
183
184 pprev = root;
185 cur = *root;
186 while (cur) {
187 pprev = &cur->next;
188 cur = cur->next;
189 }
190
191 *pprev = new;
192 new->next = NULL;
193
194 return 0;
195}
196
197static int __init parse_tag_mem(struct tag *tag)
198{
199 return parse_tag_mem_range(tag, &mem_phys);
200}
201__tagtable(ATAG_MEM, parse_tag_mem);
202
203static int __init parse_tag_cmdline(struct tag *tag)
204{
205 strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
206 return 0;
207}
208__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
209
210static int __init parse_tag_rdimg(struct tag *tag)
211{
212 return parse_tag_mem_range(tag, &mem_ramdisk);
213}
214__tagtable(ATAG_RDIMG, parse_tag_rdimg);
215
216static int __init parse_tag_clock(struct tag *tag)
217{
218 /*
219 * We'll figure out the clocks by peeking at the system
220 * manager regs directly.
221 */
222 return 0;
223}
224__tagtable(ATAG_CLOCK, parse_tag_clock);
225
226static int __init parse_tag_rsvd_mem(struct tag *tag)
227{
228 return parse_tag_mem_range(tag, &mem_reserved);
229}
230__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
231
232static int __init parse_tag_ethernet(struct tag *tag)
233{
234#if 0
235 const struct platform_device *pdev;
236
237 /*
238 * We really need a bus type that supports "classes"...this
239 * will do for now (until we must handle other kinds of
240 * ethernet controllers)
241 */
242 pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
243 if (pdev && pdev->dev.platform_data) {
244 struct eth_platform_data *data = pdev->dev.platform_data;
245
246 data->valid = 1;
247 data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
248 memcpy(data->hw_addr, tag->u.ethernet.hw_address,
249 sizeof(data->hw_addr));
250 }
251#endif
252 return 0;
253}
254__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
255
256/*
257 * Scan the tag table for this tag, and call its parse function. The
258 * tag table is built by the linker from all the __tagtable
259 * declarations.
260 */
261static int __init parse_tag(struct tag *tag)
262{
263 extern struct tagtable __tagtable_begin, __tagtable_end;
264 struct tagtable *t;
265
266 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
267 if (tag->hdr.tag == t->tag) {
268 t->parse(tag);
269 break;
270 }
271
272 return t < &__tagtable_end;
273}
274
275/*
276 * Parse all tags in the list we got from the boot loader
277 */
278static void __init parse_tags(struct tag *t)
279{
280 for (; t->hdr.tag != ATAG_NONE; t = tag_next(t))
281 if (!parse_tag(t))
282 printk(KERN_WARNING
283 "Ignoring unrecognised tag 0x%08x\n",
284 t->hdr.tag);
285}
286
287void __init setup_arch (char **cmdline_p)
288{
289 struct clk *cpu_clk;
290
291 parse_tags(bootloader_tags);
292
293 setup_processor();
294 setup_platform();
295
296 cpu_clk = clk_get(NULL, "cpu");
297 if (IS_ERR(cpu_clk)) {
298 printk(KERN_WARNING "Warning: Unable to get CPU clock\n");
299 } else {
300 unsigned long cpu_hz = clk_get_rate(cpu_clk);
301
302 /*
303 * Well, duh, but it's probably a good idea to
304 * increment the use count.
305 */
306 clk_enable(cpu_clk);
307
308 boot_cpu_data.clk = cpu_clk;
309 boot_cpu_data.loops_per_jiffy = cpu_hz * 4;
310 printk("CPU: Running at %lu.%03lu MHz\n",
311 ((cpu_hz + 500) / 1000) / 1000,
312 ((cpu_hz + 500) / 1000) % 1000);
313 }
314
315 init_mm.start_code = (unsigned long) &_text;
316 init_mm.end_code = (unsigned long) &_etext;
317 init_mm.end_data = (unsigned long) &_edata;
318 init_mm.brk = (unsigned long) &_end;
319
320 strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
321 *cmdline_p = command_line;
322 parse_early_param();
323
324 setup_bootmem();
325
326 board_setup_fbmem(fbmem_start, fbmem_size);
327
328#ifdef CONFIG_VT
329 conswitchp = &dummy_con;
330#endif
331
332 paging_init();
333
334 resource_init();
335}
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
new file mode 100644
index 000000000000..33096651c24f
--- /dev/null
+++ b/arch/avr32/kernel/signal.c
@@ -0,0 +1,328 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on linux/arch/sh/kernel/signal.c
5 * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <linux/errno.h>
16#include <linux/ptrace.h>
17#include <linux/unistd.h>
18#include <linux/suspend.h>
19
20#include <asm/uaccess.h>
21#include <asm/ucontext.h>
22
23#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
24
25asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
26 struct pt_regs *regs)
27{
28 return do_sigaltstack(uss, uoss, regs->sp);
29}
30
31struct rt_sigframe
32{
33 struct siginfo info;
34 struct ucontext uc;
35 unsigned long retcode;
36};
37
38static int
39restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
40{
41 int err = 0;
42
43#define COPY(x) err |= __get_user(regs->x, &sc->x)
44 COPY(sr);
45 COPY(pc);
46 COPY(lr);
47 COPY(sp);
48 COPY(r12);
49 COPY(r11);
50 COPY(r10);
51 COPY(r9);
52 COPY(r8);
53 COPY(r7);
54 COPY(r6);
55 COPY(r5);
56 COPY(r4);
57 COPY(r3);
58 COPY(r2);
59 COPY(r1);
60 COPY(r0);
61#undef COPY
62
63 /*
64 * Don't allow anyone to pretend they're running in supervisor
65 * mode or something...
66 */
67 err |= !valid_user_regs(regs);
68
69 return err;
70}
71
72
73asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
74{
75 struct rt_sigframe __user *frame;
76 sigset_t set;
77
78 frame = (struct rt_sigframe __user *)regs->sp;
79 pr_debug("SIG return: frame = %p\n", frame);
80
81 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
82 goto badframe;
83
84 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
85 goto badframe;
86
87 sigdelsetmask(&set, ~_BLOCKABLE);
88 spin_lock_irq(&current->sighand->siglock);
89 current->blocked = set;
90 recalc_sigpending();
91 spin_unlock_irq(&current->sighand->siglock);
92
93 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
94 goto badframe;
95
96 pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n",
97 regs->pc, regs->lr, regs->sp);
98
99 return regs->r12;
100
101badframe:
102 force_sig(SIGSEGV, current);
103 return 0;
104}
105
106static int
107setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
108{
109 int err = 0;
110
111#define COPY(x) err |= __put_user(regs->x, &sc->x)
112 COPY(sr);
113 COPY(pc);
114 COPY(lr);
115 COPY(sp);
116 COPY(r12);
117 COPY(r11);
118 COPY(r10);
119 COPY(r9);
120 COPY(r8);
121 COPY(r7);
122 COPY(r6);
123 COPY(r5);
124 COPY(r4);
125 COPY(r3);
126 COPY(r2);
127 COPY(r1);
128 COPY(r0);
129#undef COPY
130
131 return err;
132}
133
134static inline void __user *
135get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
136{
137 unsigned long sp = regs->sp;
138
139 if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
140 sp = current->sas_ss_sp + current->sas_ss_size;
141
142 return (void __user *)((sp - framesize) & ~3);
143}
144
145static int
146setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
147 sigset_t *set, struct pt_regs *regs)
148{
149 struct rt_sigframe __user *frame;
150 int err = 0;
151
152 frame = get_sigframe(ka, regs, sizeof(*frame));
153 err = -EFAULT;
154 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
155 goto out;
156
157 /*
158 * Set up the return code:
159 *
160 * mov r8, __NR_rt_sigreturn
161 * scall
162 *
163 * Note: This will blow up since we're using a non-executable
164 * stack. Better use SA_RESTORER.
165 */
166#if __NR_rt_sigreturn > 127
167# error __NR_rt_sigreturn must be < 127 to fit in a short mov
168#endif
169 err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
170 &frame->retcode);
171
172 err |= copy_siginfo_to_user(&frame->info, info);
173
174 /* Set up the ucontext */
175 err |= __put_user(0, &frame->uc.uc_flags);
176 err |= __put_user(NULL, &frame->uc.uc_link);
177 err |= __put_user((void __user *)current->sas_ss_sp,
178 &frame->uc.uc_stack.ss_sp);
179 err |= __put_user(sas_ss_flags(regs->sp),
180 &frame->uc.uc_stack.ss_flags);
181 err |= __put_user(current->sas_ss_size,
182 &frame->uc.uc_stack.ss_size);
183 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
184 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
185
186 if (err)
187 goto out;
188
189 regs->r12 = sig;
190 regs->r11 = (unsigned long) &frame->info;
191 regs->r10 = (unsigned long) &frame->uc;
192 regs->sp = (unsigned long) frame;
193 if (ka->sa.sa_flags & SA_RESTORER)
194 regs->lr = (unsigned long)ka->sa.sa_restorer;
195 else {
196 printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
197 current->comm, current->pid);
198 regs->lr = (unsigned long) &frame->retcode;
199 }
200
201 pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
202 current->comm, current->pid, sig, regs->sp,
203 regs->pc, ka->sa.sa_handler, regs->lr);
204
205 regs->pc = (unsigned long) ka->sa.sa_handler;
206
207out:
208 return err;
209}
210
211static inline void restart_syscall(struct pt_regs *regs)
212{
213 if (regs->r12 == -ERESTART_RESTARTBLOCK)
214 regs->r8 = __NR_restart_syscall;
215 else
216 regs->r12 = regs->r12_orig;
217 regs->pc -= 2;
218}
219
220static inline void
221handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
222 sigset_t *oldset, struct pt_regs *regs, int syscall)
223{
224 int ret;
225
226 /*
227 * Set up the stack frame
228 */
229 ret = setup_rt_frame(sig, ka, info, oldset, regs);
230
231 /*
232 * Check that the resulting registers are sane
233 */
234 ret |= !valid_user_regs(regs);
235
236 /*
237 * Block the signal if we were unsuccessful.
238 */
239 if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
240 spin_lock_irq(&current->sighand->siglock);
241 sigorsets(&current->blocked, &current->blocked,
242 &ka->sa.sa_mask);
243 sigaddset(&current->blocked, sig);
244 recalc_sigpending();
245 spin_unlock_irq(&current->sighand->siglock);
246 }
247
248 if (ret == 0)
249 return;
250
251 force_sigsegv(sig, current);
252}
253
254/*
255 * Note that 'init' is a special process: it doesn't get signals it
256 * doesn't want to handle. Thus you cannot kill init even with a
257 * SIGKILL even by mistake.
258 */
259int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
260{
261 siginfo_t info;
262 int signr;
263 struct k_sigaction ka;
264
265 /*
266 * We want the common case to go fast, which is why we may in
267 * certain cases get here from kernel mode. Just return
268 * without doing anything if so.
269 */
270 if (!user_mode(regs))
271 return 0;
272
273 if (try_to_freeze()) {
274 signr = 0;
275 if (!signal_pending(current))
276 goto no_signal;
277 }
278
279 if (test_thread_flag(TIF_RESTORE_SIGMASK))
280 oldset = &current->saved_sigmask;
281 else if (!oldset)
282 oldset = &current->blocked;
283
284 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
285no_signal:
286 if (syscall) {
287 switch (regs->r12) {
288 case -ERESTART_RESTARTBLOCK:
289 case -ERESTARTNOHAND:
290 if (signr > 0) {
291 regs->r12 = -EINTR;
292 break;
293 }
294 /* fall through */
295 case -ERESTARTSYS:
296 if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
297 regs->r12 = -EINTR;
298 break;
299 }
300 /* fall through */
301 case -ERESTARTNOINTR:
302 restart_syscall(regs);
303 }
304 }
305
306 if (signr == 0) {
307 /* No signal to deliver -- put the saved sigmask back */
308 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
309 clear_thread_flag(TIF_RESTORE_SIGMASK);
310 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
311 }
312 return 0;
313 }
314
315 handle_signal(signr, &ka, &info, oldset, regs, syscall);
316 return 1;
317}
318
319asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
320{
321 int syscall = 0;
322
323 if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
324 syscall = 1;
325
326 if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
327 do_signal(regs, &current->blocked, syscall);
328}
diff --git a/arch/avr32/kernel/switch_to.S b/arch/avr32/kernel/switch_to.S
new file mode 100644
index 000000000000..a48d046723c5
--- /dev/null
+++ b/arch/avr32/kernel/switch_to.S
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <asm/sysreg.h>
10
11 .text
12 .global __switch_to
13 .type __switch_to, @function
14
15 /* Switch thread context from "prev" to "next", returning "last"
16 * r12 : prev
17 * r11 : &prev->thread + 1
18 * r10 : &next->thread
19 */
20__switch_to:
21 stm --r11, r0,r1,r2,r3,r4,r5,r6,r7,sp,lr
22 mfsr r9, SYSREG_SR
23 st.w --r11, r9
24 ld.w r8, r10++
25 /*
26 * schedule() may have been called from a mode with a different
27 * set of registers. Make sure we don't lose anything here.
28 */
29 pushm r10,r12
30 mtsr SYSREG_SR, r8
31 frs /* flush the return stack */
32 sub pc, -2 /* flush the pipeline */
33 popm r10,r12
34 ldm r10++, r0,r1,r2,r3,r4,r5,r6,r7,sp,pc
35 .size __switch_to, . - __switch_to
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c
new file mode 100644
index 000000000000..6ec5693da448
--- /dev/null
+++ b/arch/avr32/kernel/sys_avr32.c
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/errno.h>
9#include <linux/fs.h>
10#include <linux/file.h>
11#include <linux/mm.h>
12#include <linux/unistd.h>
13
14#include <asm/mman.h>
15#include <asm/uaccess.h>
16
17asmlinkage int sys_pipe(unsigned long __user *filedes)
18{
19 int fd[2];
20 int error;
21
22 error = do_pipe(fd);
23 if (!error) {
24 if (copy_to_user(filedes, fd, sizeof(fd)))
25 error = -EFAULT;
26 }
27 return error;
28}
29
30asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
31 unsigned long prot, unsigned long flags,
32 unsigned long fd, off_t offset)
33{
34 int error = -EBADF;
35 struct file *file = NULL;
36
37 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
38 if (!(flags & MAP_ANONYMOUS)) {
39 file = fget(fd);
40 if (!file)
41 return error;
42 }
43
44 down_write(&current->mm->mmap_sem);
45 error = do_mmap_pgoff(file, addr, len, prot, flags, offset);
46 up_write(&current->mm->mmap_sem);
47
48 if (file)
49 fput(file);
50 return error;
51}
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
new file mode 100644
index 000000000000..7589a9b426cb
--- /dev/null
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -0,0 +1,102 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/*
10 * Stubs for syscalls that require access to pt_regs or that take more
11 * than five parameters.
12 */
13
14#define ARG6 r3
15
16 .text
17 .global __sys_rt_sigsuspend
18 .type __sys_rt_sigsuspend,@function
19__sys_rt_sigsuspend:
20 mov r10, sp
21 rjmp sys_rt_sigsuspend
22
23 .global __sys_sigaltstack
24 .type __sys_sigaltstack,@function
25__sys_sigaltstack:
26 mov r10, sp
27 rjmp sys_sigaltstack
28
29 .global __sys_rt_sigreturn
30 .type __sys_rt_sigreturn,@function
31__sys_rt_sigreturn:
32 mov r12, sp
33 rjmp sys_rt_sigreturn
34
35 .global __sys_fork
36 .type __sys_fork,@function
37__sys_fork:
38 mov r12, sp
39 rjmp sys_fork
40
41 .global __sys_clone
42 .type __sys_clone,@function
43__sys_clone:
44 mov r8, sp
45 rjmp sys_clone
46
47 .global __sys_vfork
48 .type __sys_vfork,@function
49__sys_vfork:
50 mov r12, sp
51 rjmp sys_vfork
52
53 .global __sys_execve
54 .type __sys_execve,@function
55__sys_execve:
56 mov r9, sp
57 rjmp sys_execve
58
59 .global __sys_mmap2
60 .type __sys_mmap2,@function
61__sys_mmap2:
62 pushm lr
63 st.w --sp, ARG6
64 rcall sys_mmap2
65 sub sp, -4
66 popm pc
67
68 .global __sys_sendto
69 .type __sys_sendto,@function
70__sys_sendto:
71 pushm lr
72 st.w --sp, ARG6
73 rcall sys_sendto
74 sub sp, -4
75 popm pc
76
77 .global __sys_recvfrom
78 .type __sys_recvfrom,@function
79__sys_recvfrom:
80 pushm lr
81 st.w --sp, ARG6
82 rcall sys_recvfrom
83 sub sp, -4
84 popm pc
85
86 .global __sys_pselect6
87 .type __sys_pselect6,@function
88__sys_pselect6:
89 pushm lr
90 st.w --sp, ARG6
91 rcall sys_pselect6
92 sub sp, -4
93 popm pc
94
95 .global __sys_splice
96 .type __sys_splice,@function
97__sys_splice:
98 pushm lr
99 st.w --sp, ARG6
100 rcall sys_splice
101 sub sp, -4
102 popm pc
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
new file mode 100644
index 000000000000..63b206965d05
--- /dev/null
+++ b/arch/avr32/kernel/syscall_table.S
@@ -0,0 +1,289 @@
1/*
2 * AVR32 system call table
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
12#define sys_nfsservctl sys_ni_syscall
13#endif
14
15#if !defined(CONFIG_SYSV_IPC)
16# define sys_ipc sys_ni_syscall
17#endif
18
19 .section .rodata,"a",@progbits
20 .type sys_call_table,@object
21 .global sys_call_table
22 .align 2
23sys_call_table:
24 .long sys_restart_syscall
25 .long sys_exit
26 .long __sys_fork
27 .long sys_read
28 .long sys_write
29 .long sys_open /* 5 */
30 .long sys_close
31 .long sys_umask
32 .long sys_creat
33 .long sys_link
34 .long sys_unlink /* 10 */
35 .long __sys_execve
36 .long sys_chdir
37 .long sys_time
38 .long sys_mknod
39 .long sys_chmod /* 15 */
40 .long sys_chown
41 .long sys_lchown
42 .long sys_lseek
43 .long sys_llseek
44 .long sys_getpid /* 20 */
45 .long sys_mount
46 .long sys_umount
47 .long sys_setuid
48 .long sys_getuid
49 .long sys_stime /* 25 */
50 .long sys_ptrace
51 .long sys_alarm
52 .long sys_pause
53 .long sys_utime
54 .long sys_newstat /* 30 */
55 .long sys_newfstat
56 .long sys_newlstat
57 .long sys_access
58 .long sys_chroot
59 .long sys_sync /* 35 */
60 .long sys_fsync
61 .long sys_kill
62 .long sys_rename
63 .long sys_mkdir
64 .long sys_rmdir /* 40 */
65 .long sys_dup
66 .long sys_pipe
67 .long sys_times
68 .long __sys_clone
69 .long sys_brk /* 45 */
70 .long sys_setgid
71 .long sys_getgid
72 .long sys_getcwd
73 .long sys_geteuid
74 .long sys_getegid /* 50 */
75 .long sys_acct
76 .long sys_setfsuid
77 .long sys_setfsgid
78 .long sys_ioctl
79 .long sys_fcntl /* 55 */
80 .long sys_setpgid
81 .long sys_mremap
82 .long sys_setresuid
83 .long sys_getresuid
84 .long sys_setreuid /* 60 */
85 .long sys_setregid
86 .long sys_ustat
87 .long sys_dup2
88 .long sys_getppid
89 .long sys_getpgrp /* 65 */
90 .long sys_setsid
91 .long sys_rt_sigaction
92 .long __sys_rt_sigreturn
93 .long sys_rt_sigprocmask
94 .long sys_rt_sigpending /* 70 */
95 .long sys_rt_sigtimedwait
96 .long sys_rt_sigqueueinfo
97 .long __sys_rt_sigsuspend
98 .long sys_sethostname
99 .long sys_setrlimit /* 75 */
100 .long sys_getrlimit
101 .long sys_getrusage
102 .long sys_gettimeofday
103 .long sys_settimeofday
104 .long sys_getgroups /* 80 */
105 .long sys_setgroups
106 .long sys_select
107 .long sys_symlink
108 .long sys_fchdir
109 .long sys_readlink /* 85 */
110 .long sys_pread64
111 .long sys_pwrite64
112 .long sys_swapon
113 .long sys_reboot
114 .long __sys_mmap2 /* 90 */
115 .long sys_munmap
116 .long sys_truncate
117 .long sys_ftruncate
118 .long sys_fchmod
119 .long sys_fchown /* 95 */
120 .long sys_getpriority
121 .long sys_setpriority
122 .long sys_wait4
123 .long sys_statfs
124 .long sys_fstatfs /* 100 */
125 .long sys_vhangup
126 .long __sys_sigaltstack
127 .long sys_syslog
128 .long sys_setitimer
129 .long sys_getitimer /* 105 */
130 .long sys_swapoff
131 .long sys_sysinfo
132 .long sys_ipc
133 .long sys_sendfile
134 .long sys_setdomainname /* 110 */
135 .long sys_newuname
136 .long sys_adjtimex
137 .long sys_mprotect
138 .long __sys_vfork
139 .long sys_init_module /* 115 */
140 .long sys_delete_module
141 .long sys_quotactl
142 .long sys_getpgid
143 .long sys_bdflush
144 .long sys_sysfs /* 120 */
145 .long sys_personality
146 .long sys_ni_syscall /* reserved for afs_syscall */
147 .long sys_getdents
148 .long sys_flock
149 .long sys_msync /* 125 */
150 .long sys_readv
151 .long sys_writev
152 .long sys_getsid
153 .long sys_fdatasync
154 .long sys_sysctl /* 130 */
155 .long sys_mlock
156 .long sys_munlock
157 .long sys_mlockall
158 .long sys_munlockall
159 .long sys_sched_setparam /* 135 */
160 .long sys_sched_getparam
161 .long sys_sched_setscheduler
162 .long sys_sched_getscheduler
163 .long sys_sched_yield
164 .long sys_sched_get_priority_max /* 140 */
165 .long sys_sched_get_priority_min
166 .long sys_sched_rr_get_interval
167 .long sys_nanosleep
168 .long sys_poll
169 .long sys_nfsservctl /* 145 */
170 .long sys_setresgid
171 .long sys_getresgid
172 .long sys_prctl
173 .long sys_socket
174 .long sys_bind /* 150 */
175 .long sys_connect
176 .long sys_listen
177 .long sys_accept
178 .long sys_getsockname
179 .long sys_getpeername /* 155 */
180 .long sys_socketpair
181 .long sys_send
182 .long sys_recv
183 .long __sys_sendto
184 .long __sys_recvfrom /* 160 */
185 .long sys_shutdown
186 .long sys_setsockopt
187 .long sys_getsockopt
188 .long sys_sendmsg
189 .long sys_recvmsg /* 165 */
190 .long sys_truncate64
191 .long sys_ftruncate64
192 .long sys_stat64
193 .long sys_lstat64
194 .long sys_fstat64 /* 170 */
195 .long sys_pivot_root
196 .long sys_mincore
197 .long sys_madvise
198 .long sys_getdents64
199 .long sys_fcntl64 /* 175 */
200 .long sys_gettid
201 .long sys_readahead
202 .long sys_setxattr
203 .long sys_lsetxattr
204 .long sys_fsetxattr /* 180 */
205 .long sys_getxattr
206 .long sys_lgetxattr
207 .long sys_fgetxattr
208 .long sys_listxattr
209 .long sys_llistxattr /* 185 */
210 .long sys_flistxattr
211 .long sys_removexattr
212 .long sys_lremovexattr
213 .long sys_fremovexattr
214 .long sys_tkill /* 190 */
215 .long sys_sendfile64
216 .long sys_futex
217 .long sys_sched_setaffinity
218 .long sys_sched_getaffinity
219 .long sys_capget /* 195 */
220 .long sys_capset
221 .long sys_io_setup
222 .long sys_io_destroy
223 .long sys_io_getevents
224 .long sys_io_submit /* 200 */
225 .long sys_io_cancel
226 .long sys_fadvise64
227 .long sys_exit_group
228 .long sys_lookup_dcookie
229 .long sys_epoll_create /* 205 */
230 .long sys_epoll_ctl
231 .long sys_epoll_wait
232 .long sys_remap_file_pages
233 .long sys_set_tid_address
234 .long sys_timer_create /* 210 */
235 .long sys_timer_settime
236 .long sys_timer_gettime
237 .long sys_timer_getoverrun
238 .long sys_timer_delete
239 .long sys_clock_settime /* 215 */
240 .long sys_clock_gettime
241 .long sys_clock_getres
242 .long sys_clock_nanosleep
243 .long sys_statfs64
244 .long sys_fstatfs64 /* 220 */
245 .long sys_tgkill
246 .long sys_ni_syscall /* reserved for TUX */
247 .long sys_utimes
248 .long sys_fadvise64_64
249 .long sys_cacheflush /* 225 */
250 .long sys_ni_syscall /* sys_vserver */
251 .long sys_mq_open
252 .long sys_mq_unlink
253 .long sys_mq_timedsend
254 .long sys_mq_timedreceive /* 230 */
255 .long sys_mq_notify
256 .long sys_mq_getsetattr
257 .long sys_kexec_load
258 .long sys_waitid
259 .long sys_add_key /* 235 */
260 .long sys_request_key
261 .long sys_keyctl
262 .long sys_ioprio_set
263 .long sys_ioprio_get
264 .long sys_inotify_init /* 240 */
265 .long sys_inotify_add_watch
266 .long sys_inotify_rm_watch
267 .long sys_openat
268 .long sys_mkdirat
269 .long sys_mknodat /* 245 */
270 .long sys_fchownat
271 .long sys_futimesat
272 .long sys_fstatat64
273 .long sys_unlinkat
274 .long sys_renameat /* 250 */
275 .long sys_linkat
276 .long sys_symlinkat
277 .long sys_readlinkat
278 .long sys_fchmodat
279 .long sys_faccessat /* 255 */
280 .long __sys_pselect6
281 .long sys_ppoll
282 .long sys_unshare
283 .long sys_set_robust_list
284 .long sys_get_robust_list /* 260 */
285 .long __sys_splice
286 .long sys_sync_file_range
287 .long sys_tee
288 .long sys_vmsplice
289 .long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
new file mode 100644
index 000000000000..b0e6b5855a38
--- /dev/null
+++ b/arch/avr32/kernel/time.c
@@ -0,0 +1,238 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on MIPS implementation arch/mips/kernel/time.c
5 * Copyright 2001 MontaVista Software Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/clocksource.h>
14#include <linux/time.h>
15#include <linux/module.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18#include <linux/kernel_stat.h>
19#include <linux/errno.h>
20#include <linux/init.h>
21#include <linux/profile.h>
22#include <linux/sysdev.h>
23
24#include <asm/div64.h>
25#include <asm/sysreg.h>
26#include <asm/io.h>
27#include <asm/sections.h>
28
29static cycle_t read_cycle_count(void)
30{
31 return (cycle_t)sysreg_read(COUNT);
32}
33
34static struct clocksource clocksource_avr32 = {
35 .name = "avr32",
36 .rating = 350,
37 .read = read_cycle_count,
38 .mask = CLOCKSOURCE_MASK(32),
39 .shift = 16,
40 .is_continuous = 1,
41};
42
43/*
44 * By default we provide the null RTC ops
45 */
46static unsigned long null_rtc_get_time(void)
47{
48 return mktime(2004, 1, 1, 0, 0, 0);
49}
50
51static int null_rtc_set_time(unsigned long sec)
52{
53 return 0;
54}
55
56static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
57static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
58
59/* how many counter cycles in a jiffy? */
60static unsigned long cycles_per_jiffy;
61
62/* cycle counter value at the previous timer interrupt */
63static unsigned int timerhi, timerlo;
64
65/* the count value for the next timer interrupt */
66static unsigned int expirelo;
67
68static void avr32_timer_ack(void)
69{
70 unsigned int count;
71
72 /* Ack this timer interrupt and set the next one */
73 expirelo += cycles_per_jiffy;
74 if (expirelo == 0) {
75 printk(KERN_DEBUG "expirelo == 0\n");
76 sysreg_write(COMPARE, expirelo + 1);
77 } else {
78 sysreg_write(COMPARE, expirelo);
79 }
80
81 /* Check to see if we have missed any timer interrupts */
82 count = sysreg_read(COUNT);
83 if ((count - expirelo) < 0x7fffffff) {
84 expirelo = count + cycles_per_jiffy;
85 sysreg_write(COMPARE, expirelo);
86 }
87}
88
89static unsigned int avr32_hpt_read(void)
90{
91 return sysreg_read(COUNT);
92}
93
94/*
95 * Taken from MIPS c0_hpt_timer_init().
96 *
97 * Why is it so complicated, and what is "count"? My assumption is
98 * that `count' specifies the "reference cycle", i.e. the cycle since
99 * reset that should mean "zero". The reason COUNT is written twice is
100 * probably to make sure we don't get any timer interrupts while we
101 * are messing with the counter.
102 */
103static void avr32_hpt_init(unsigned int count)
104{
105 count = sysreg_read(COUNT) - count;
106 expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
107 sysreg_write(COUNT, expirelo - cycles_per_jiffy);
108 sysreg_write(COMPARE, expirelo);
109 sysreg_write(COUNT, count);
110}
111
112/*
113 * Scheduler clock - returns current time in nanosec units.
114 */
115unsigned long long sched_clock(void)
116{
117 /* There must be better ways...? */
118 return (unsigned long long)jiffies * (1000000000 / HZ);
119}
120
121/*
122 * local_timer_interrupt() does profiling and process accounting on a
123 * per-CPU basis.
124 *
125 * In UP mode, it is invoked from the (global) timer_interrupt.
126 */
127static void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
128{
129 if (current->pid)
130 profile_tick(CPU_PROFILING, regs);
131 update_process_times(user_mode(regs));
132}
133
134static irqreturn_t
135timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
136{
137 unsigned int count;
138
139 /* ack timer interrupt and try to set next interrupt */
140 count = avr32_hpt_read();
141 avr32_timer_ack();
142
143 /* Update timerhi/timerlo for intra-jiffy calibration */
144 timerhi += count < timerlo; /* Wrap around */
145 timerlo = count;
146
147 /*
148 * Call the generic timer interrupt handler
149 */
150 write_seqlock(&xtime_lock);
151 do_timer(regs);
152 write_sequnlock(&xtime_lock);
153
154 /*
155 * In UP mode, we call local_timer_interrupt() to do profiling
156 * and process accounting.
157 *
158 * SMP is not supported yet.
159 */
160 local_timer_interrupt(irq, dev_id, regs);
161
162 return IRQ_HANDLED;
163}
164
165static struct irqaction timer_irqaction = {
166 .handler = timer_interrupt,
167 .flags = IRQF_DISABLED,
168 .name = "timer",
169};
170
171void __init time_init(void)
172{
173 unsigned long mult, shift, count_hz;
174 int ret;
175
176 xtime.tv_sec = rtc_get_time();
177 xtime.tv_nsec = 0;
178
179 set_normalized_timespec(&wall_to_monotonic,
180 -xtime.tv_sec, -xtime.tv_nsec);
181
182 printk("Before time_init: count=%08lx, compare=%08lx\n",
183 (unsigned long)sysreg_read(COUNT),
184 (unsigned long)sysreg_read(COMPARE));
185
186 count_hz = clk_get_rate(boot_cpu_data.clk);
187 shift = clocksource_avr32.shift;
188 mult = clocksource_hz2mult(count_hz, shift);
189 clocksource_avr32.mult = mult;
190
191 printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift);
192
193 {
194 u64 tmp;
195
196 tmp = TICK_NSEC;
197 tmp <<= shift;
198 tmp += mult / 2;
199 do_div(tmp, mult);
200
201 cycles_per_jiffy = tmp;
202 }
203
204 /* This sets up the high precision timer for the first interrupt. */
205 avr32_hpt_init(avr32_hpt_read());
206
207 printk("After time_init: count=%08lx, compare=%08lx\n",
208 (unsigned long)sysreg_read(COUNT),
209 (unsigned long)sysreg_read(COMPARE));
210
211 ret = clocksource_register(&clocksource_avr32);
212 if (ret)
213 printk(KERN_ERR
214 "timer: could not register clocksource: %d\n", ret);
215
216 ret = setup_irq(0, &timer_irqaction);
217 if (ret)
218 printk("timer: could not request IRQ 0: %d\n", ret);
219}
220
221static struct sysdev_class timer_class = {
222 set_kset_name("timer"),
223};
224
225static struct sys_device timer_device = {
226 .id = 0,
227 .cls = &timer_class,
228};
229
230static int __init init_timer_sysfs(void)
231{
232 int err = sysdev_class_register(&timer_class);
233 if (!err)
234 err = sysdev_register(&timer_device);
235 return err;
236}
237
238device_initcall(init_timer_sysfs);
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
new file mode 100644
index 000000000000..7e803f4d7a12
--- /dev/null
+++ b/arch/avr32/kernel/traps.c
@@ -0,0 +1,425 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#undef DEBUG
9#include <linux/sched.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/kallsyms.h>
13#include <linux/notifier.h>
14
15#include <asm/traps.h>
16#include <asm/sysreg.h>
17#include <asm/addrspace.h>
18#include <asm/ocd.h>
19#include <asm/mmu_context.h>
20#include <asm/uaccess.h>
21
22static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
23{
24 unsigned long p;
25 int i;
26
27 printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
28
29 for (p = bottom & ~31; p < top; ) {
30 printk("%04lx: ", p & 0xffff);
31
32 for (i = 0; i < 8; i++, p += 4) {
33 unsigned int val;
34
35 if (p < bottom || p >= top)
36 printk(" ");
37 else {
38 if (__get_user(val, (unsigned int __user *)p)) {
39 printk("\n");
40 goto out;
41 }
42 printk("%08x ", val);
43 }
44 }
45 printk("\n");
46 }
47
48out:
49 return;
50}
51
52#ifdef CONFIG_FRAME_POINTER
53static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
54 struct pt_regs *regs)
55{
56 unsigned long __user *fp;
57 unsigned long __user *last_fp = NULL;
58
59 if (regs) {
60 fp = (unsigned long __user *)regs->r7;
61 } else if (tsk == current) {
62 register unsigned long __user *real_fp __asm__("r7");
63 fp = real_fp;
64 } else {
65 fp = (unsigned long __user *)tsk->thread.cpu_context.r7;
66 }
67
68 /*
69 * Walk the stack until (a) we get an exception, (b) the frame
70 * pointer becomes zero, or (c) the frame pointer gets stuck
71 * at the same value.
72 */
73 while (fp && fp != last_fp) {
74 unsigned long lr, new_fp = 0;
75
76 last_fp = fp;
77 if (__get_user(lr, fp))
78 break;
79 if (fp && __get_user(new_fp, fp + 1))
80 break;
81 fp = (unsigned long __user *)new_fp;
82
83 printk(" [<%08lx>] ", lr);
84 print_symbol("%s\n", lr);
85 }
86 printk("\n");
87}
88#else
89static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
90 struct pt_regs *regs)
91{
92 unsigned long addr;
93
94 while (!kstack_end(sp)) {
95 addr = *sp++;
96 if (kernel_text_address(addr)) {
97 printk(" [<%08lx>] ", addr);
98 print_symbol("%s\n", addr);
99 }
100 }
101}
102#endif
103
104void show_trace(struct task_struct *tsk, unsigned long *sp,
105 struct pt_regs *regs)
106{
107 if (regs &&
108 (((regs->sr & MODE_MASK) == MODE_EXCEPTION) ||
109 ((regs->sr & MODE_MASK) == MODE_USER)))
110 return;
111
112 printk ("Call trace:");
113#ifdef CONFIG_KALLSYMS
114 printk("\n");
115#endif
116
117 __show_trace(tsk, sp, regs);
118 printk("\n");
119}
120
121void show_stack(struct task_struct *tsk, unsigned long *sp)
122{
123 unsigned long stack;
124
125 if (!tsk)
126 tsk = current;
127 if (sp == 0) {
128 if (tsk == current) {
129 register unsigned long *real_sp __asm__("sp");
130 sp = real_sp;
131 } else {
132 sp = (unsigned long *)tsk->thread.cpu_context.ksp;
133 }
134 }
135
136 stack = (unsigned long)sp;
137 dump_mem("Stack: ", stack,
138 THREAD_SIZE + (unsigned long)tsk->thread_info);
139 show_trace(tsk, sp, NULL);
140}
141
142void dump_stack(void)
143{
144 show_stack(NULL, NULL);
145}
146EXPORT_SYMBOL(dump_stack);
147
148ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
149
150int register_die_notifier(struct notifier_block *nb)
151{
152 pr_debug("register_die_notifier: %p\n", nb);
153
154 return atomic_notifier_chain_register(&avr32_die_chain, nb);
155}
156EXPORT_SYMBOL(register_die_notifier);
157
158int unregister_die_notifier(struct notifier_block *nb)
159{
160 return atomic_notifier_chain_unregister(&avr32_die_chain, nb);
161}
162EXPORT_SYMBOL(unregister_die_notifier);
163
164static DEFINE_SPINLOCK(die_lock);
165
166void __die(const char *str, struct pt_regs *regs, unsigned long err,
167 const char *file, const char *func, unsigned long line)
168{
169 struct task_struct *tsk = current;
170 static int die_counter;
171
172 console_verbose();
173 spin_lock_irq(&die_lock);
174 bust_spinlocks(1);
175
176 printk(KERN_ALERT "%s", str);
177 if (file && func)
178 printk(" in %s:%s, line %ld", file, func, line);
179 printk("[#%d]:\n", ++die_counter);
180 print_modules();
181 show_regs(regs);
182 printk("Process %s (pid: %d, stack limit = 0x%p)\n",
183 tsk->comm, tsk->pid, tsk->thread_info + 1);
184
185 if (!user_mode(regs) || in_interrupt()) {
186 dump_mem("Stack: ", regs->sp,
187 THREAD_SIZE + (unsigned long)tsk->thread_info);
188 }
189
190 bust_spinlocks(0);
191 spin_unlock_irq(&die_lock);
192 do_exit(SIGSEGV);
193}
194
195void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err,
196 const char *file, const char *func, unsigned long line)
197{
198 if (!user_mode(regs))
199 __die(str, regs, err, file, func, line);
200}
201
202asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
203{
204#ifdef CONFIG_SUBARCH_AVR32B
205 /*
206 * The exception entry always saves RSR_EX. For NMI, this is
207 * wrong; it should be RSR_NMI
208 */
209 regs->sr = sysreg_read(RSR_NMI);
210#endif
211
212 printk("NMI taken!!!!\n");
213 die("NMI", regs, ecr);
214 BUG();
215}
216
217asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)
218{
219 printk("Unable to handle critical exception %lu at pc = %08lx!\n",
220 ecr, regs->pc);
221 die("Oops", regs, ecr);
222 BUG();
223}
224
225asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
226{
227 siginfo_t info;
228
229 die_if_kernel("Oops: Address exception in kernel mode", regs, ecr);
230
231#ifdef DEBUG
232 if (ecr == ECR_ADDR_ALIGN_X)
233 pr_debug("Instruction Address Exception at pc = %08lx\n",
234 regs->pc);
235 else if (ecr == ECR_ADDR_ALIGN_R)
236 pr_debug("Data Address Exception (Read) at pc = %08lx\n",
237 regs->pc);
238 else if (ecr == ECR_ADDR_ALIGN_W)
239 pr_debug("Data Address Exception (Write) at pc = %08lx\n",
240 regs->pc);
241 else
242 BUG();
243
244 show_regs(regs);
245#endif
246
247 info.si_signo = SIGBUS;
248 info.si_errno = 0;
249 info.si_code = BUS_ADRALN;
250 info.si_addr = (void __user *)regs->pc;
251
252 force_sig_info(SIGBUS, &info, current);
253}
254
255/* This way of handling undefined instructions is stolen from ARM */
256static LIST_HEAD(undef_hook);
257static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
258
259void register_undef_hook(struct undef_hook *hook)
260{
261 spin_lock_irq(&undef_lock);
262 list_add(&hook->node, &undef_hook);
263 spin_unlock_irq(&undef_lock);
264}
265
266void unregister_undef_hook(struct undef_hook *hook)
267{
268 spin_lock_irq(&undef_lock);
269 list_del(&hook->node);
270 spin_unlock_irq(&undef_lock);
271}
272
273static int do_cop_absent(u32 insn)
274{
275 int cop_nr;
276 u32 cpucr;
277 if ( (insn & 0xfdf00000) == 0xf1900000 )
278 /* LDC0 */
279 cop_nr = 0;
280 else
281 cop_nr = (insn >> 13) & 0x7;
282
283 /* Try enabling the coprocessor */
284 cpucr = sysreg_read(CPUCR);
285 cpucr |= (1 << (24 + cop_nr));
286 sysreg_write(CPUCR, cpucr);
287
288 cpucr = sysreg_read(CPUCR);
289 if ( !(cpucr & (1 << (24 + cop_nr))) ){
290 printk("Coprocessor #%i not found!\n", cop_nr);
291 return -1;
292 }
293
294 return 0;
295}
296
297#ifdef CONFIG_BUG
298#ifdef CONFIG_DEBUG_BUGVERBOSE
299static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
300{
301 char *file;
302 u16 line;
303 char c;
304
305 if (__get_user(line, (u16 __user *)(regs->pc + 2)))
306 return;
307 if (__get_user(file, (char * __user *)(regs->pc + 4))
308 || (unsigned long)file < PAGE_OFFSET
309 || __get_user(c, file))
310 file = "<bad filename>";
311
312 printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
313}
314#else
315static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
316{
317
318}
319#endif
320#endif
321
322asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
323{
324 u32 insn;
325 struct undef_hook *hook;
326 siginfo_t info;
327 void __user *pc;
328
329 if (!user_mode(regs))
330 goto kernel_trap;
331
332 local_irq_enable();
333
334 pc = (void __user *)instruction_pointer(regs);
335 if (__get_user(insn, (u32 __user *)pc))
336 goto invalid_area;
337
338 if (ecr == ECR_COPROC_ABSENT) {
339 if (do_cop_absent(insn) == 0)
340 return;
341 }
342
343 spin_lock_irq(&undef_lock);
344 list_for_each_entry(hook, &undef_hook, node) {
345 if ((insn & hook->insn_mask) == hook->insn_val) {
346 if (hook->fn(regs, insn) == 0) {
347 spin_unlock_irq(&undef_lock);
348 return;
349 }
350 }
351 }
352 spin_unlock_irq(&undef_lock);
353
354invalid_area:
355
356#ifdef DEBUG
357 printk("Illegal instruction at pc = %08lx\n", regs->pc);
358 if (regs->pc < TASK_SIZE) {
359 unsigned long ptbr, pgd, pte, *p;
360
361 ptbr = sysreg_read(PTBR);
362 p = (unsigned long *)ptbr;
363 pgd = p[regs->pc >> 22];
364 p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000);
365 pte = p[(regs->pc >> 12) & 0x3ff];
366 printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte);
367 }
368#endif
369
370 info.si_signo = SIGILL;
371 info.si_errno = 0;
372 info.si_addr = (void __user *)regs->pc;
373 switch (ecr) {
374 case ECR_ILLEGAL_OPCODE:
375 case ECR_UNIMPL_INSTRUCTION:
376 info.si_code = ILL_ILLOPC;
377 break;
378 case ECR_PRIVILEGE_VIOLATION:
379 info.si_code = ILL_PRVOPC;
380 break;
381 case ECR_COPROC_ABSENT:
382 info.si_code = ILL_COPROC;
383 break;
384 default:
385 BUG();
386 }
387
388 force_sig_info(SIGILL, &info, current);
389 return;
390
391kernel_trap:
392#ifdef CONFIG_BUG
393 if (__kernel_text_address(instruction_pointer(regs))) {
394 insn = *(u16 *)instruction_pointer(regs);
395 if (insn == AVR32_BUG_OPCODE) {
396 do_bug_verbose(regs, insn);
397 die("Kernel BUG", regs, 0);
398 return;
399 }
400 }
401#endif
402
403 die("Oops: Illegal instruction in kernel code", regs, ecr);
404}
405
406asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs)
407{
408 siginfo_t info;
409
410 printk("Floating-point exception at pc = %08lx\n", regs->pc);
411
412 /* We have no FPU... */
413 info.si_signo = SIGILL;
414 info.si_errno = 0;
415 info.si_addr = (void __user *)regs->pc;
416 info.si_code = ILL_COPROC;
417
418 force_sig_info(SIGILL, &info, current);
419}
420
421
422void __init trap_init(void)
423{
424
425}
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
new file mode 100644
index 000000000000..cdd627c6b7dc
--- /dev/null
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -0,0 +1,139 @@
1/*
2 * AVR32 linker script for the Linux kernel
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#define LOAD_OFFSET 0x00000000
11#include <asm-generic/vmlinux.lds.h>
12
13OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32")
14OUTPUT_ARCH(avr32)
15ENTRY(_start)
16
17/* Big endian */
18jiffies = jiffies_64 + 4;
19
20SECTIONS
21{
22 . = CONFIG_ENTRY_ADDRESS;
23 .init : AT(ADDR(.init) - LOAD_OFFSET) {
24 _stext = .;
25 __init_begin = .;
26 _sinittext = .;
27 *(.text.reset)
28 *(.init.text)
29 _einittext = .;
30 . = ALIGN(4);
31 __tagtable_begin = .;
32 *(.taglist)
33 __tagtable_end = .;
34 *(.init.data)
35 . = ALIGN(16);
36 __setup_start = .;
37 *(.init.setup)
38 __setup_end = .;
39 . = ALIGN(4);
40 __initcall_start = .;
41 *(.initcall1.init)
42 *(.initcall2.init)
43 *(.initcall3.init)
44 *(.initcall4.init)
45 *(.initcall5.init)
46 *(.initcall6.init)
47 *(.initcall7.init)
48 __initcall_end = .;
49 __con_initcall_start = .;
50 *(.con_initcall.init)
51 __con_initcall_end = .;
52 __security_initcall_start = .;
53 *(.security_initcall.init)
54 __security_initcall_end = .;
55 . = ALIGN(32);
56 __initramfs_start = .;
57 *(.init.ramfs)
58 __initramfs_end = .;
59 . = ALIGN(4096);
60 __init_end = .;
61 }
62
63 . = ALIGN(8192);
64 .text : AT(ADDR(.text) - LOAD_OFFSET) {
65 _evba = .;
66 _text = .;
67 *(.ex.text)
68 . = 0x50;
69 *(.tlbx.ex.text)
70 . = 0x60;
71 *(.tlbr.ex.text)
72 . = 0x70;
73 *(.tlbw.ex.text)
74 . = 0x100;
75 *(.scall.text)
76 *(.irq.text)
77 *(.text)
78 SCHED_TEXT
79 LOCK_TEXT
80 KPROBES_TEXT
81 *(.fixup)
82 *(.gnu.warning)
83 _etext = .;
84 } = 0xd703d703
85
86 . = ALIGN(4);
87 __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
88 __start___ex_table = .;
89 *(__ex_table)
90 __stop___ex_table = .;
91 }
92
93 RODATA
94
95 . = ALIGN(8192);
96
97 .data : AT(ADDR(.data) - LOAD_OFFSET) {
98 _data = .;
99 _sdata = .;
100 /*
101 * First, the init task union, aligned to an 8K boundary.
102 */
103 *(.data.init_task)
104
105 /* Then, the cacheline aligned data */
106 . = ALIGN(32);
107 *(.data.cacheline_aligned)
108
109 /* And the rest... */
110 *(.data.rel*)
111 *(.data)
112 CONSTRUCTORS
113
114 _edata = .;
115 }
116
117
118 . = ALIGN(8);
119 .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
120 __bss_start = .;
121 *(.bss)
122 *(COMMON)
123 . = ALIGN(8);
124 __bss_stop = .;
125 _end = .;
126 }
127
128 /* When something in the kernel is NOT compiled as a module, the module
129 * cleanup code and data are put into these segments. Both can then be
130 * thrown away, as cleanup code is never called unless it's a module.
131 */
132 /DISCARD/ : {
133 *(.exit.text)
134 *(.exit.data)
135 *(.exitcall.exit)
136 }
137
138 DWARF_DEBUG
139}
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile
new file mode 100644
index 000000000000..09ac43e40522
--- /dev/null
+++ b/arch/avr32/lib/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for AVR32-specific library files
3#
4
5lib-y := copy_user.o clear_user.o
6lib-y += strncpy_from_user.o strnlen_user.o
7lib-y += delay.o memset.o memcpy.o findbit.o
8lib-y += csum_partial.o csum_partial_copy_generic.o
9lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o
10lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o
diff --git a/arch/avr32/lib/__avr32_asr64.S b/arch/avr32/lib/__avr32_asr64.S
new file mode 100644
index 000000000000..368b6bca4c76
--- /dev/null
+++ b/arch/avr32/lib/__avr32_asr64.S
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 /*
10 * DWtype __avr32_asr64(DWtype u, word_type b)
11 */
12 .text
13 .global __avr32_asr64
14 .type __avr32_asr64,@function
15__avr32_asr64:
16 cp.w r12, 0
17 reteq r12
18
19 rsub r9, r12, 32
20 brle 1f
21
22 lsl r8, r11, r9
23 lsr r10, r10, r12
24 asr r11, r11, r12
25 or r10, r8
26 retal r12
27
281: neg r9
29 asr r10, r11, r9
30 asr r11, 31
31 retal r12
diff --git a/arch/avr32/lib/__avr32_lsl64.S b/arch/avr32/lib/__avr32_lsl64.S
new file mode 100644
index 000000000000..f1dbc2b36257
--- /dev/null
+++ b/arch/avr32/lib/__avr32_lsl64.S
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 /*
10 * DWtype __avr32_lsl64(DWtype u, word_type b)
11 */
12 .text
13 .global __avr32_lsl64
14 .type __avr32_lsl64,@function
15__avr32_lsl64:
16 cp.w r12, 0
17 reteq r12
18
19 rsub r9, r12, 32
20 brle 1f
21
22 lsr r8, r10, r9
23 lsl r10, r10, r12
24 lsl r11, r11, r12
25 or r11, r8
26 retal r12
27
281: neg r9
29 lsl r11, r10, r9
30 mov r10, 0
31 retal r12
diff --git a/arch/avr32/lib/__avr32_lsr64.S b/arch/avr32/lib/__avr32_lsr64.S
new file mode 100644
index 000000000000..e65bb7f0d24c
--- /dev/null
+++ b/arch/avr32/lib/__avr32_lsr64.S
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 /*
10 * DWtype __avr32_lsr64(DWtype u, word_type b)
11 */
12 .text
13 .global __avr32_lsr64
14 .type __avr32_lsr64,@function
15__avr32_lsr64:
16 cp.w r12, 0
17 reteq r12
18
19 rsub r9, r12, 32
20 brle 1f
21
22 lsl r8, r11, r9
23 lsr r11, r11, r12
24 lsr r10, r10, r12
25 or r10, r8
26 retal r12
27
281: neg r9
29 lsr r10, r11, r9
30 mov r11, 0
31 retal r12
diff --git a/arch/avr32/lib/clear_user.S b/arch/avr32/lib/clear_user.S
new file mode 100644
index 000000000000..d8991b6f8eb7
--- /dev/null
+++ b/arch/avr32/lib/clear_user.S
@@ -0,0 +1,76 @@
1/*
2 * Copyright 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <asm/page.h>
9#include <asm/thread_info.h>
10#include <asm/asm.h>
11
12 .text
13 .align 1
14 .global clear_user
15 .type clear_user, "function"
16clear_user:
17 branch_if_kernel r8, __clear_user
18 ret_if_privileged r8, r12, r11, r11
19
20 .global __clear_user
21 .type __clear_user, "function"
22__clear_user:
23 mov r9, r12
24 mov r8, 0
25 andl r9, 3, COH
26 brne 5f
27
281: sub r11, 4
29 brlt 2f
30
3110: st.w r12++, r8
32 sub r11, 4
33 brge 10b
34
352: sub r11, -4
36 reteq 0
37
38 /* Unaligned count or address */
39 bld r11, 1
40 brcc 12f
4111: st.h r12++, r8
42 sub r11, 2
43 reteq 0
4412: st.b r12++, r8
45 retal 0
46
47 /* Unaligned address */
485: cp.w r11, 4
49 brlt 2b
50
51 lsl r9, 2
52 add pc, pc, r9
5313: st.b r12++, r8
54 sub r11, 1
5514: st.b r12++, r8
56 sub r11, 1
5715: st.b r12++, r8
58 sub r11, 1
59 rjmp 1b
60
61 .size clear_user, . - clear_user
62 .size __clear_user, . - __clear_user
63
64 .section .fixup, "ax"
65 .align 1
6618: sub r11, -4
6719: retal r11
68
69 .section __ex_table, "a"
70 .align 2
71 .long 10b, 18b
72 .long 11b, 19b
73 .long 12b, 19b
74 .long 13b, 19b
75 .long 14b, 19b
76 .long 15b, 19b
diff --git a/arch/avr32/lib/copy_user.S b/arch/avr32/lib/copy_user.S
new file mode 100644
index 000000000000..ea59c04b07de
--- /dev/null
+++ b/arch/avr32/lib/copy_user.S
@@ -0,0 +1,119 @@
1/*
2 * Copy to/from userspace with optional address space checking.
3 *
4 * Copyright 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <asm/page.h>
11#include <asm/thread_info.h>
12#include <asm/asm.h>
13
14 /*
15 * __kernel_size_t
16 * __copy_user(void *to, const void *from, __kernel_size_t n)
17 *
18 * Returns the number of bytes not copied. Might be off by
19 * max 3 bytes if we get a fault in the main loop.
20 *
21 * The address-space checking functions simply fall through to
22 * the non-checking version.
23 */
24 .text
25 .align 1
26 .global copy_from_user
27 .type copy_from_user, @function
28copy_from_user:
29 branch_if_kernel r8, __copy_user
30 ret_if_privileged r8, r11, r10, r10
31 rjmp __copy_user
32 .size copy_from_user, . - copy_from_user
33
34 .global copy_to_user
35 .type copy_to_user, @function
36copy_to_user:
37 branch_if_kernel r8, __copy_user
38 ret_if_privileged r8, r12, r10, r10
39 .size copy_to_user, . - copy_to_user
40
41 .global __copy_user
42 .type __copy_user, @function
43__copy_user:
44 mov r9, r11
45 andl r9, 3, COH
46 brne 6f
47
48 /* At this point, from is word-aligned */
491: sub r10, 4
50 brlt 3f
51
522:
5310: ld.w r8, r11++
5411: st.w r12++, r8
55 sub r10, 4
56 brge 2b
57
583: sub r10, -4
59 reteq 0
60
61 /*
62 * Handle unaligned count. Need to be careful with r10 here so
63 * that we return the correct value even if we get a fault
64 */
654:
6620: ld.ub r8, r11++
6721: st.b r12++, r8
68 sub r10, 1
69 reteq 0
7022: ld.ub r8, r11++
7123: st.b r12++, r8
72 sub r10, 1
73 reteq 0
7424: ld.ub r8, r11++
7525: st.b r12++, r8
76 retal 0
77
78 /* Handle unaligned from-pointer */
796: cp.w r10, 4
80 brlt 4b
81 rsub r9, r9, 4
82
8330: ld.ub r8, r11++
8431: st.b r12++, r8
85 sub r10, 1
86 sub r9, 1
87 breq 1b
8832: ld.ub r8, r11++
8933: st.b r12++, r8
90 sub r10, 1
91 sub r9, 1
92 breq 1b
9334: ld.ub r8, r11++
9435: st.b r12++, r8
95 sub r10, 1
96 rjmp 1b
97 .size __copy_user, . - __copy_user
98
99 .section .fixup,"ax"
100 .align 1
10119: sub r10, -4
10229: retal r10
103
104 .section __ex_table,"a"
105 .align 2
106 .long 10b, 19b
107 .long 11b, 19b
108 .long 20b, 29b
109 .long 21b, 29b
110 .long 22b, 29b
111 .long 23b, 29b
112 .long 24b, 29b
113 .long 25b, 29b
114 .long 30b, 29b
115 .long 31b, 29b
116 .long 32b, 29b
117 .long 33b, 29b
118 .long 34b, 29b
119 .long 35b, 29b
diff --git a/arch/avr32/lib/csum_partial.S b/arch/avr32/lib/csum_partial.S
new file mode 100644
index 000000000000..6a262b528eb7
--- /dev/null
+++ b/arch/avr32/lib/csum_partial.S
@@ -0,0 +1,47 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 /*
10 * unsigned int csum_partial(const unsigned char *buff,
11 * int len, unsigned int sum)
12 */
13 .text
14 .global csum_partial
15 .type csum_partial,"function"
16 .align 1
17csum_partial:
18 /* checksum complete words, aligned or not */
193: sub r11, 4
20 brlt 5f
214: ld.w r9, r12++
22 add r10, r9
23 acr r10
24 sub r11, 4
25 brge 4b
26
27 /* return if we had a whole number of words */
285: sub r11, -4
29 reteq r10
30
31 /* checksum any remaining bytes at the end */
32 mov r9, 0
33 mov r8, 0
34 cp r11, 2
35 brlt 6f
36 ld.uh r9, r12++
37 sub r11, 2
38 breq 7f
39 lsl r9, 16
406: ld.ub r8, r12++
41 lsl r8, 8
427: or r9, r8
43 add r10, r9
44 acr r10
45
46 retal r10
47 .size csum_partial, . - csum_partial
diff --git a/arch/avr32/lib/csum_partial_copy_generic.S b/arch/avr32/lib/csum_partial_copy_generic.S
new file mode 100644
index 000000000000..a3a0f9b8929c
--- /dev/null
+++ b/arch/avr32/lib/csum_partial_copy_generic.S
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <asm/errno.h>
9#include <asm/asm.h>
10
11 /*
12 * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len
13 * int sum, int *src_err_ptr,
14 * int *dst_err_ptr)
15 *
16 * Copy src to dst while checksumming, otherwise like csum_partial.
17 */
18
19 .macro ld_src size, reg, ptr
209999: ld.\size \reg, \ptr
21 .section __ex_table, "a"
22 .long 9999b, fixup_ld_src
23 .previous
24 .endm
25
26 .macro st_dst size, ptr, reg
279999: st.\size \ptr, \reg
28 .section __ex_table, "a"
29 .long 9999b, fixup_st_dst
30 .previous
31 .endm
32
33 .text
34 .global csum_partial_copy_generic
35 .type csum_partial_copy_generic,"function"
36 .align 1
37csum_partial_copy_generic:
38 pushm r4-r7,lr
39
40 /* The inner loop */
411: sub r10, 4
42 brlt 5f
432: ld_src w, r5, r12++
44 st_dst w, r11++, r5
45 add r9, r5
46 acr r9
47 sub r10, 4
48 brge 2b
49
50 /* return if we had a whole number of words */
515: sub r10, -4
52 brne 7f
53
546: mov r12, r9
55 popm r4-r7,pc
56
57 /* handle additional bytes at the tail */
587: mov r5, 0
59 mov r4, 32
608: ld_src ub, r6, r12++
61 st_dst b, r11++, r6
62 lsl r5, 8
63 sub r4, 8
64 bfins r5, r6, 0, 8
65 sub r10, 1
66 brne 8b
67
68 lsl r5, r5, r4
69 add r9, r5
70 acr r9
71 rjmp 6b
72
73 /* Exception handler */
74 .section .fixup,"ax"
75 .align 1
76fixup_ld_src:
77 mov r9, -EFAULT
78 cp.w r8, 0
79 breq 1f
80 st.w r8[0], r9
81
821: /*
83 * TODO: zero the complete destination - computing the rest
84 * is too much work
85 */
86
87 mov r9, 0
88 rjmp 6b
89
90fixup_st_dst:
91 mov r9, -EFAULT
92 lddsp r8, sp[20]
93 cp.w r8, 0
94 breq 1f
95 st.w r8[0], r9
961: mov r9, 0
97 rjmp 6b
98
99 .previous
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
new file mode 100644
index 000000000000..462c8307b680
--- /dev/null
+++ b/arch/avr32/lib/delay.c
@@ -0,0 +1,55 @@
1/*
2 * Precise Delay Loops for avr32
3 *
4 * Copyright (C) 1993 Linus Torvalds
5 * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
6 * Copyright (C) 2005-2006 Atmel Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/module.h>
15#include <linux/types.h>
16
17#include <asm/delay.h>
18#include <asm/processor.h>
19#include <asm/sysreg.h>
20
21int read_current_timer(unsigned long *timer_value)
22{
23 *timer_value = sysreg_read(COUNT);
24 return 0;
25}
26
27void __delay(unsigned long loops)
28{
29 unsigned bclock, now;
30
31 bclock = sysreg_read(COUNT);
32 do {
33 now = sysreg_read(COUNT);
34 } while ((now - bclock) < loops);
35}
36
37inline void __const_udelay(unsigned long xloops)
38{
39 unsigned long long loops;
40
41 asm("mulu.d %0, %1, %2"
42 : "=r"(loops)
43 : "r"(current_cpu_data.loops_per_jiffy * HZ), "r"(xloops));
44 __delay(loops >> 32);
45}
46
47void __udelay(unsigned long usecs)
48{
49 __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
50}
51
52void __ndelay(unsigned long nsecs)
53{
54 __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
55}
diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S
new file mode 100644
index 000000000000..2b4856f4bf7c
--- /dev/null
+++ b/arch/avr32/lib/findbit.S
@@ -0,0 +1,154 @@
1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/linkage.h>
9
10 .text
11 /*
12 * unsigned long find_first_zero_bit(const unsigned long *addr,
13 * unsigned long size)
14 */
15ENTRY(find_first_zero_bit)
16 cp.w r11, 0
17 reteq r11
18 mov r9, r11
191: ld.w r8, r12[0]
20 com r8
21 brne .L_found
22 sub r12, -4
23 sub r9, 32
24 brgt 1b
25 retal r11
26
27 /*
28 * unsigned long find_next_zero_bit(const unsigned long *addr,
29 * unsigned long size,
30 * unsigned long offset)
31 */
32ENTRY(find_next_zero_bit)
33 lsr r8, r10, 5
34 sub r9, r11, r10
35 retle r11
36
37 lsl r8, 2
38 add r12, r8
39 andl r10, 31, COH
40 breq 1f
41
42 /* offset is not word-aligned. Handle the first (32 - r10) bits */
43 ld.w r8, r12[0]
44 com r8
45 sub r12, -4
46 lsr r8, r8, r10
47 brne .L_found
48
49 /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
50 add r9, r10
51 sub r9, 32
52 retle r11
53
54 /* Main loop. offset must be word-aligned */
551: ld.w r8, r12[0]
56 com r8
57 brne .L_found
58 sub r12, -4
59 sub r9, 32
60 brgt 1b
61 retal r11
62
63 /* Common return path for when a bit is actually found. */
64.L_found:
65 brev r8
66 clz r10, r8
67 rsub r9, r11
68 add r10, r9
69
70 /* XXX: If we don't have to return exactly "size" when the bit
71 is not found, we may drop this "min" thing */
72 min r12, r11, r10
73 retal r12
74
75 /*
76 * unsigned long find_first_bit(const unsigned long *addr,
77 * unsigned long size)
78 */
79ENTRY(find_first_bit)
80 cp.w r11, 0
81 reteq r11
82 mov r9, r11
831: ld.w r8, r12[0]
84 cp.w r8, 0
85 brne .L_found
86 sub r12, -4
87 sub r9, 32
88 brgt 1b
89 retal r11
90
91 /*
92 * unsigned long find_next_bit(const unsigned long *addr,
93 * unsigned long size,
94 * unsigned long offset)
95 */
96ENTRY(find_next_bit)
97 lsr r8, r10, 5
98 sub r9, r11, r10
99 retle r11
100
101 lsl r8, 2
102 add r12, r8
103 andl r10, 31, COH
104 breq 1f
105
106 /* offset is not word-aligned. Handle the first (32 - r10) bits */
107 ld.w r8, r12[0]
108 sub r12, -4
109 lsr r8, r8, r10
110 brne .L_found
111
112 /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
113 add r9, r10
114 sub r9, 32
115 retle r11
116
117 /* Main loop. offset must be word-aligned */
1181: ld.w r8, r12[0]
119 cp.w r8, 0
120 brne .L_found
121 sub r12, -4
122 sub r9, 32
123 brgt 1b
124 retal r11
125
126ENTRY(generic_find_next_zero_le_bit)
127 lsr r8, r10, 5
128 sub r9, r11, r10
129 retle r11
130
131 lsl r8, 2
132 add r12, r8
133 andl r10, 31, COH
134 breq 1f
135
136 /* offset is not word-aligned. Handle the first (32 - r10) bits */
137 ldswp.w r8, r12[0]
138 sub r12, -4
139 lsr r8, r8, r10
140 brne .L_found
141
142 /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
143 add r9, r10
144 sub r9, 32
145 retle r11
146
147 /* Main loop. offset must be word-aligned */
1481: ldswp.w r8, r12[0]
149 cp.w r8, 0
150 brne .L_found
151 sub r12, -4
152 sub r9, 32
153 brgt 1b
154 retal r11
diff --git a/arch/avr32/lib/io-readsl.S b/arch/avr32/lib/io-readsl.S
new file mode 100644
index 000000000000..b103511ed6c4
--- /dev/null
+++ b/arch/avr32/lib/io-readsl.S
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 .global __raw_readsl
10 .type __raw_readsl,@function
11__raw_readsl:
12 cp.w r10, 0
13 reteq r12
14
15 /*
16 * If r11 isn't properly aligned, we might get an exception on
17 * some implementations. But there's not much we can do about it.
18 */
191: ld.w r8, r12[0]
20 sub r10, 1
21 st.w r11++, r8
22 brne 1b
23
24 retal r12
diff --git a/arch/avr32/lib/io-readsw.S b/arch/avr32/lib/io-readsw.S
new file mode 100644
index 000000000000..456be9909027
--- /dev/null
+++ b/arch/avr32/lib/io-readsw.S
@@ -0,0 +1,43 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9.Lnot_word_aligned:
10 /*
11 * Bad alignment will cause a hardware exception, which is as
12 * good as anything. No need for us to check for proper alignment.
13 */
14 ld.uh r8, r12[0]
15 sub r10, 1
16 st.h r11++, r8
17
18 /* fall through */
19
20 .global __raw_readsw
21 .type __raw_readsw,@function
22__raw_readsw:
23 cp.w r10, 0
24 reteq r12
25 mov r9, 3
26 tst r11, r9
27 brne .Lnot_word_aligned
28
29 sub r10, 2
30 brlt 2f
31
321: ldins.h r8:t, r12[0]
33 ldins.h r8:b, r12[0]
34 st.w r11++, r8
35 sub r10, 2
36 brge 1b
37
382: sub r10, -2
39 reteq r12
40
41 ld.uh r8, r12[0]
42 st.h r11++, r8
43 retal r12
diff --git a/arch/avr32/lib/io-writesl.S b/arch/avr32/lib/io-writesl.S
new file mode 100644
index 000000000000..22138b3a16e5
--- /dev/null
+++ b/arch/avr32/lib/io-writesl.S
@@ -0,0 +1,20 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 .global __raw_writesl
10 .type __raw_writesl,@function
11__raw_writesl:
12 cp.w r10, 0
13 reteq r12
14
151: ld.w r8, r11++
16 sub r10, 1
17 st.w r12[0], r8
18 brne 1b
19
20 retal r12
diff --git a/arch/avr32/lib/io-writesw.S b/arch/avr32/lib/io-writesw.S
new file mode 100644
index 000000000000..8c4a53f1c52a
--- /dev/null
+++ b/arch/avr32/lib/io-writesw.S
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9.Lnot_word_aligned:
10 ld.uh r8, r11++
11 sub r10, 1
12 st.h r12[0], r8
13
14 .global __raw_writesw
15 .type __raw_writesw,@function
16__raw_writesw:
17 cp.w r10, 0
18 mov r9, 3
19 reteq r12
20 tst r11, r9
21 brne .Lnot_word_aligned
22
23 sub r10, 2
24 brlt 2f
25
261: ld.w r8, r11++
27 bfextu r9, r8, 16, 16
28 st.h r12[0], r9
29 st.h r12[0], r8
30 sub r10, 2
31 brge 1b
32
332: sub r10, -2
34 reteq r12
35
36 ld.uh r8, r11++
37 st.h r12[0], r8
38 retal r12
diff --git a/arch/avr32/lib/libgcc.h b/arch/avr32/lib/libgcc.h
new file mode 100644
index 000000000000..5a091b5e3618
--- /dev/null
+++ b/arch/avr32/lib/libgcc.h
@@ -0,0 +1,33 @@
1/* Definitions for various functions 'borrowed' from gcc-3.4.3 */
2
3#define BITS_PER_UNIT 8
4
5typedef int QItype __attribute__ ((mode (QI)));
6typedef unsigned int UQItype __attribute__ ((mode (QI)));
7typedef int HItype __attribute__ ((mode (HI)));
8typedef unsigned int UHItype __attribute__ ((mode (HI)));
9typedef int SItype __attribute__ ((mode (SI)));
10typedef unsigned int USItype __attribute__ ((mode (SI)));
11typedef int DItype __attribute__ ((mode (DI)));
12typedef unsigned int UDItype __attribute__ ((mode (DI)));
13typedef float SFtype __attribute__ ((mode (SF)));
14typedef float DFtype __attribute__ ((mode (DF)));
15typedef int word_type __attribute__ ((mode (__word__)));
16
17#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
18#define Wtype SItype
19#define UWtype USItype
20#define HWtype SItype
21#define UHWtype USItype
22#define DWtype DItype
23#define UDWtype UDItype
24#define __NW(a,b) __ ## a ## si ## b
25#define __NDW(a,b) __ ## a ## di ## b
26
27struct DWstruct {Wtype high, low;};
28
29typedef union
30{
31 struct DWstruct s;
32 DWtype ll;
33} DWunion;
diff --git a/arch/avr32/lib/longlong.h b/arch/avr32/lib/longlong.h
new file mode 100644
index 000000000000..cd5e369ac437
--- /dev/null
+++ b/arch/avr32/lib/longlong.h
@@ -0,0 +1,98 @@
1/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
2 Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4
5 This definition file is free software; you can redistribute it
6 and/or modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2, or (at your option) any later version.
9
10 This definition file is distributed in the hope that it will be
11 useful, but WITHOUT ANY WARRANTY; without even the implied
12 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20/* Borrowed from gcc-3.4.3 */
21
22#define __BITS4 (W_TYPE_SIZE / 4)
23#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
24#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
25#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
26
27#define count_leading_zeros(count, x) ((count) = __builtin_clz(x))
28
29#define __udiv_qrnnd_c(q, r, n1, n0, d) \
30 do { \
31 UWtype __d1, __d0, __q1, __q0; \
32 UWtype __r1, __r0, __m; \
33 __d1 = __ll_highpart (d); \
34 __d0 = __ll_lowpart (d); \
35 \
36 __r1 = (n1) % __d1; \
37 __q1 = (n1) / __d1; \
38 __m = (UWtype) __q1 * __d0; \
39 __r1 = __r1 * __ll_B | __ll_highpart (n0); \
40 if (__r1 < __m) \
41 { \
42 __q1--, __r1 += (d); \
43 if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
44 if (__r1 < __m) \
45 __q1--, __r1 += (d); \
46 } \
47 __r1 -= __m; \
48 \
49 __r0 = __r1 % __d1; \
50 __q0 = __r1 / __d1; \
51 __m = (UWtype) __q0 * __d0; \
52 __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
53 if (__r0 < __m) \
54 { \
55 __q0--, __r0 += (d); \
56 if (__r0 >= (d)) \
57 if (__r0 < __m) \
58 __q0--, __r0 += (d); \
59 } \
60 __r0 -= __m; \
61 \
62 (q) = (UWtype) __q1 * __ll_B | __q0; \
63 (r) = __r0; \
64 } while (0)
65
66#define udiv_qrnnd __udiv_qrnnd_c
67
68#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
69 do { \
70 UWtype __x; \
71 __x = (al) - (bl); \
72 (sh) = (ah) - (bh) - (__x > (al)); \
73 (sl) = __x; \
74 } while (0)
75
76#define umul_ppmm(w1, w0, u, v) \
77 do { \
78 UWtype __x0, __x1, __x2, __x3; \
79 UHWtype __ul, __vl, __uh, __vh; \
80 \
81 __ul = __ll_lowpart (u); \
82 __uh = __ll_highpart (u); \
83 __vl = __ll_lowpart (v); \
84 __vh = __ll_highpart (v); \
85 \
86 __x0 = (UWtype) __ul * __vl; \
87 __x1 = (UWtype) __ul * __vh; \
88 __x2 = (UWtype) __uh * __vl; \
89 __x3 = (UWtype) __uh * __vh; \
90 \
91 __x1 += __ll_highpart (__x0);/* this can't give carry */ \
92 __x1 += __x2; /* but this indeed can */ \
93 if (__x1 < __x2) /* did we get it? */ \
94 __x3 += __ll_B; /* yes, add it in the proper pos. */ \
95 \
96 (w1) = __x3 + __ll_highpart (__x1); \
97 (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
98 } while (0)
diff --git a/arch/avr32/lib/memcpy.S b/arch/avr32/lib/memcpy.S
new file mode 100644
index 000000000000..0abb26142b64
--- /dev/null
+++ b/arch/avr32/lib/memcpy.S
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9 /*
10 * void *memcpy(void *to, const void *from, unsigned long n)
11 *
12 * This implementation does word-aligned loads in the main loop,
13 * possibly sacrificing alignment of stores.
14 *
15 * Hopefully, in most cases, both "to" and "from" will be
16 * word-aligned to begin with.
17 */
18 .text
19 .global memcpy
20 .type memcpy, @function
21memcpy:
22 mov r9, r11
23 andl r9, 3, COH
24 brne 1f
25
26 /* At this point, "from" is word-aligned */
272: sub r10, 4
28 mov r9, r12
29 brlt 4f
30
313: ld.w r8, r11++
32 sub r10, 4
33 st.w r12++, r8
34 brge 3b
35
364: neg r10
37 reteq r9
38
39 /* Handle unaligned count */
40 lsl r10, 2
41 add pc, pc, r10
42 ld.ub r8, r11++
43 st.b r12++, r8
44 ld.ub r8, r11++
45 st.b r12++, r8
46 ld.ub r8, r11++
47 st.b r12++, r8
48 retal r9
49
50 /* Handle unaligned "from" pointer */
511: sub r10, 4
52 brlt 4b
53 add r10, r9
54 lsl r9, 2
55 add pc, pc, r9
56 ld.ub r8, r11++
57 st.b r12++, r8
58 ld.ub r8, r11++
59 st.b r12++, r8
60 ld.ub r8, r11++
61 st.b r12++, r8
62 rjmp 2b
diff --git a/arch/avr32/lib/memset.S b/arch/avr32/lib/memset.S
new file mode 100644
index 000000000000..40da32c0480c
--- /dev/null
+++ b/arch/avr32/lib/memset.S
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on linux/arch/arm/lib/memset.S
5 * Copyright (C) 1995-2000 Russell King
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * ASM optimised string functions
12 */
13#include <asm/asm.h>
14
15 /*
16 * r12: void *b
17 * r11: int c
18 * r10: size_t len
19 *
20 * Returns b in r12
21 */
22 .text
23 .global memset
24 .type memset, @function
25 .align 5
26memset:
27 mov r9, r12
28 mov r8, r12
29 or r11, r11, r11 << 8
30 andl r9, 3, COH
31 brne 1f
32
332: or r11, r11, r11 << 16
34 sub r10, 4
35 brlt 5f
36
37 /* Let's do some real work */
384: st.w r8++, r11
39 sub r10, 4
40 brge 4b
41
42 /*
43 * When we get here, we've got less than 4 bytes to set. r10
44 * might be negative.
45 */
465: sub r10, -4
47 reteq r12
48
49 /* Fastpath ends here, exactly 32 bytes from memset */
50
51 /* Handle unaligned count or pointer */
52 bld r10, 1
53 brcc 6f
54 st.b r8++, r11
55 st.b r8++, r11
56 bld r10, 0
57 retcc r12
586: st.b r8++, r11
59 retal r12
60
61 /* Handle unaligned pointer */
621: sub r10, 4
63 brlt 5b
64 add r10, r9
65 lsl r9, 1
66 add pc, r9
67 st.b r8++, r11
68 st.b r8++, r11
69 st.b r8++, r11
70 rjmp 2b
71
72 .size memset, . - memset
diff --git a/arch/avr32/lib/strncpy_from_user.S b/arch/avr32/lib/strncpy_from_user.S
new file mode 100644
index 000000000000..72bd50599ec6
--- /dev/null
+++ b/arch/avr32/lib/strncpy_from_user.S
@@ -0,0 +1,60 @@
1/*
2 * Copy to/from userspace with optional address space checking.
3 *
4 * Copyright 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/errno.h>
11
12#include <asm/page.h>
13#include <asm/thread_info.h>
14#include <asm/asm.h>
15
16 /*
17 * long strncpy_from_user(char *dst, const char *src, long count)
18 *
19 * On success, returns the length of the string, not including
20 * the terminating NUL.
21 *
22 * If the string is longer than count, returns count
23 *
24 * If userspace access fails, returns -EFAULT
25 */
26 .text
27 .align 1
28 .global strncpy_from_user
29 .type strncpy_from_user, "function"
30strncpy_from_user:
31 mov r9, -EFAULT
32 branch_if_kernel r8, __strncpy_from_user
33 ret_if_privileged r8, r11, r10, r9
34
35 .global __strncpy_from_user
36 .type __strncpy_from_user, "function"
37__strncpy_from_user:
38 cp.w r10, 0
39 reteq 0
40
41 mov r9, r10
42
431: ld.ub r8, r11++
44 st.b r12++, r8
45 cp.w r8, 0
46 breq 2f
47 sub r9, 1
48 brne 1b
49
502: sub r10, r9
51 retal r10
52
53 .section .fixup, "ax"
54 .align 1
553: mov r12, -EFAULT
56 retal r12
57
58 .section __ex_table, "a"
59 .align 2
60 .long 1b, 3b
diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S
new file mode 100644
index 000000000000..65ce11afa66a
--- /dev/null
+++ b/arch/avr32/lib/strnlen_user.S
@@ -0,0 +1,67 @@
1/*
2 * Copy to/from userspace with optional address space checking.
3 *
4 * Copyright 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <asm/page.h>
11#include <asm/thread_info.h>
12#include <asm/processor.h>
13#include <asm/asm.h>
14
15 .text
16 .align 1
17 .global strnlen_user
18 .type strnlen_user, "function"
19strnlen_user:
20 branch_if_kernel r8, __strnlen_user
21 sub r8, r11, 1
22 add r8, r12
23 retcs 0
24 brmi adjust_length /* do a closer inspection */
25
26 .global __strnlen_user
27 .type __strnlen_user, "function"
28__strnlen_user:
29 mov r10, r12
30
3110: ld.ub r8, r12++
32 cp.w r8, 0
33 breq 2f
34 sub r11, 1
35 brne 10b
36
37 sub r12, -1
382: sub r12, r10
39 retal r12
40
41
42 .type adjust_length, "function"
43adjust_length:
44 cp.w r12, 0 /* addr must always be < TASK_SIZE */
45 retmi 0
46
47 pushm lr
48 lddpc lr, _task_size
49 sub r11, lr, r12
50 mov r9, r11
51 rcall __strnlen_user
52 cp.w r12, r9
53 brgt 1f
54 popm pc
551: popm pc, r12=0
56
57 .align 2
58_task_size:
59 .long TASK_SIZE
60
61 .section .fixup, "ax"
62 .align 1
6319: retal 0
64
65 .section __ex_table, "a"
66 .align 2
67 .long 10b, 19b
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
new file mode 100644
index 000000000000..f62eb6915510
--- /dev/null
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -0,0 +1,2 @@
1obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o
2obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c
new file mode 100644
index 000000000000..f7cedf5aabea
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/err.h>
11#include <linux/init.h>
12#include <linux/platform_device.h>
13
14#include <asm/io.h>
15
16#include <asm/arch/init.h>
17#include <asm/arch/sm.h>
18
19struct at32_sm system_manager;
20
21static int __init at32_sm_init(void)
22{
23 struct resource *regs;
24 struct at32_sm *sm = &system_manager;
25 int ret = -ENXIO;
26
27 regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
28 if (!regs)
29 goto fail;
30
31 spin_lock_init(&sm->lock);
32 sm->pdev = &at32_sm_device;
33
34 ret = -ENOMEM;
35 sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
36 if (!sm->regs)
37 goto fail;
38
39 return 0;
40
41fail:
42 printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
43 return ret;
44}
45
46void __init setup_platform(void)
47{
48 at32_sm_init();
49 at32_clock_init();
50 at32_portmux_init();
51
52 /* FIXME: This doesn't belong here */
53 at32_setup_serial_console(1);
54}
55
56static int __init pdc_probe(struct platform_device *pdev)
57{
58 struct clk *pclk, *hclk;
59
60 pclk = clk_get(&pdev->dev, "pclk");
61 if (IS_ERR(pclk)) {
62 dev_err(&pdev->dev, "no pclk defined\n");
63 return PTR_ERR(pclk);
64 }
65 hclk = clk_get(&pdev->dev, "hclk");
66 if (IS_ERR(hclk)) {
67 dev_err(&pdev->dev, "no hclk defined\n");
68 clk_put(pclk);
69 return PTR_ERR(hclk);
70 }
71
72 clk_enable(pclk);
73 clk_enable(hclk);
74
75 dev_info(&pdev->dev, "Atmel Peripheral DMA Controller enabled\n");
76 return 0;
77}
78
79static struct platform_driver pdc_driver = {
80 .probe = pdc_probe,
81 .driver = {
82 .name = "pdc",
83 },
84};
85
86static int __init pdc_init(void)
87{
88 return platform_driver_register(&pdc_driver);
89}
90arch_initcall(pdc_init);
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
new file mode 100644
index 000000000000..37982b60398e
--- /dev/null
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -0,0 +1,876 @@
1/*
2 * Copyright (C) 2005-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/clk.h>
9#include <linux/init.h>
10#include <linux/platform_device.h>
11
12#include <asm/io.h>
13
14#include <asm/arch/board.h>
15#include <asm/arch/portmux.h>
16#include <asm/arch/sm.h>
17
18#include "clock.h"
19#include "pio.h"
20#include "sm.h"
21
22#define PBMEM(base) \
23 { \
24 .start = base, \
25 .end = base + 0x3ff, \
26 .flags = IORESOURCE_MEM, \
27 }
28#define IRQ(num) \
29 { \
30 .start = num, \
31 .end = num, \
32 .flags = IORESOURCE_IRQ, \
33 }
34#define NAMED_IRQ(num, _name) \
35 { \
36 .start = num, \
37 .end = num, \
38 .name = _name, \
39 .flags = IORESOURCE_IRQ, \
40 }
41
42#define DEFINE_DEV(_name, _id) \
43static struct platform_device _name##_id##_device = { \
44 .name = #_name, \
45 .id = _id, \
46 .resource = _name##_id##_resource, \
47 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
48}
49#define DEFINE_DEV_DATA(_name, _id) \
50static struct platform_device _name##_id##_device = { \
51 .name = #_name, \
52 .id = _id, \
53 .dev = { \
54 .platform_data = &_name##_id##_data, \
55 }, \
56 .resource = _name##_id##_resource, \
57 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
58}
59
60#define DEV_CLK(_name, devname, bus, _index) \
61static struct clk devname##_##_name = { \
62 .name = #_name, \
63 .dev = &devname##_device.dev, \
64 .parent = &bus##_clk, \
65 .mode = bus##_clk_mode, \
66 .get_rate = bus##_clk_get_rate, \
67 .index = _index, \
68}
69
70enum {
71 PIOA,
72 PIOB,
73 PIOC,
74 PIOD,
75};
76
77enum {
78 FUNC_A,
79 FUNC_B,
80};
81
82unsigned long at32ap7000_osc_rates[3] = {
83 [0] = 32768,
84 /* FIXME: these are ATSTK1002-specific */
85 [1] = 20000000,
86 [2] = 12000000,
87};
88
89static unsigned long osc_get_rate(struct clk *clk)
90{
91 return at32ap7000_osc_rates[clk->index];
92}
93
94static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
95{
96 unsigned long div, mul, rate;
97
98 if (!(control & SM_BIT(PLLEN)))
99 return 0;
100
101 div = SM_BFEXT(PLLDIV, control) + 1;
102 mul = SM_BFEXT(PLLMUL, control) + 1;
103
104 rate = clk->parent->get_rate(clk->parent);
105 rate = (rate + div / 2) / div;
106 rate *= mul;
107
108 return rate;
109}
110
111static unsigned long pll0_get_rate(struct clk *clk)
112{
113 u32 control;
114
115 control = sm_readl(&system_manager, PM_PLL0);
116
117 return pll_get_rate(clk, control);
118}
119
120static unsigned long pll1_get_rate(struct clk *clk)
121{
122 u32 control;
123
124 control = sm_readl(&system_manager, PM_PLL1);
125
126 return pll_get_rate(clk, control);
127}
128
129/*
130 * The AT32AP7000 has five primary clock sources: One 32kHz
131 * oscillator, two crystal oscillators and two PLLs.
132 */
133static struct clk osc32k = {
134 .name = "osc32k",
135 .get_rate = osc_get_rate,
136 .users = 1,
137 .index = 0,
138};
139static struct clk osc0 = {
140 .name = "osc0",
141 .get_rate = osc_get_rate,
142 .users = 1,
143 .index = 1,
144};
145static struct clk osc1 = {
146 .name = "osc1",
147 .get_rate = osc_get_rate,
148 .index = 2,
149};
150static struct clk pll0 = {
151 .name = "pll0",
152 .get_rate = pll0_get_rate,
153 .parent = &osc0,
154};
155static struct clk pll1 = {
156 .name = "pll1",
157 .get_rate = pll1_get_rate,
158 .parent = &osc0,
159};
160
161/*
162 * The main clock can be either osc0 or pll0. The boot loader may
163 * have chosen one for us, so we don't really know which one until we
164 * have a look at the SM.
165 */
166static struct clk *main_clock;
167
168/*
169 * Synchronous clocks are generated from the main clock. The clocks
170 * must satisfy the constraint
171 * fCPU >= fHSB >= fPB
172 * i.e. each clock must not be faster than its parent.
173 */
174static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
175{
176 return main_clock->get_rate(main_clock) >> shift;
177};
178
179static void cpu_clk_mode(struct clk *clk, int enabled)
180{
181 struct at32_sm *sm = &system_manager;
182 unsigned long flags;
183 u32 mask;
184
185 spin_lock_irqsave(&sm->lock, flags);
186 mask = sm_readl(sm, PM_CPU_MASK);
187 if (enabled)
188 mask |= 1 << clk->index;
189 else
190 mask &= ~(1 << clk->index);
191 sm_writel(sm, PM_CPU_MASK, mask);
192 spin_unlock_irqrestore(&sm->lock, flags);
193}
194
195static unsigned long cpu_clk_get_rate(struct clk *clk)
196{
197 unsigned long cksel, shift = 0;
198
199 cksel = sm_readl(&system_manager, PM_CKSEL);
200 if (cksel & SM_BIT(CPUDIV))
201 shift = SM_BFEXT(CPUSEL, cksel) + 1;
202
203 return bus_clk_get_rate(clk, shift);
204}
205
206static void hsb_clk_mode(struct clk *clk, int enabled)
207{
208 struct at32_sm *sm = &system_manager;
209 unsigned long flags;
210 u32 mask;
211
212 spin_lock_irqsave(&sm->lock, flags);
213 mask = sm_readl(sm, PM_HSB_MASK);
214 if (enabled)
215 mask |= 1 << clk->index;
216 else
217 mask &= ~(1 << clk->index);
218 sm_writel(sm, PM_HSB_MASK, mask);
219 spin_unlock_irqrestore(&sm->lock, flags);
220}
221
222static unsigned long hsb_clk_get_rate(struct clk *clk)
223{
224 unsigned long cksel, shift = 0;
225
226 cksel = sm_readl(&system_manager, PM_CKSEL);
227 if (cksel & SM_BIT(HSBDIV))
228 shift = SM_BFEXT(HSBSEL, cksel) + 1;
229
230 return bus_clk_get_rate(clk, shift);
231}
232
233static void pba_clk_mode(struct clk *clk, int enabled)
234{
235 struct at32_sm *sm = &system_manager;
236 unsigned long flags;
237 u32 mask;
238
239 spin_lock_irqsave(&sm->lock, flags);
240 mask = sm_readl(sm, PM_PBA_MASK);
241 if (enabled)
242 mask |= 1 << clk->index;
243 else
244 mask &= ~(1 << clk->index);
245 sm_writel(sm, PM_PBA_MASK, mask);
246 spin_unlock_irqrestore(&sm->lock, flags);
247}
248
249static unsigned long pba_clk_get_rate(struct clk *clk)
250{
251 unsigned long cksel, shift = 0;
252
253 cksel = sm_readl(&system_manager, PM_CKSEL);
254 if (cksel & SM_BIT(PBADIV))
255 shift = SM_BFEXT(PBASEL, cksel) + 1;
256
257 return bus_clk_get_rate(clk, shift);
258}
259
260static void pbb_clk_mode(struct clk *clk, int enabled)
261{
262 struct at32_sm *sm = &system_manager;
263 unsigned long flags;
264 u32 mask;
265
266 spin_lock_irqsave(&sm->lock, flags);
267 mask = sm_readl(sm, PM_PBB_MASK);
268 if (enabled)
269 mask |= 1 << clk->index;
270 else
271 mask &= ~(1 << clk->index);
272 sm_writel(sm, PM_PBB_MASK, mask);
273 spin_unlock_irqrestore(&sm->lock, flags);
274}
275
276static unsigned long pbb_clk_get_rate(struct clk *clk)
277{
278 unsigned long cksel, shift = 0;
279
280 cksel = sm_readl(&system_manager, PM_CKSEL);
281 if (cksel & SM_BIT(PBBDIV))
282 shift = SM_BFEXT(PBBSEL, cksel) + 1;
283
284 return bus_clk_get_rate(clk, shift);
285}
286
287static struct clk cpu_clk = {
288 .name = "cpu",
289 .get_rate = cpu_clk_get_rate,
290 .users = 1,
291};
292static struct clk hsb_clk = {
293 .name = "hsb",
294 .parent = &cpu_clk,
295 .get_rate = hsb_clk_get_rate,
296};
297static struct clk pba_clk = {
298 .name = "pba",
299 .parent = &hsb_clk,
300 .mode = hsb_clk_mode,
301 .get_rate = pba_clk_get_rate,
302 .index = 1,
303};
304static struct clk pbb_clk = {
305 .name = "pbb",
306 .parent = &hsb_clk,
307 .mode = hsb_clk_mode,
308 .get_rate = pbb_clk_get_rate,
309 .users = 1,
310 .index = 2,
311};
312
313/* --------------------------------------------------------------------
314 * Generic Clock operations
315 * -------------------------------------------------------------------- */
316
317static void genclk_mode(struct clk *clk, int enabled)
318{
319 u32 control;
320
321 BUG_ON(clk->index > 7);
322
323 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
324 if (enabled)
325 control |= SM_BIT(CEN);
326 else
327 control &= ~SM_BIT(CEN);
328 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
329}
330
331static unsigned long genclk_get_rate(struct clk *clk)
332{
333 u32 control;
334 unsigned long div = 1;
335
336 BUG_ON(clk->index > 7);
337
338 if (!clk->parent)
339 return 0;
340
341 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
342 if (control & SM_BIT(DIVEN))
343 div = 2 * (SM_BFEXT(DIV, control) + 1);
344
345 return clk->parent->get_rate(clk->parent) / div;
346}
347
348static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
349{
350 u32 control;
351 unsigned long parent_rate, actual_rate, div;
352
353 BUG_ON(clk->index > 7);
354
355 if (!clk->parent)
356 return 0;
357
358 parent_rate = clk->parent->get_rate(clk->parent);
359 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
360
361 if (rate > 3 * parent_rate / 4) {
362 actual_rate = parent_rate;
363 control &= ~SM_BIT(DIVEN);
364 } else {
365 div = (parent_rate + rate) / (2 * rate) - 1;
366 control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
367 actual_rate = parent_rate / (2 * (div + 1));
368 }
369
370 printk("clk %s: new rate %lu (actual rate %lu)\n",
371 clk->name, rate, actual_rate);
372
373 if (apply)
374 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
375 control);
376
377 return actual_rate;
378}
379
380int genclk_set_parent(struct clk *clk, struct clk *parent)
381{
382 u32 control;
383
384 BUG_ON(clk->index > 7);
385
386 printk("clk %s: new parent %s (was %s)\n",
387 clk->name, parent->name,
388 clk->parent ? clk->parent->name : "(null)");
389
390 control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
391
392 if (parent == &osc1 || parent == &pll1)
393 control |= SM_BIT(OSCSEL);
394 else if (parent == &osc0 || parent == &pll0)
395 control &= ~SM_BIT(OSCSEL);
396 else
397 return -EINVAL;
398
399 if (parent == &pll0 || parent == &pll1)
400 control |= SM_BIT(PLLSEL);
401 else
402 control &= ~SM_BIT(PLLSEL);
403
404 sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
405 clk->parent = parent;
406
407 return 0;
408}
409
410/* --------------------------------------------------------------------
411 * System peripherals
412 * -------------------------------------------------------------------- */
413static struct resource sm_resource[] = {
414 PBMEM(0xfff00000),
415 NAMED_IRQ(19, "eim"),
416 NAMED_IRQ(20, "pm"),
417 NAMED_IRQ(21, "rtc"),
418};
419struct platform_device at32_sm_device = {
420 .name = "sm",
421 .id = 0,
422 .resource = sm_resource,
423 .num_resources = ARRAY_SIZE(sm_resource),
424};
425DEV_CLK(pclk, at32_sm, pbb, 0);
426
427static struct resource intc0_resource[] = {
428 PBMEM(0xfff00400),
429};
430struct platform_device at32_intc0_device = {
431 .name = "intc",
432 .id = 0,
433 .resource = intc0_resource,
434 .num_resources = ARRAY_SIZE(intc0_resource),
435};
436DEV_CLK(pclk, at32_intc0, pbb, 1);
437
438static struct clk ebi_clk = {
439 .name = "ebi",
440 .parent = &hsb_clk,
441 .mode = hsb_clk_mode,
442 .get_rate = hsb_clk_get_rate,
443 .users = 1,
444};
445static struct clk hramc_clk = {
446 .name = "hramc",
447 .parent = &hsb_clk,
448 .mode = hsb_clk_mode,
449 .get_rate = hsb_clk_get_rate,
450 .users = 1,
451};
452
453static struct resource smc0_resource[] = {
454 PBMEM(0xfff03400),
455};
456DEFINE_DEV(smc, 0);
457DEV_CLK(pclk, smc0, pbb, 13);
458DEV_CLK(mck, smc0, hsb, 0);
459
460static struct platform_device pdc_device = {
461 .name = "pdc",
462 .id = 0,
463};
464DEV_CLK(hclk, pdc, hsb, 4);
465DEV_CLK(pclk, pdc, pba, 16);
466
467static struct clk pico_clk = {
468 .name = "pico",
469 .parent = &cpu_clk,
470 .mode = cpu_clk_mode,
471 .get_rate = cpu_clk_get_rate,
472 .users = 1,
473};
474
475/* --------------------------------------------------------------------
476 * PIO
477 * -------------------------------------------------------------------- */
478
479static struct resource pio0_resource[] = {
480 PBMEM(0xffe02800),
481 IRQ(13),
482};
483DEFINE_DEV(pio, 0);
484DEV_CLK(mck, pio0, pba, 10);
485
486static struct resource pio1_resource[] = {
487 PBMEM(0xffe02c00),
488 IRQ(14),
489};
490DEFINE_DEV(pio, 1);
491DEV_CLK(mck, pio1, pba, 11);
492
493static struct resource pio2_resource[] = {
494 PBMEM(0xffe03000),
495 IRQ(15),
496};
497DEFINE_DEV(pio, 2);
498DEV_CLK(mck, pio2, pba, 12);
499
500static struct resource pio3_resource[] = {
501 PBMEM(0xffe03400),
502 IRQ(16),
503};
504DEFINE_DEV(pio, 3);
505DEV_CLK(mck, pio3, pba, 13);
506
507void __init at32_add_system_devices(void)
508{
509 system_manager.eim_first_irq = NR_INTERNAL_IRQS;
510
511 platform_device_register(&at32_sm_device);
512 platform_device_register(&at32_intc0_device);
513 platform_device_register(&smc0_device);
514 platform_device_register(&pdc_device);
515
516 platform_device_register(&pio0_device);
517 platform_device_register(&pio1_device);
518 platform_device_register(&pio2_device);
519 platform_device_register(&pio3_device);
520}
521
522/* --------------------------------------------------------------------
523 * USART
524 * -------------------------------------------------------------------- */
525
526static struct resource usart0_resource[] = {
527 PBMEM(0xffe00c00),
528 IRQ(7),
529};
530DEFINE_DEV(usart, 0);
531DEV_CLK(usart, usart0, pba, 4);
532
533static struct resource usart1_resource[] = {
534 PBMEM(0xffe01000),
535 IRQ(7),
536};
537DEFINE_DEV(usart, 1);
538DEV_CLK(usart, usart1, pba, 4);
539
540static struct resource usart2_resource[] = {
541 PBMEM(0xffe01400),
542 IRQ(8),
543};
544DEFINE_DEV(usart, 2);
545DEV_CLK(usart, usart2, pba, 5);
546
547static struct resource usart3_resource[] = {
548 PBMEM(0xffe01800),
549 IRQ(9),
550};
551DEFINE_DEV(usart, 3);
552DEV_CLK(usart, usart3, pba, 6);
553
554static inline void configure_usart0_pins(void)
555{
556 portmux_set_func(PIOA, 8, FUNC_B); /* RXD */
557 portmux_set_func(PIOA, 9, FUNC_B); /* TXD */
558}
559
560static inline void configure_usart1_pins(void)
561{
562 portmux_set_func(PIOA, 17, FUNC_A); /* RXD */
563 portmux_set_func(PIOA, 18, FUNC_A); /* TXD */
564}
565
566static inline void configure_usart2_pins(void)
567{
568 portmux_set_func(PIOB, 26, FUNC_B); /* RXD */
569 portmux_set_func(PIOB, 27, FUNC_B); /* TXD */
570}
571
572static inline void configure_usart3_pins(void)
573{
574 portmux_set_func(PIOB, 18, FUNC_B); /* RXD */
575 portmux_set_func(PIOB, 17, FUNC_B); /* TXD */
576}
577
578static struct platform_device *setup_usart(unsigned int id)
579{
580 struct platform_device *pdev;
581
582 switch (id) {
583 case 0:
584 pdev = &usart0_device;
585 configure_usart0_pins();
586 break;
587 case 1:
588 pdev = &usart1_device;
589 configure_usart1_pins();
590 break;
591 case 2:
592 pdev = &usart2_device;
593 configure_usart2_pins();
594 break;
595 case 3:
596 pdev = &usart3_device;
597 configure_usart3_pins();
598 break;
599 default:
600 pdev = NULL;
601 break;
602 }
603
604 return pdev;
605}
606
607struct platform_device *__init at32_add_device_usart(unsigned int id)
608{
609 struct platform_device *pdev;
610
611 pdev = setup_usart(id);
612 if (pdev)
613 platform_device_register(pdev);
614
615 return pdev;
616}
617
618struct platform_device *at91_default_console_device;
619
620void __init at32_setup_serial_console(unsigned int usart_id)
621{
622 at91_default_console_device = setup_usart(usart_id);
623}
624
625/* --------------------------------------------------------------------
626 * Ethernet
627 * -------------------------------------------------------------------- */
628
629static struct eth_platform_data macb0_data;
630static struct resource macb0_resource[] = {
631 PBMEM(0xfff01800),
632 IRQ(25),
633};
634DEFINE_DEV_DATA(macb, 0);
635DEV_CLK(hclk, macb0, hsb, 8);
636DEV_CLK(pclk, macb0, pbb, 6);
637
638struct platform_device *__init
639at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
640{
641 struct platform_device *pdev;
642
643 switch (id) {
644 case 0:
645 pdev = &macb0_device;
646
647 portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */
648 portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */
649 portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */
650 portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */
651 portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */
652 portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */
653 portmux_set_func(PIOC, 13, FUNC_A); /* RXER */
654 portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */
655 portmux_set_func(PIOC, 16, FUNC_A); /* MDC */
656 portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */
657
658 if (!data->is_rmii) {
659 portmux_set_func(PIOC, 0, FUNC_A); /* COL */
660 portmux_set_func(PIOC, 1, FUNC_A); /* CRS */
661 portmux_set_func(PIOC, 2, FUNC_A); /* TXER */
662 portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */
663 portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */
664 portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */
665 portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */
666 portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */
667 portmux_set_func(PIOC, 18, FUNC_A); /* SPD */
668 }
669 break;
670
671 default:
672 return NULL;
673 }
674
675 memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data));
676 platform_device_register(pdev);
677
678 return pdev;
679}
680
681/* --------------------------------------------------------------------
682 * SPI
683 * -------------------------------------------------------------------- */
684static struct resource spi0_resource[] = {
685 PBMEM(0xffe00000),
686 IRQ(3),
687};
688DEFINE_DEV(spi, 0);
689DEV_CLK(mck, spi0, pba, 0);
690
691struct platform_device *__init at32_add_device_spi(unsigned int id)
692{
693 struct platform_device *pdev;
694
695 switch (id) {
696 case 0:
697 pdev = &spi0_device;
698 portmux_set_func(PIOA, 0, FUNC_A); /* MISO */
699 portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */
700 portmux_set_func(PIOA, 2, FUNC_A); /* SCK */
701 portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */
702 portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */
703 portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */
704 break;
705
706 default:
707 return NULL;
708 }
709
710 platform_device_register(pdev);
711 return pdev;
712}
713
714/* --------------------------------------------------------------------
715 * LCDC
716 * -------------------------------------------------------------------- */
717static struct lcdc_platform_data lcdc0_data;
718static struct resource lcdc0_resource[] = {
719 {
720 .start = 0xff000000,
721 .end = 0xff000fff,
722 .flags = IORESOURCE_MEM,
723 },
724 IRQ(1),
725};
726DEFINE_DEV_DATA(lcdc, 0);
727DEV_CLK(hclk, lcdc0, hsb, 7);
728static struct clk lcdc0_pixclk = {
729 .name = "pixclk",
730 .dev = &lcdc0_device.dev,
731 .mode = genclk_mode,
732 .get_rate = genclk_get_rate,
733 .set_rate = genclk_set_rate,
734 .set_parent = genclk_set_parent,
735 .index = 7,
736};
737
738struct platform_device *__init
739at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
740{
741 struct platform_device *pdev;
742
743 switch (id) {
744 case 0:
745 pdev = &lcdc0_device;
746 portmux_set_func(PIOC, 19, FUNC_A); /* CC */
747 portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */
748 portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */
749 portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */
750 portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */
751 portmux_set_func(PIOC, 24, FUNC_A); /* MODE */
752 portmux_set_func(PIOC, 25, FUNC_A); /* PWR */
753 portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */
754 portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */
755 portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */
756 portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */
757 portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */
758 portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */
759 portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */
760 portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */
761 portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */
762 portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */
763 portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */
764 portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */
765 portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */
766 portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */
767 portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */
768 portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */
769 portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */
770 portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */
771 portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */
772 portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */
773 portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */
774 portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */
775 portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */
776 portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */
777
778 clk_set_parent(&lcdc0_pixclk, &pll0);
779 clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
780 break;
781
782 default:
783 return NULL;
784 }
785
786 memcpy(pdev->dev.platform_data, data,
787 sizeof(struct lcdc_platform_data));
788
789 platform_device_register(pdev);
790 return pdev;
791}
792
793struct clk *at32_clock_list[] = {
794 &osc32k,
795 &osc0,
796 &osc1,
797 &pll0,
798 &pll1,
799 &cpu_clk,
800 &hsb_clk,
801 &pba_clk,
802 &pbb_clk,
803 &at32_sm_pclk,
804 &at32_intc0_pclk,
805 &ebi_clk,
806 &hramc_clk,
807 &smc0_pclk,
808 &smc0_mck,
809 &pdc_hclk,
810 &pdc_pclk,
811 &pico_clk,
812 &pio0_mck,
813 &pio1_mck,
814 &pio2_mck,
815 &pio3_mck,
816 &usart0_usart,
817 &usart1_usart,
818 &usart2_usart,
819 &usart3_usart,
820 &macb0_hclk,
821 &macb0_pclk,
822 &spi0_mck,
823 &lcdc0_hclk,
824 &lcdc0_pixclk,
825};
826unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
827
828void __init at32_portmux_init(void)
829{
830 at32_init_pio(&pio0_device);
831 at32_init_pio(&pio1_device);
832 at32_init_pio(&pio2_device);
833 at32_init_pio(&pio3_device);
834}
835
836void __init at32_clock_init(void)
837{
838 struct at32_sm *sm = &system_manager;
839 u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
840 int i;
841
842 if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
843 main_clock = &pll0;
844 else
845 main_clock = &osc0;
846
847 if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
848 pll0.parent = &osc1;
849 if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
850 pll1.parent = &osc1;
851
852 /*
853 * Turn on all clocks that have at least one user already, and
854 * turn off everything else. We only do this for module
855 * clocks, and even though it isn't particularly pretty to
856 * check the address of the mode function, it should do the
857 * trick...
858 */
859 for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
860 struct clk *clk = at32_clock_list[i];
861
862 if (clk->mode == &cpu_clk_mode)
863 cpu_mask |= 1 << clk->index;
864 else if (clk->mode == &hsb_clk_mode)
865 hsb_mask |= 1 << clk->index;
866 else if (clk->mode == &pba_clk_mode)
867 pba_mask |= 1 << clk->index;
868 else if (clk->mode == &pbb_clk_mode)
869 pbb_mask |= 1 << clk->index;
870 }
871
872 sm_writel(sm, PM_CPU_MASK, cpu_mask);
873 sm_writel(sm, PM_HSB_MASK, hsb_mask);
874 sm_writel(sm, PM_PBA_MASK, pba_mask);
875 sm_writel(sm, PM_PBB_MASK, pbb_mask);
876}
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
new file mode 100644
index 000000000000..3d0d1097389f
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -0,0 +1,148 @@
1/*
2 * Clock management for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c
7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/clk.h>
15#include <linux/err.h>
16#include <linux/device.h>
17#include <linux/string.h>
18
19#include "clock.h"
20
21static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
22
23struct clk *clk_get(struct device *dev, const char *id)
24{
25 int i;
26
27 for (i = 0; i < at32_nr_clocks; i++) {
28 struct clk *clk = at32_clock_list[i];
29
30 if (clk->dev == dev && strcmp(id, clk->name) == 0)
31 return clk;
32 }
33
34 return ERR_PTR(-ENOENT);
35}
36EXPORT_SYMBOL(clk_get);
37
38void clk_put(struct clk *clk)
39{
40 /* clocks are static for now, we can't free them */
41}
42EXPORT_SYMBOL(clk_put);
43
44static void __clk_enable(struct clk *clk)
45{
46 if (clk->parent)
47 __clk_enable(clk->parent);
48 if (clk->users++ == 0 && clk->mode)
49 clk->mode(clk, 1);
50}
51
52int clk_enable(struct clk *clk)
53{
54 unsigned long flags;
55
56 spin_lock_irqsave(&clk_lock, flags);
57 __clk_enable(clk);
58 spin_unlock_irqrestore(&clk_lock, flags);
59
60 return 0;
61}
62EXPORT_SYMBOL(clk_enable);
63
64static void __clk_disable(struct clk *clk)
65{
66 BUG_ON(clk->users == 0);
67
68 if (--clk->users == 0 && clk->mode)
69 clk->mode(clk, 0);
70 if (clk->parent)
71 __clk_disable(clk->parent);
72}
73
74void clk_disable(struct clk *clk)
75{
76 unsigned long flags;
77
78 spin_lock_irqsave(&clk_lock, flags);
79 __clk_disable(clk);
80 spin_unlock_irqrestore(&clk_lock, flags);
81}
82EXPORT_SYMBOL(clk_disable);
83
84unsigned long clk_get_rate(struct clk *clk)
85{
86 unsigned long flags;
87 unsigned long rate;
88
89 spin_lock_irqsave(&clk_lock, flags);
90 rate = clk->get_rate(clk);
91 spin_unlock_irqrestore(&clk_lock, flags);
92
93 return rate;
94}
95EXPORT_SYMBOL(clk_get_rate);
96
97long clk_round_rate(struct clk *clk, unsigned long rate)
98{
99 unsigned long flags, actual_rate;
100
101 if (!clk->set_rate)
102 return -ENOSYS;
103
104 spin_lock_irqsave(&clk_lock, flags);
105 actual_rate = clk->set_rate(clk, rate, 0);
106 spin_unlock_irqrestore(&clk_lock, flags);
107
108 return actual_rate;
109}
110EXPORT_SYMBOL(clk_round_rate);
111
112int clk_set_rate(struct clk *clk, unsigned long rate)
113{
114 unsigned long flags;
115 long ret;
116
117 if (!clk->set_rate)
118 return -ENOSYS;
119
120 spin_lock_irqsave(&clk_lock, flags);
121 ret = clk->set_rate(clk, rate, 1);
122 spin_unlock_irqrestore(&clk_lock, flags);
123
124 return (ret < 0) ? ret : 0;
125}
126EXPORT_SYMBOL(clk_set_rate);
127
128int clk_set_parent(struct clk *clk, struct clk *parent)
129{
130 unsigned long flags;
131 int ret;
132
133 if (!clk->set_parent)
134 return -ENOSYS;
135
136 spin_lock_irqsave(&clk_lock, flags);
137 ret = clk->set_parent(clk, parent);
138 spin_unlock_irqrestore(&clk_lock, flags);
139
140 return ret;
141}
142EXPORT_SYMBOL(clk_set_parent);
143
144struct clk *clk_get_parent(struct clk *clk)
145{
146 return clk->parent;
147}
148EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
new file mode 100644
index 000000000000..f953f044ba4d
--- /dev/null
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -0,0 +1,30 @@
1/*
2 * Clock management for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c
7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/clk.h>
15
16struct clk {
17 const char *name; /* Clock name/function */
18 struct device *dev; /* Device the clock is used by */
19 struct clk *parent; /* Parent clock, if any */
20 void (*mode)(struct clk *clk, int enabled);
21 unsigned long (*get_rate)(struct clk *clk);
22 long (*set_rate)(struct clk *clk, unsigned long rate,
23 int apply);
24 int (*set_parent)(struct clk *clk, struct clk *parent);
25 u16 users; /* Enabled if non-zero */
26 u16 index; /* Sibling index */
27};
28
29extern struct clk *at32_clock_list[];
30extern unsigned int at32_nr_clocks;
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
new file mode 100644
index 000000000000..7da9c5f7a0eb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -0,0 +1,171 @@
1/*
2 * External interrupt handling for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17
18#include <asm/io.h>
19
20#include <asm/arch/sm.h>
21
22#include "sm.h"
23
24static void eim_ack_irq(unsigned int irq)
25{
26 struct at32_sm *sm = get_irq_chip_data(irq);
27 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
28}
29
30static void eim_mask_irq(unsigned int irq)
31{
32 struct at32_sm *sm = get_irq_chip_data(irq);
33 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
34}
35
36static void eim_mask_ack_irq(unsigned int irq)
37{
38 struct at32_sm *sm = get_irq_chip_data(irq);
39 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
40 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
41}
42
43static void eim_unmask_irq(unsigned int irq)
44{
45 struct at32_sm *sm = get_irq_chip_data(irq);
46 sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
47}
48
49static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
50{
51 struct at32_sm *sm = get_irq_chip_data(irq);
52 unsigned int i = irq - sm->eim_first_irq;
53 u32 mode, edge, level;
54 unsigned long flags;
55 int ret = 0;
56
57 flow_type &= IRQ_TYPE_SENSE_MASK;
58
59 spin_lock_irqsave(&sm->lock, flags);
60
61 mode = sm_readl(sm, EIM_MODE);
62 edge = sm_readl(sm, EIM_EDGE);
63 level = sm_readl(sm, EIM_LEVEL);
64
65 switch (flow_type) {
66 case IRQ_TYPE_LEVEL_LOW:
67 mode |= 1 << i;
68 level &= ~(1 << i);
69 break;
70 case IRQ_TYPE_LEVEL_HIGH:
71 mode |= 1 << i;
72 level |= 1 << i;
73 break;
74 case IRQ_TYPE_EDGE_RISING:
75 mode &= ~(1 << i);
76 edge |= 1 << i;
77 break;
78 case IRQ_TYPE_EDGE_FALLING:
79 mode &= ~(1 << i);
80 edge &= ~(1 << i);
81 break;
82 default:
83 ret = -EINVAL;
84 break;
85 }
86
87 sm_writel(sm, EIM_MODE, mode);
88 sm_writel(sm, EIM_EDGE, edge);
89 sm_writel(sm, EIM_LEVEL, level);
90
91 spin_unlock_irqrestore(&sm->lock, flags);
92
93 return ret;
94}
95
96struct irq_chip eim_chip = {
97 .name = "eim",
98 .ack = eim_ack_irq,
99 .mask = eim_mask_irq,
100 .mask_ack = eim_mask_ack_irq,
101 .unmask = eim_unmask_irq,
102 .set_type = eim_set_irq_type,
103};
104
105static void demux_eim_irq(unsigned int irq, struct irq_desc *desc,
106 struct pt_regs *regs)
107{
108 struct at32_sm *sm = desc->handler_data;
109 struct irq_desc *ext_desc;
110 unsigned long status, pending;
111 unsigned int i, ext_irq;
112
113 spin_lock(&sm->lock);
114
115 status = sm_readl(sm, EIM_ISR);
116 pending = status & sm_readl(sm, EIM_IMR);
117
118 while (pending) {
119 i = fls(pending) - 1;
120 pending &= ~(1 << i);
121
122 ext_irq = i + sm->eim_first_irq;
123 ext_desc = irq_desc + ext_irq;
124 ext_desc->handle_irq(ext_irq, ext_desc, regs);
125 }
126
127 spin_unlock(&sm->lock);
128}
129
130static int __init eim_init(void)
131{
132 struct at32_sm *sm = &system_manager;
133 unsigned int i;
134 unsigned int nr_irqs;
135 unsigned int int_irq;
136 u32 pattern;
137
138 /*
139 * The EIM is really the same module as SM, so register
140 * mapping, etc. has been taken care of already.
141 */
142
143 /*
144 * Find out how many interrupt lines that are actually
145 * implemented in hardware.
146 */
147 sm_writel(sm, EIM_IDR, ~0UL);
148 sm_writel(sm, EIM_MODE, ~0UL);
149 pattern = sm_readl(sm, EIM_MODE);
150 nr_irqs = fls(pattern);
151
152 sm->eim_chip = &eim_chip;
153
154 for (i = 0; i < nr_irqs; i++) {
155 set_irq_chip(sm->eim_first_irq + i, &eim_chip);
156 set_irq_chip_data(sm->eim_first_irq + i, sm);
157 }
158
159 int_irq = platform_get_irq_byname(sm->pdev, "eim");
160
161 set_irq_chained_handler(int_irq, demux_eim_irq);
162 set_irq_data(int_irq, sm);
163
164 printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
165 sm->regs, int_irq);
166 printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
167 nr_irqs, sm->eim_first_irq);
168
169 return 0;
170}
171arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
new file mode 100644
index 000000000000..7691721928a7
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -0,0 +1,164 @@
1/*
2 * Static Memory Controller for AT32 chips
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#define DEBUG
11#include <linux/clk.h>
12#include <linux/err.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16
17#include <asm/io.h>
18#include <asm/arch/smc.h>
19
20#include "hsmc.h"
21
22#define NR_CHIP_SELECTS 6
23
24struct hsmc {
25 void __iomem *regs;
26 struct clk *pclk;
27 struct clk *mck;
28};
29
30static struct hsmc *hsmc;
31
32int smc_set_configuration(int cs, const struct smc_config *config)
33{
34 unsigned long mul;
35 unsigned long offset;
36 u32 setup, pulse, cycle, mode;
37
38 if (!hsmc)
39 return -ENODEV;
40 if (cs >= NR_CHIP_SELECTS)
41 return -EINVAL;
42
43 /*
44 * cycles = x / T = x * f
45 * = ((x * 1000000000) * ((f * 65536) / 1000000000)) / 65536
46 * = ((x * 1000000000) * (((f / 10000) * 65536) / 100000)) / 65536
47 */
48 mul = (clk_get_rate(hsmc->mck) / 10000) << 16;
49 mul /= 100000;
50
51#define ns2cyc(x) ((((x) * mul) + 65535) >> 16)
52
53 setup = (HSMC_BF(NWE_SETUP, ns2cyc(config->nwe_setup))
54 | HSMC_BF(NCS_WR_SETUP, ns2cyc(config->ncs_write_setup))
55 | HSMC_BF(NRD_SETUP, ns2cyc(config->nrd_setup))
56 | HSMC_BF(NCS_RD_SETUP, ns2cyc(config->ncs_read_setup)));
57 pulse = (HSMC_BF(NWE_PULSE, ns2cyc(config->nwe_pulse))
58 | HSMC_BF(NCS_WR_PULSE, ns2cyc(config->ncs_write_pulse))
59 | HSMC_BF(NRD_PULSE, ns2cyc(config->nrd_pulse))
60 | HSMC_BF(NCS_RD_PULSE, ns2cyc(config->ncs_read_pulse)));
61 cycle = (HSMC_BF(NWE_CYCLE, ns2cyc(config->write_cycle))
62 | HSMC_BF(NRD_CYCLE, ns2cyc(config->read_cycle)));
63
64 switch (config->bus_width) {
65 case 1:
66 mode = HSMC_BF(DBW, HSMC_DBW_8_BITS);
67 break;
68 case 2:
69 mode = HSMC_BF(DBW, HSMC_DBW_16_BITS);
70 break;
71 case 4:
72 mode = HSMC_BF(DBW, HSMC_DBW_32_BITS);
73 break;
74 default:
75 return -EINVAL;
76 }
77
78 if (config->nrd_controlled)
79 mode |= HSMC_BIT(READ_MODE);
80 if (config->nwe_controlled)
81 mode |= HSMC_BIT(WRITE_MODE);
82 if (config->byte_write)
83 mode |= HSMC_BIT(BAT);
84
85 pr_debug("smc cs%d: setup/%08x pulse/%08x cycle/%08x mode/%08x\n",
86 cs, setup, pulse, cycle, mode);
87
88 offset = cs * 0x10;
89 hsmc_writel(hsmc, SETUP0 + offset, setup);
90 hsmc_writel(hsmc, PULSE0 + offset, pulse);
91 hsmc_writel(hsmc, CYCLE0 + offset, cycle);
92 hsmc_writel(hsmc, MODE0 + offset, mode);
93 hsmc_readl(hsmc, MODE0); /* I/O barrier */
94
95 return 0;
96}
97EXPORT_SYMBOL(smc_set_configuration);
98
99static int hsmc_probe(struct platform_device *pdev)
100{
101 struct resource *regs;
102 struct clk *pclk, *mck;
103 int ret;
104
105 if (hsmc)
106 return -EBUSY;
107
108 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
109 if (!regs)
110 return -ENXIO;
111 pclk = clk_get(&pdev->dev, "pclk");
112 if (IS_ERR(pclk))
113 return PTR_ERR(pclk);
114 mck = clk_get(&pdev->dev, "mck");
115 if (IS_ERR(mck)) {
116 ret = PTR_ERR(mck);
117 goto out_put_pclk;
118 }
119
120 ret = -ENOMEM;
121 hsmc = kzalloc(sizeof(struct hsmc), GFP_KERNEL);
122 if (!hsmc)
123 goto out_put_clocks;
124
125 clk_enable(pclk);
126 clk_enable(mck);
127
128 hsmc->pclk = pclk;
129 hsmc->mck = mck;
130 hsmc->regs = ioremap(regs->start, regs->end - regs->start + 1);
131 if (!hsmc->regs)
132 goto out_disable_clocks;
133
134 dev_info(&pdev->dev, "Atmel Static Memory Controller at 0x%08lx\n",
135 (unsigned long)regs->start);
136
137 platform_set_drvdata(pdev, hsmc);
138
139 return 0;
140
141out_disable_clocks:
142 clk_disable(mck);
143 clk_disable(pclk);
144 kfree(hsmc);
145out_put_clocks:
146 clk_put(mck);
147out_put_pclk:
148 clk_put(pclk);
149 hsmc = NULL;
150 return ret;
151}
152
153static struct platform_driver hsmc_driver = {
154 .probe = hsmc_probe,
155 .driver = {
156 .name = "smc",
157 },
158};
159
160static int __init hsmc_init(void)
161{
162 return platform_driver_register(&hsmc_driver);
163}
164arch_initcall(hsmc_init);
diff --git a/arch/avr32/mach-at32ap/hsmc.h b/arch/avr32/mach-at32ap/hsmc.h
new file mode 100644
index 000000000000..5681276fafdb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hsmc.h
@@ -0,0 +1,127 @@
1/*
2 * Register definitions for Atmel Static Memory Controller (SMC)
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef __ASM_AVR32_HSMC_H__
11#define __ASM_AVR32_HSMC_H__
12
13/* HSMC register offsets */
14#define HSMC_SETUP0 0x0000
15#define HSMC_PULSE0 0x0004
16#define HSMC_CYCLE0 0x0008
17#define HSMC_MODE0 0x000c
18#define HSMC_SETUP1 0x0010
19#define HSMC_PULSE1 0x0014
20#define HSMC_CYCLE1 0x0018
21#define HSMC_MODE1 0x001c
22#define HSMC_SETUP2 0x0020
23#define HSMC_PULSE2 0x0024
24#define HSMC_CYCLE2 0x0028
25#define HSMC_MODE2 0x002c
26#define HSMC_SETUP3 0x0030
27#define HSMC_PULSE3 0x0034
28#define HSMC_CYCLE3 0x0038
29#define HSMC_MODE3 0x003c
30#define HSMC_SETUP4 0x0040
31#define HSMC_PULSE4 0x0044
32#define HSMC_CYCLE4 0x0048
33#define HSMC_MODE4 0x004c
34#define HSMC_SETUP5 0x0050
35#define HSMC_PULSE5 0x0054
36#define HSMC_CYCLE5 0x0058
37#define HSMC_MODE5 0x005c
38
39/* Bitfields in SETUP0 */
40#define HSMC_NWE_SETUP_OFFSET 0
41#define HSMC_NWE_SETUP_SIZE 6
42#define HSMC_NCS_WR_SETUP_OFFSET 8
43#define HSMC_NCS_WR_SETUP_SIZE 6
44#define HSMC_NRD_SETUP_OFFSET 16
45#define HSMC_NRD_SETUP_SIZE 6
46#define HSMC_NCS_RD_SETUP_OFFSET 24
47#define HSMC_NCS_RD_SETUP_SIZE 6
48
49/* Bitfields in PULSE0 */
50#define HSMC_NWE_PULSE_OFFSET 0
51#define HSMC_NWE_PULSE_SIZE 7
52#define HSMC_NCS_WR_PULSE_OFFSET 8
53#define HSMC_NCS_WR_PULSE_SIZE 7
54#define HSMC_NRD_PULSE_OFFSET 16
55#define HSMC_NRD_PULSE_SIZE 7
56#define HSMC_NCS_RD_PULSE_OFFSET 24
57#define HSMC_NCS_RD_PULSE_SIZE 7
58
59/* Bitfields in CYCLE0 */
60#define HSMC_NWE_CYCLE_OFFSET 0
61#define HSMC_NWE_CYCLE_SIZE 9
62#define HSMC_NRD_CYCLE_OFFSET 16
63#define HSMC_NRD_CYCLE_SIZE 9
64
65/* Bitfields in MODE0 */
66#define HSMC_READ_MODE_OFFSET 0
67#define HSMC_READ_MODE_SIZE 1
68#define HSMC_WRITE_MODE_OFFSET 1
69#define HSMC_WRITE_MODE_SIZE 1
70#define HSMC_EXNW_MODE_OFFSET 4
71#define HSMC_EXNW_MODE_SIZE 2
72#define HSMC_BAT_OFFSET 8
73#define HSMC_BAT_SIZE 1
74#define HSMC_DBW_OFFSET 12
75#define HSMC_DBW_SIZE 2
76#define HSMC_TDF_CYCLES_OFFSET 16
77#define HSMC_TDF_CYCLES_SIZE 4
78#define HSMC_TDF_MODE_OFFSET 20
79#define HSMC_TDF_MODE_SIZE 1
80#define HSMC_PMEN_OFFSET 24
81#define HSMC_PMEN_SIZE 1
82#define HSMC_PS_OFFSET 28
83#define HSMC_PS_SIZE 2
84
85/* Constants for READ_MODE */
86#define HSMC_READ_MODE_NCS_CONTROLLED 0
87#define HSMC_READ_MODE_NRD_CONTROLLED 1
88
89/* Constants for WRITE_MODE */
90#define HSMC_WRITE_MODE_NCS_CONTROLLED 0
91#define HSMC_WRITE_MODE_NWE_CONTROLLED 1
92
93/* Constants for EXNW_MODE */
94#define HSMC_EXNW_MODE_DISABLED 0
95#define HSMC_EXNW_MODE_RESERVED 1
96#define HSMC_EXNW_MODE_FROZEN 2
97#define HSMC_EXNW_MODE_READY 3
98
99/* Constants for BAT */
100#define HSMC_BAT_BYTE_SELECT 0
101#define HSMC_BAT_BYTE_WRITE 1
102
103/* Constants for DBW */
104#define HSMC_DBW_8_BITS 0
105#define HSMC_DBW_16_BITS 1
106#define HSMC_DBW_32_BITS 2
107
108/* Bit manipulation macros */
109#define HSMC_BIT(name) \
110 (1 << HSMC_##name##_OFFSET)
111#define HSMC_BF(name,value) \
112 (((value) & ((1 << HSMC_##name##_SIZE) - 1)) \
113 << HSMC_##name##_OFFSET)
114#define HSMC_BFEXT(name,value) \
115 (((value) >> HSMC_##name##_OFFSET) \
116 & ((1 << HSMC_##name##_SIZE) - 1))
117#define HSMC_BFINS(name,value,old) \
118 (((old) & ~(((1 << HSMC_##name##_SIZE) - 1) \
119 << HSMC_##name##_OFFSET)) | HSMC_BF(name,value))
120
121/* Register access macros */
122#define hsmc_readl(port,reg) \
123 readl((port)->regs + HSMC_##reg)
124#define hsmc_writel(port,reg,value) \
125 writel((value), (port)->regs + HSMC_##reg)
126
127#endif /* __ASM_AVR32_HSMC_H__ */
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
new file mode 100644
index 000000000000..74f8c9f2f03d
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/err.h>
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/platform_device.h>
15
16#include <asm/io.h>
17
18#include "intc.h"
19
20struct intc {
21 void __iomem *regs;
22 struct irq_chip chip;
23};
24
25extern struct platform_device at32_intc0_device;
26
27/*
28 * TODO: We may be able to implement mask/unmask by setting IxM flags
29 * in the status register.
30 */
31static void intc_mask_irq(unsigned int irq)
32{
33
34}
35
36static void intc_unmask_irq(unsigned int irq)
37{
38
39}
40
41static struct intc intc0 = {
42 .chip = {
43 .name = "intc",
44 .mask = intc_mask_irq,
45 .unmask = intc_unmask_irq,
46 },
47};
48
49/*
50 * All interrupts go via intc at some point.
51 */
52asmlinkage void do_IRQ(int level, struct pt_regs *regs)
53{
54 struct irq_desc *desc;
55 unsigned int irq;
56 unsigned long status_reg;
57
58 local_irq_disable();
59
60 irq_enter();
61
62 irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
63 desc = irq_desc + irq;
64 desc->handle_irq(irq, desc, regs);
65
66 /*
67 * Clear all interrupt level masks so that we may handle
68 * interrupts during softirq processing. If this is a nested
69 * interrupt, interrupts must stay globally disabled until we
70 * return.
71 */
72 status_reg = sysreg_read(SR);
73 status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M)
74 | SYSREG_BIT(I2M) | SYSREG_BIT(I3M));
75 sysreg_write(SR, status_reg);
76
77 irq_exit();
78}
79
80void __init init_IRQ(void)
81{
82 extern void _evba(void);
83 extern void irq_level0(void);
84 struct resource *regs;
85 struct clk *pclk;
86 unsigned int i;
87 u32 offset, readback;
88
89 regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0);
90 if (!regs) {
91 printk(KERN_EMERG "intc: no mmio resource defined\n");
92 goto fail;
93 }
94 pclk = clk_get(&at32_intc0_device.dev, "pclk");
95 if (IS_ERR(pclk)) {
96 printk(KERN_EMERG "intc: no clock defined\n");
97 goto fail;
98 }
99
100 clk_enable(pclk);
101
102 intc0.regs = ioremap(regs->start, regs->end - regs->start + 1);
103 if (!intc0.regs) {
104 printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n",
105 (unsigned long)regs->start);
106 goto fail;
107 }
108
109 /*
110 * Initialize all interrupts to level 0 (lowest priority). The
111 * priority level may be changed by calling
112 * irq_set_priority().
113 *
114 */
115 offset = (unsigned long)&irq_level0 - (unsigned long)&_evba;
116 for (i = 0; i < NR_INTERNAL_IRQS; i++) {
117 intc_writel(&intc0, INTPR0 + 4 * i, offset);
118 readback = intc_readl(&intc0, INTPR0 + 4 * i);
119 if (readback == offset)
120 set_irq_chip_and_handler(i, &intc0.chip,
121 handle_simple_irq);
122 }
123
124 /* Unmask all interrupt levels */
125 sysreg_write(SR, (sysreg_read(SR)
126 & ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M)));
127
128 return;
129
130fail:
131 panic("Interrupt controller initialization failed!\n");
132}
133
diff --git a/arch/avr32/mach-at32ap/intc.h b/arch/avr32/mach-at32ap/intc.h
new file mode 100644
index 000000000000..d289ca2fff13
--- /dev/null
+++ b/arch/avr32/mach-at32ap/intc.h
@@ -0,0 +1,327 @@
1/*
2 * Automatically generated by gen-header.xsl
3 */
4#ifndef __ASM_AVR32_PERIHP_INTC_H__
5#define __ASM_AVR32_PERIHP_INTC_H__
6
7#define INTC_NUM_INT_GRPS 33
8
9#define INTC_INTPR0 0x0
10# define INTC_INTPR0_INTLEV_OFFSET 30
11# define INTC_INTPR0_INTLEV_SIZE 2
12# define INTC_INTPR0_OFFSET_OFFSET 0
13# define INTC_INTPR0_OFFSET_SIZE 24
14#define INTC_INTREQ0 0x100
15# define INTC_INTREQ0_IREQUEST0_OFFSET 0
16# define INTC_INTREQ0_IREQUEST0_SIZE 1
17# define INTC_INTREQ0_IREQUEST1_OFFSET 1
18# define INTC_INTREQ0_IREQUEST1_SIZE 1
19#define INTC_INTPR1 0x4
20# define INTC_INTPR1_INTLEV_OFFSET 30
21# define INTC_INTPR1_INTLEV_SIZE 2
22# define INTC_INTPR1_OFFSET_OFFSET 0
23# define INTC_INTPR1_OFFSET_SIZE 24
24#define INTC_INTREQ1 0x104
25# define INTC_INTREQ1_IREQUEST32_OFFSET 0
26# define INTC_INTREQ1_IREQUEST32_SIZE 1
27# define INTC_INTREQ1_IREQUEST33_OFFSET 1
28# define INTC_INTREQ1_IREQUEST33_SIZE 1
29# define INTC_INTREQ1_IREQUEST34_OFFSET 2
30# define INTC_INTREQ1_IREQUEST34_SIZE 1
31# define INTC_INTREQ1_IREQUEST35_OFFSET 3
32# define INTC_INTREQ1_IREQUEST35_SIZE 1
33# define INTC_INTREQ1_IREQUEST36_OFFSET 4
34# define INTC_INTREQ1_IREQUEST36_SIZE 1
35# define INTC_INTREQ1_IREQUEST37_OFFSET 5
36# define INTC_INTREQ1_IREQUEST37_SIZE 1
37#define INTC_INTPR2 0x8
38# define INTC_INTPR2_INTLEV_OFFSET 30
39# define INTC_INTPR2_INTLEV_SIZE 2
40# define INTC_INTPR2_OFFSET_OFFSET 0
41# define INTC_INTPR2_OFFSET_SIZE 24
42#define INTC_INTREQ2 0x108
43# define INTC_INTREQ2_IREQUEST64_OFFSET 0
44# define INTC_INTREQ2_IREQUEST64_SIZE 1
45# define INTC_INTREQ2_IREQUEST65_OFFSET 1
46# define INTC_INTREQ2_IREQUEST65_SIZE 1
47# define INTC_INTREQ2_IREQUEST66_OFFSET 2
48# define INTC_INTREQ2_IREQUEST66_SIZE 1
49# define INTC_INTREQ2_IREQUEST67_OFFSET 3
50# define INTC_INTREQ2_IREQUEST67_SIZE 1
51# define INTC_INTREQ2_IREQUEST68_OFFSET 4
52# define INTC_INTREQ2_IREQUEST68_SIZE 1
53#define INTC_INTPR3 0xc
54# define INTC_INTPR3_INTLEV_OFFSET 30
55# define INTC_INTPR3_INTLEV_SIZE 2
56# define INTC_INTPR3_OFFSET_OFFSET 0
57# define INTC_INTPR3_OFFSET_SIZE 24
58#define INTC_INTREQ3 0x10c
59# define INTC_INTREQ3_IREQUEST96_OFFSET 0
60# define INTC_INTREQ3_IREQUEST96_SIZE 1
61#define INTC_INTPR4 0x10
62# define INTC_INTPR4_INTLEV_OFFSET 30
63# define INTC_INTPR4_INTLEV_SIZE 2
64# define INTC_INTPR4_OFFSET_OFFSET 0
65# define INTC_INTPR4_OFFSET_SIZE 24
66#define INTC_INTREQ4 0x110
67# define INTC_INTREQ4_IREQUEST128_OFFSET 0
68# define INTC_INTREQ4_IREQUEST128_SIZE 1
69#define INTC_INTPR5 0x14
70# define INTC_INTPR5_INTLEV_OFFSET 30
71# define INTC_INTPR5_INTLEV_SIZE 2
72# define INTC_INTPR5_OFFSET_OFFSET 0
73# define INTC_INTPR5_OFFSET_SIZE 24
74#define INTC_INTREQ5 0x114
75# define INTC_INTREQ5_IREQUEST160_OFFSET 0
76# define INTC_INTREQ5_IREQUEST160_SIZE 1
77#define INTC_INTPR6 0x18
78# define INTC_INTPR6_INTLEV_OFFSET 30
79# define INTC_INTPR6_INTLEV_SIZE 2
80# define INTC_INTPR6_OFFSET_OFFSET 0
81# define INTC_INTPR6_OFFSET_SIZE 24
82#define INTC_INTREQ6 0x118
83# define INTC_INTREQ6_IREQUEST192_OFFSET 0
84# define INTC_INTREQ6_IREQUEST192_SIZE 1
85#define INTC_INTPR7 0x1c
86# define INTC_INTPR7_INTLEV_OFFSET 30
87# define INTC_INTPR7_INTLEV_SIZE 2
88# define INTC_INTPR7_OFFSET_OFFSET 0
89# define INTC_INTPR7_OFFSET_SIZE 24
90#define INTC_INTREQ7 0x11c
91# define INTC_INTREQ7_IREQUEST224_OFFSET 0
92# define INTC_INTREQ7_IREQUEST224_SIZE 1
93#define INTC_INTPR8 0x20
94# define INTC_INTPR8_INTLEV_OFFSET 30
95# define INTC_INTPR8_INTLEV_SIZE 2
96# define INTC_INTPR8_OFFSET_OFFSET 0
97# define INTC_INTPR8_OFFSET_SIZE 24
98#define INTC_INTREQ8 0x120
99# define INTC_INTREQ8_IREQUEST256_OFFSET 0
100# define INTC_INTREQ8_IREQUEST256_SIZE 1
101#define INTC_INTPR9 0x24
102# define INTC_INTPR9_INTLEV_OFFSET 30
103# define INTC_INTPR9_INTLEV_SIZE 2
104# define INTC_INTPR9_OFFSET_OFFSET 0
105# define INTC_INTPR9_OFFSET_SIZE 24
106#define INTC_INTREQ9 0x124
107# define INTC_INTREQ9_IREQUEST288_OFFSET 0
108# define INTC_INTREQ9_IREQUEST288_SIZE 1
109#define INTC_INTPR10 0x28
110# define INTC_INTPR10_INTLEV_OFFSET 30
111# define INTC_INTPR10_INTLEV_SIZE 2
112# define INTC_INTPR10_OFFSET_OFFSET 0
113# define INTC_INTPR10_OFFSET_SIZE 24
114#define INTC_INTREQ10 0x128
115# define INTC_INTREQ10_IREQUEST320_OFFSET 0
116# define INTC_INTREQ10_IREQUEST320_SIZE 1
117#define INTC_INTPR11 0x2c
118# define INTC_INTPR11_INTLEV_OFFSET 30
119# define INTC_INTPR11_INTLEV_SIZE 2
120# define INTC_INTPR11_OFFSET_OFFSET 0
121# define INTC_INTPR11_OFFSET_SIZE 24
122#define INTC_INTREQ11 0x12c
123# define INTC_INTREQ11_IREQUEST352_OFFSET 0
124# define INTC_INTREQ11_IREQUEST352_SIZE 1
125#define INTC_INTPR12 0x30
126# define INTC_INTPR12_INTLEV_OFFSET 30
127# define INTC_INTPR12_INTLEV_SIZE 2
128# define INTC_INTPR12_OFFSET_OFFSET 0
129# define INTC_INTPR12_OFFSET_SIZE 24
130#define INTC_INTREQ12 0x130
131# define INTC_INTREQ12_IREQUEST384_OFFSET 0
132# define INTC_INTREQ12_IREQUEST384_SIZE 1
133#define INTC_INTPR13 0x34
134# define INTC_INTPR13_INTLEV_OFFSET 30
135# define INTC_INTPR13_INTLEV_SIZE 2
136# define INTC_INTPR13_OFFSET_OFFSET 0
137# define INTC_INTPR13_OFFSET_SIZE 24
138#define INTC_INTREQ13 0x134
139# define INTC_INTREQ13_IREQUEST416_OFFSET 0
140# define INTC_INTREQ13_IREQUEST416_SIZE 1
141#define INTC_INTPR14 0x38
142# define INTC_INTPR14_INTLEV_OFFSET 30
143# define INTC_INTPR14_INTLEV_SIZE 2
144# define INTC_INTPR14_OFFSET_OFFSET 0
145# define INTC_INTPR14_OFFSET_SIZE 24
146#define INTC_INTREQ14 0x138
147# define INTC_INTREQ14_IREQUEST448_OFFSET 0
148# define INTC_INTREQ14_IREQUEST448_SIZE 1
149#define INTC_INTPR15 0x3c
150# define INTC_INTPR15_INTLEV_OFFSET 30
151# define INTC_INTPR15_INTLEV_SIZE 2
152# define INTC_INTPR15_OFFSET_OFFSET 0
153# define INTC_INTPR15_OFFSET_SIZE 24
154#define INTC_INTREQ15 0x13c
155# define INTC_INTREQ15_IREQUEST480_OFFSET 0
156# define INTC_INTREQ15_IREQUEST480_SIZE 1
157#define INTC_INTPR16 0x40
158# define INTC_INTPR16_INTLEV_OFFSET 30
159# define INTC_INTPR16_INTLEV_SIZE 2
160# define INTC_INTPR16_OFFSET_OFFSET 0
161# define INTC_INTPR16_OFFSET_SIZE 24
162#define INTC_INTREQ16 0x140
163# define INTC_INTREQ16_IREQUEST512_OFFSET 0
164# define INTC_INTREQ16_IREQUEST512_SIZE 1
165#define INTC_INTPR17 0x44
166# define INTC_INTPR17_INTLEV_OFFSET 30
167# define INTC_INTPR17_INTLEV_SIZE 2
168# define INTC_INTPR17_OFFSET_OFFSET 0
169# define INTC_INTPR17_OFFSET_SIZE 24
170#define INTC_INTREQ17 0x144
171# define INTC_INTREQ17_IREQUEST544_OFFSET 0
172# define INTC_INTREQ17_IREQUEST544_SIZE 1
173#define INTC_INTPR18 0x48
174# define INTC_INTPR18_INTLEV_OFFSET 30
175# define INTC_INTPR18_INTLEV_SIZE 2
176# define INTC_INTPR18_OFFSET_OFFSET 0
177# define INTC_INTPR18_OFFSET_SIZE 24
178#define INTC_INTREQ18 0x148
179# define INTC_INTREQ18_IREQUEST576_OFFSET 0
180# define INTC_INTREQ18_IREQUEST576_SIZE 1
181#define INTC_INTPR19 0x4c
182# define INTC_INTPR19_INTLEV_OFFSET 30
183# define INTC_INTPR19_INTLEV_SIZE 2
184# define INTC_INTPR19_OFFSET_OFFSET 0
185# define INTC_INTPR19_OFFSET_SIZE 24
186#define INTC_INTREQ19 0x14c
187# define INTC_INTREQ19_IREQUEST608_OFFSET 0
188# define INTC_INTREQ19_IREQUEST608_SIZE 1
189# define INTC_INTREQ19_IREQUEST609_OFFSET 1
190# define INTC_INTREQ19_IREQUEST609_SIZE 1
191# define INTC_INTREQ19_IREQUEST610_OFFSET 2
192# define INTC_INTREQ19_IREQUEST610_SIZE 1
193# define INTC_INTREQ19_IREQUEST611_OFFSET 3
194# define INTC_INTREQ19_IREQUEST611_SIZE 1
195#define INTC_INTPR20 0x50
196# define INTC_INTPR20_INTLEV_OFFSET 30
197# define INTC_INTPR20_INTLEV_SIZE 2
198# define INTC_INTPR20_OFFSET_OFFSET 0
199# define INTC_INTPR20_OFFSET_SIZE 24
200#define INTC_INTREQ20 0x150
201# define INTC_INTREQ20_IREQUEST640_OFFSET 0
202# define INTC_INTREQ20_IREQUEST640_SIZE 1
203#define INTC_INTPR21 0x54
204# define INTC_INTPR21_INTLEV_OFFSET 30
205# define INTC_INTPR21_INTLEV_SIZE 2
206# define INTC_INTPR21_OFFSET_OFFSET 0
207# define INTC_INTPR21_OFFSET_SIZE 24
208#define INTC_INTREQ21 0x154
209# define INTC_INTREQ21_IREQUEST672_OFFSET 0
210# define INTC_INTREQ21_IREQUEST672_SIZE 1
211#define INTC_INTPR22 0x58
212# define INTC_INTPR22_INTLEV_OFFSET 30
213# define INTC_INTPR22_INTLEV_SIZE 2
214# define INTC_INTPR22_OFFSET_OFFSET 0
215# define INTC_INTPR22_OFFSET_SIZE 24
216#define INTC_INTREQ22 0x158
217# define INTC_INTREQ22_IREQUEST704_OFFSET 0
218# define INTC_INTREQ22_IREQUEST704_SIZE 1
219# define INTC_INTREQ22_IREQUEST705_OFFSET 1
220# define INTC_INTREQ22_IREQUEST705_SIZE 1
221# define INTC_INTREQ22_IREQUEST706_OFFSET 2
222# define INTC_INTREQ22_IREQUEST706_SIZE 1
223#define INTC_INTPR23 0x5c
224# define INTC_INTPR23_INTLEV_OFFSET 30
225# define INTC_INTPR23_INTLEV_SIZE 2
226# define INTC_INTPR23_OFFSET_OFFSET 0
227# define INTC_INTPR23_OFFSET_SIZE 24
228#define INTC_INTREQ23 0x15c
229# define INTC_INTREQ23_IREQUEST736_OFFSET 0
230# define INTC_INTREQ23_IREQUEST736_SIZE 1
231# define INTC_INTREQ23_IREQUEST737_OFFSET 1
232# define INTC_INTREQ23_IREQUEST737_SIZE 1
233# define INTC_INTREQ23_IREQUEST738_OFFSET 2
234# define INTC_INTREQ23_IREQUEST738_SIZE 1
235#define INTC_INTPR24 0x60
236# define INTC_INTPR24_INTLEV_OFFSET 30
237# define INTC_INTPR24_INTLEV_SIZE 2
238# define INTC_INTPR24_OFFSET_OFFSET 0
239# define INTC_INTPR24_OFFSET_SIZE 24
240#define INTC_INTREQ24 0x160
241# define INTC_INTREQ24_IREQUEST768_OFFSET 0
242# define INTC_INTREQ24_IREQUEST768_SIZE 1
243#define INTC_INTPR25 0x64
244# define INTC_INTPR25_INTLEV_OFFSET 30
245# define INTC_INTPR25_INTLEV_SIZE 2
246# define INTC_INTPR25_OFFSET_OFFSET 0
247# define INTC_INTPR25_OFFSET_SIZE 24
248#define INTC_INTREQ25 0x164
249# define INTC_INTREQ25_IREQUEST800_OFFSET 0
250# define INTC_INTREQ25_IREQUEST800_SIZE 1
251#define INTC_INTPR26 0x68
252# define INTC_INTPR26_INTLEV_OFFSET 30
253# define INTC_INTPR26_INTLEV_SIZE 2
254# define INTC_INTPR26_OFFSET_OFFSET 0
255# define INTC_INTPR26_OFFSET_SIZE 24
256#define INTC_INTREQ26 0x168
257# define INTC_INTREQ26_IREQUEST832_OFFSET 0
258# define INTC_INTREQ26_IREQUEST832_SIZE 1
259#define INTC_INTPR27 0x6c
260# define INTC_INTPR27_INTLEV_OFFSET 30
261# define INTC_INTPR27_INTLEV_SIZE 2
262# define INTC_INTPR27_OFFSET_OFFSET 0
263# define INTC_INTPR27_OFFSET_SIZE 24
264#define INTC_INTREQ27 0x16c
265# define INTC_INTREQ27_IREQUEST864_OFFSET 0
266# define INTC_INTREQ27_IREQUEST864_SIZE 1
267#define INTC_INTPR28 0x70
268# define INTC_INTPR28_INTLEV_OFFSET 30
269# define INTC_INTPR28_INTLEV_SIZE 2
270# define INTC_INTPR28_OFFSET_OFFSET 0
271# define INTC_INTPR28_OFFSET_SIZE 24
272#define INTC_INTREQ28 0x170
273# define INTC_INTREQ28_IREQUEST896_OFFSET 0
274# define INTC_INTREQ28_IREQUEST896_SIZE 1
275#define INTC_INTPR29 0x74
276# define INTC_INTPR29_INTLEV_OFFSET 30
277# define INTC_INTPR29_INTLEV_SIZE 2
278# define INTC_INTPR29_OFFSET_OFFSET 0
279# define INTC_INTPR29_OFFSET_SIZE 24
280#define INTC_INTREQ29 0x174
281# define INTC_INTREQ29_IREQUEST928_OFFSET 0
282# define INTC_INTREQ29_IREQUEST928_SIZE 1
283#define INTC_INTPR30 0x78
284# define INTC_INTPR30_INTLEV_OFFSET 30
285# define INTC_INTPR30_INTLEV_SIZE 2
286# define INTC_INTPR30_OFFSET_OFFSET 0
287# define INTC_INTPR30_OFFSET_SIZE 24
288#define INTC_INTREQ30 0x178
289# define INTC_INTREQ30_IREQUEST960_OFFSET 0
290# define INTC_INTREQ30_IREQUEST960_SIZE 1
291#define INTC_INTPR31 0x7c
292# define INTC_INTPR31_INTLEV_OFFSET 30
293# define INTC_INTPR31_INTLEV_SIZE 2
294# define INTC_INTPR31_OFFSET_OFFSET 0
295# define INTC_INTPR31_OFFSET_SIZE 24
296#define INTC_INTREQ31 0x17c
297# define INTC_INTREQ31_IREQUEST992_OFFSET 0
298# define INTC_INTREQ31_IREQUEST992_SIZE 1
299#define INTC_INTPR32 0x80
300# define INTC_INTPR32_INTLEV_OFFSET 30
301# define INTC_INTPR32_INTLEV_SIZE 2
302# define INTC_INTPR32_OFFSET_OFFSET 0
303# define INTC_INTPR32_OFFSET_SIZE 24
304#define INTC_INTREQ32 0x180
305# define INTC_INTREQ32_IREQUEST1024_OFFSET 0
306# define INTC_INTREQ32_IREQUEST1024_SIZE 1
307#define INTC_INTCAUSE0 0x20c
308# define INTC_INTCAUSE0_CAUSEGRP_OFFSET 0
309# define INTC_INTCAUSE0_CAUSEGRP_SIZE 6
310#define INTC_INTCAUSE1 0x208
311# define INTC_INTCAUSE1_CAUSEGRP_OFFSET 0
312# define INTC_INTCAUSE1_CAUSEGRP_SIZE 6
313#define INTC_INTCAUSE2 0x204
314# define INTC_INTCAUSE2_CAUSEGRP_OFFSET 0
315# define INTC_INTCAUSE2_CAUSEGRP_SIZE 6
316#define INTC_INTCAUSE3 0x200
317# define INTC_INTCAUSE3_CAUSEGRP_OFFSET 0
318# define INTC_INTCAUSE3_CAUSEGRP_SIZE 6
319
320#define INTC_BIT(name) (1 << INTC_##name##_OFFSET)
321#define INTC_MKBF(name, value) (((value) & ((1 << INTC_##name##_SIZE) - 1)) << INTC_##name##_OFFSET)
322#define INTC_GETBF(name, value) (((value) >> INTC_##name##_OFFSET) & ((1 << INTC_##name##_SIZE) - 1))
323
324#define intc_readl(port,reg) readl((port)->regs + INTC_##reg)
325#define intc_writel(port,reg,value) writel((value), (port)->regs + INTC_##reg)
326
327#endif /* __ASM_AVR32_PERIHP_INTC_H__ */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
new file mode 100644
index 000000000000..d3aabfca8598
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -0,0 +1,118 @@
1/*
2 * Atmel PIO2 Port Multiplexer support
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/debugfs.h>
13#include <linux/fs.h>
14#include <linux/platform_device.h>
15
16#include <asm/io.h>
17
18#include <asm/arch/portmux.h>
19
20#include "pio.h"
21
22#define MAX_NR_PIO_DEVICES 8
23
24struct pio_device {
25 void __iomem *regs;
26 const struct platform_device *pdev;
27 struct clk *clk;
28 u32 alloc_mask;
29 char name[32];
30};
31
32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
33
34void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
35 unsigned int function_id)
36{
37 struct pio_device *pio;
38 u32 mask = 1 << pin_id;
39
40 BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
41
42 pio = &pio_dev[portmux_id];
43
44 if (function_id)
45 pio_writel(pio, BSR, mask);
46 else
47 pio_writel(pio, ASR, mask);
48 pio_writel(pio, PDR, mask);
49}
50
51static int __init pio_probe(struct platform_device *pdev)
52{
53 struct pio_device *pio = NULL;
54
55 BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES);
56 pio = &pio_dev[pdev->id];
57 BUG_ON(!pio->regs);
58
59 /* TODO: Interrupts */
60
61 platform_set_drvdata(pdev, pio);
62
63 printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n",
64 pio->name, pio->regs, platform_get_irq(pdev, 0));
65
66 return 0;
67}
68
69static struct platform_driver pio_driver = {
70 .probe = pio_probe,
71 .driver = {
72 .name = "pio",
73 },
74};
75
76static int __init pio_init(void)
77{
78 return platform_driver_register(&pio_driver);
79}
80subsys_initcall(pio_init);
81
82void __init at32_init_pio(struct platform_device *pdev)
83{
84 struct resource *regs;
85 struct pio_device *pio;
86
87 if (pdev->id > MAX_NR_PIO_DEVICES) {
88 dev_err(&pdev->dev, "only %d PIO devices supported\n",
89 MAX_NR_PIO_DEVICES);
90 return;
91 }
92
93 pio = &pio_dev[pdev->id];
94 snprintf(pio->name, sizeof(pio->name), "pio%d", pdev->id);
95
96 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
97 if (!regs) {
98 dev_err(&pdev->dev, "no mmio resource defined\n");
99 return;
100 }
101
102 pio->clk = clk_get(&pdev->dev, "mck");
103 if (IS_ERR(pio->clk))
104 /*
105 * This is a fatal error, but if we continue we might
106 * be so lucky that we manage to initialize the
107 * console and display this message...
108 */
109 dev_err(&pdev->dev, "no mck clock defined\n");
110 else
111 clk_enable(pio->clk);
112
113 pio->pdev = pdev;
114 pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
115
116 pio_writel(pio, ODR, ~0UL);
117 pio_writel(pio, PER, ~0UL);
118}
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
new file mode 100644
index 000000000000..cfea12351599
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -0,0 +1,178 @@
1/*
2 * Atmel PIO2 Port Multiplexer support
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef __ARCH_AVR32_AT32AP_PIO_H__
11#define __ARCH_AVR32_AT32AP_PIO_H__
12
13/* PIO register offsets */
14#define PIO_PER 0x0000
15#define PIO_PDR 0x0004
16#define PIO_PSR 0x0008
17#define PIO_OER 0x0010
18#define PIO_ODR 0x0014
19#define PIO_OSR 0x0018
20#define PIO_IFER 0x0020
21#define PIO_IFDR 0x0024
22#define PIO_ISFR 0x0028
23#define PIO_SODR 0x0030
24#define PIO_CODR 0x0034
25#define PIO_ODSR 0x0038
26#define PIO_PDSR 0x003c
27#define PIO_IER 0x0040
28#define PIO_IDR 0x0044
29#define PIO_IMR 0x0048
30#define PIO_ISR 0x004c
31#define PIO_MDER 0x0050
32#define PIO_MDDR 0x0054
33#define PIO_MDSR 0x0058
34#define PIO_PUDR 0x0060
35#define PIO_PUER 0x0064
36#define PIO_PUSR 0x0068
37#define PIO_ASR 0x0070
38#define PIO_BSR 0x0074
39#define PIO_ABSR 0x0078
40#define PIO_OWER 0x00a0
41#define PIO_OWDR 0x00a4
42#define PIO_OWSR 0x00a8
43
44/* Bitfields in PER */
45
46/* Bitfields in PDR */
47
48/* Bitfields in PSR */
49
50/* Bitfields in OER */
51
52/* Bitfields in ODR */
53
54/* Bitfields in OSR */
55
56/* Bitfields in IFER */
57
58/* Bitfields in IFDR */
59
60/* Bitfields in ISFR */
61
62/* Bitfields in SODR */
63
64/* Bitfields in CODR */
65
66/* Bitfields in ODSR */
67
68/* Bitfields in PDSR */
69
70/* Bitfields in IER */
71
72/* Bitfields in IDR */
73
74/* Bitfields in IMR */
75
76/* Bitfields in ISR */
77
78/* Bitfields in MDER */
79
80/* Bitfields in MDDR */
81
82/* Bitfields in MDSR */
83
84/* Bitfields in PUDR */
85
86/* Bitfields in PUER */
87
88/* Bitfields in PUSR */
89
90/* Bitfields in ASR */
91
92/* Bitfields in BSR */
93
94/* Bitfields in ABSR */
95#define PIO_P0_OFFSET 0
96#define PIO_P0_SIZE 1
97#define PIO_P1_OFFSET 1
98#define PIO_P1_SIZE 1
99#define PIO_P2_OFFSET 2
100#define PIO_P2_SIZE 1
101#define PIO_P3_OFFSET 3
102#define PIO_P3_SIZE 1
103#define PIO_P4_OFFSET 4
104#define PIO_P4_SIZE 1
105#define PIO_P5_OFFSET 5
106#define PIO_P5_SIZE 1
107#define PIO_P6_OFFSET 6
108#define PIO_P6_SIZE 1
109#define PIO_P7_OFFSET 7
110#define PIO_P7_SIZE 1
111#define PIO_P8_OFFSET 8
112#define PIO_P8_SIZE 1
113#define PIO_P9_OFFSET 9
114#define PIO_P9_SIZE 1
115#define PIO_P10_OFFSET 10
116#define PIO_P10_SIZE 1
117#define PIO_P11_OFFSET 11
118#define PIO_P11_SIZE 1
119#define PIO_P12_OFFSET 12
120#define PIO_P12_SIZE 1
121#define PIO_P13_OFFSET 13
122#define PIO_P13_SIZE 1
123#define PIO_P14_OFFSET 14
124#define PIO_P14_SIZE 1
125#define PIO_P15_OFFSET 15
126#define PIO_P15_SIZE 1
127#define PIO_P16_OFFSET 16
128#define PIO_P16_SIZE 1
129#define PIO_P17_OFFSET 17
130#define PIO_P17_SIZE 1
131#define PIO_P18_OFFSET 18
132#define PIO_P18_SIZE 1
133#define PIO_P19_OFFSET 19
134#define PIO_P19_SIZE 1
135#define PIO_P20_OFFSET 20
136#define PIO_P20_SIZE 1
137#define PIO_P21_OFFSET 21
138#define PIO_P21_SIZE 1
139#define PIO_P22_OFFSET 22
140#define PIO_P22_SIZE 1
141#define PIO_P23_OFFSET 23
142#define PIO_P23_SIZE 1
143#define PIO_P24_OFFSET 24
144#define PIO_P24_SIZE 1
145#define PIO_P25_OFFSET 25
146#define PIO_P25_SIZE 1
147#define PIO_P26_OFFSET 26
148#define PIO_P26_SIZE 1
149#define PIO_P27_OFFSET 27
150#define PIO_P27_SIZE 1
151#define PIO_P28_OFFSET 28
152#define PIO_P28_SIZE 1
153#define PIO_P29_OFFSET 29
154#define PIO_P29_SIZE 1
155#define PIO_P30_OFFSET 30
156#define PIO_P30_SIZE 1
157#define PIO_P31_OFFSET 31
158#define PIO_P31_SIZE 1
159
160/* Bitfields in OWER */
161
162/* Bitfields in OWDR */
163
164/* Bitfields in OWSR */
165
166/* Bit manipulation macros */
167#define PIO_BIT(name) (1 << PIO_##name##_OFFSET)
168#define PIO_BF(name,value) (((value) & ((1 << PIO_##name##_SIZE) - 1)) << PIO_##name##_OFFSET)
169#define PIO_BFEXT(name,value) (((value) >> PIO_##name##_OFFSET) & ((1 << PIO_##name##_SIZE) - 1))
170#define PIO_BFINS(name,value,old) (((old) & ~(((1 << PIO_##name##_SIZE) - 1) << PIO_##name##_OFFSET)) | PIO_BF(name,value))
171
172/* Register access macros */
173#define pio_readl(port,reg) readl((port)->regs + PIO_##reg)
174#define pio_writel(port,reg,value) writel((value), (port)->regs + PIO_##reg)
175
176void at32_init_pio(struct platform_device *pdev);
177
178#endif /* __ARCH_AVR32_AT32AP_PIO_H__ */
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
new file mode 100644
index 000000000000..03306eb0345e
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.c
@@ -0,0 +1,289 @@
1/*
2 * System Manager driver for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17#include <linux/spinlock.h>
18
19#include <asm/intc.h>
20#include <asm/io.h>
21#include <asm/irq.h>
22
23#include <asm/arch/sm.h>
24
25#include "sm.h"
26
27#define SM_EIM_IRQ_RESOURCE 1
28#define SM_PM_IRQ_RESOURCE 2
29#define SM_RTC_IRQ_RESOURCE 3
30
31#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
32
33struct at32_sm system_manager;
34
35int __init at32_sm_init(void)
36{
37 struct resource *regs;
38 struct at32_sm *sm = &system_manager;
39 int ret = -ENXIO;
40
41 regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
42 if (!regs)
43 goto fail;
44
45 spin_lock_init(&sm->lock);
46 sm->pdev = &at32_sm_device;
47
48 ret = -ENOMEM;
49 sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
50 if (!sm->regs)
51 goto fail;
52
53 return 0;
54
55fail:
56 printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
57 return ret;
58}
59
60/*
61 * External Interrupt Module (EIM).
62 *
63 * EIM gets level- or edge-triggered interrupts of either polarity
64 * from the outside and converts it to active-high level-triggered
65 * interrupts that the internal interrupt controller can handle. EIM
66 * also provides masking/unmasking of interrupts, as well as
67 * acknowledging of edge-triggered interrupts.
68 */
69
70static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
71 struct pt_regs *regs)
72{
73 printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
74 disable_irq(irq);
75 return IRQ_NONE;
76}
77
78static struct irqaction eim_spurious_action = {
79 .handler = spurious_eim_interrupt,
80};
81
82static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
83{
84 struct irq_controller * irqc = dev_id;
85 struct at32_sm *sm = to_eim(irqc);
86 unsigned long pending;
87
88 /*
89 * No need to disable interrupts globally. The interrupt
90 * level relevant to this group must be masked all the time,
91 * so we know that this particular EIM instance will not be
92 * re-entered.
93 */
94 spin_lock(&sm->lock);
95
96 pending = intc_get_pending(sm->irqc.irq_group);
97 if (unlikely(!pending)) {
98 printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
99 sm->irqc.irq_group);
100 goto unlock;
101 }
102
103 do {
104 struct irqaction *action;
105 unsigned int i;
106
107 i = fls(pending) - 1;
108 pending &= ~(1 << i);
109 action = sm->action[i];
110
111 /* Acknowledge the interrupt */
112 sm_writel(sm, EIM_ICR, 1 << i);
113
114 spin_unlock(&sm->lock);
115
116 if (action->flags & SA_INTERRUPT)
117 local_irq_disable();
118 action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
119 local_irq_enable();
120 spin_lock(&sm->lock);
121 if (action->flags & SA_SAMPLE_RANDOM)
122 add_interrupt_randomness(sm->irqc.first_irq + i);
123 } while (pending);
124
125unlock:
126 spin_unlock(&sm->lock);
127 return IRQ_HANDLED;
128}
129
130static void eim_mask(struct irq_controller *irqc, unsigned int irq)
131{
132 struct at32_sm *sm = to_eim(irqc);
133 unsigned int i;
134
135 i = irq - sm->irqc.first_irq;
136 sm_writel(sm, EIM_IDR, 1 << i);
137}
138
139static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
140{
141 struct at32_sm *sm = to_eim(irqc);
142 unsigned int i;
143
144 i = irq - sm->irqc.first_irq;
145 sm_writel(sm, EIM_IER, 1 << i);
146}
147
148static int eim_setup(struct irq_controller *irqc, unsigned int irq,
149 struct irqaction *action)
150{
151 struct at32_sm *sm = to_eim(irqc);
152 sm->action[irq - sm->irqc.first_irq] = action;
153 /* Acknowledge earlier interrupts */
154 sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
155 eim_unmask(irqc, irq);
156 return 0;
157}
158
159static void eim_free(struct irq_controller *irqc, unsigned int irq,
160 void *dev)
161{
162 struct at32_sm *sm = to_eim(irqc);
163 eim_mask(irqc, irq);
164 sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
165}
166
167static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
168 unsigned int type)
169{
170 struct at32_sm *sm = to_eim(irqc);
171 unsigned long flags;
172 u32 value, pattern;
173
174 spin_lock_irqsave(&sm->lock, flags);
175
176 pattern = 1 << (irq - sm->irqc.first_irq);
177
178 value = sm_readl(sm, EIM_MODE);
179 if (type & IRQ_TYPE_LEVEL)
180 value |= pattern;
181 else
182 value &= ~pattern;
183 sm_writel(sm, EIM_MODE, value);
184 value = sm_readl(sm, EIM_EDGE);
185 if (type & IRQ_EDGE_RISING)
186 value |= pattern;
187 else
188 value &= ~pattern;
189 sm_writel(sm, EIM_EDGE, value);
190 value = sm_readl(sm, EIM_LEVEL);
191 if (type & IRQ_LEVEL_HIGH)
192 value |= pattern;
193 else
194 value &= ~pattern;
195 sm_writel(sm, EIM_LEVEL, value);
196
197 spin_unlock_irqrestore(&sm->lock, flags);
198
199 return 0;
200}
201
202static unsigned int eim_get_type(struct irq_controller *irqc,
203 unsigned int irq)
204{
205 struct at32_sm *sm = to_eim(irqc);
206 unsigned long flags;
207 unsigned int type = 0;
208 u32 mode, edge, level, pattern;
209
210 pattern = 1 << (irq - sm->irqc.first_irq);
211
212 spin_lock_irqsave(&sm->lock, flags);
213 mode = sm_readl(sm, EIM_MODE);
214 edge = sm_readl(sm, EIM_EDGE);
215 level = sm_readl(sm, EIM_LEVEL);
216 spin_unlock_irqrestore(&sm->lock, flags);
217
218 if (mode & pattern)
219 type |= IRQ_TYPE_LEVEL;
220 if (edge & pattern)
221 type |= IRQ_EDGE_RISING;
222 if (level & pattern)
223 type |= IRQ_LEVEL_HIGH;
224
225 return type;
226}
227
228static struct irq_controller_class eim_irq_class = {
229 .typename = "EIM",
230 .handle = eim_handle_irq,
231 .setup = eim_setup,
232 .free = eim_free,
233 .mask = eim_mask,
234 .unmask = eim_unmask,
235 .set_type = eim_set_type,
236 .get_type = eim_get_type,
237};
238
239static int __init eim_init(void)
240{
241 struct at32_sm *sm = &system_manager;
242 unsigned int i;
243 u32 pattern;
244 int ret;
245
246 /*
247 * The EIM is really the same module as SM, so register
248 * mapping, etc. has been taken care of already.
249 */
250
251 /*
252 * Find out how many interrupt lines that are actually
253 * implemented in hardware.
254 */
255 sm_writel(sm, EIM_IDR, ~0UL);
256 sm_writel(sm, EIM_MODE, ~0UL);
257 pattern = sm_readl(sm, EIM_MODE);
258 sm->irqc.nr_irqs = fls(pattern);
259
260 ret = -ENOMEM;
261 sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
262 GFP_KERNEL);
263 if (!sm->action)
264 goto out;
265
266 for (i = 0; i < sm->irqc.nr_irqs; i++)
267 sm->action[i] = &eim_spurious_action;
268
269 spin_lock_init(&sm->lock);
270 sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
271 sm->irqc.class = &eim_irq_class;
272
273 ret = intc_register_controller(&sm->irqc);
274 if (ret < 0)
275 goto out_free_actions;
276
277 printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
278 sm->regs, sm->irqc.irq_group);
279 printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
280 sm->irqc.nr_irqs, sm->irqc.first_irq);
281
282 return 0;
283
284out_free_actions:
285 kfree(sm->action);
286out:
287 return ret;
288}
289arch_initcall(eim_init);
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h
new file mode 100644
index 000000000000..27565822ae2a
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sm.h
@@ -0,0 +1,240 @@
1/*
2 * Register definitions for SM
3 *
4 * System Manager
5 */
6#ifndef __ASM_AVR32_SM_H__
7#define __ASM_AVR32_SM_H__
8
9/* SM register offsets */
10#define SM_PM_MCCTRL 0x0000
11#define SM_PM_CKSEL 0x0004
12#define SM_PM_CPU_MASK 0x0008
13#define SM_PM_HSB_MASK 0x000c
14#define SM_PM_PBA_MASK 0x0010
15#define SM_PM_PBB_MASK 0x0014
16#define SM_PM_PLL0 0x0020
17#define SM_PM_PLL1 0x0024
18#define SM_PM_VCTRL 0x0030
19#define SM_PM_VMREF 0x0034
20#define SM_PM_VMV 0x0038
21#define SM_PM_IER 0x0040
22#define SM_PM_IDR 0x0044
23#define SM_PM_IMR 0x0048
24#define SM_PM_ISR 0x004c
25#define SM_PM_ICR 0x0050
26#define SM_PM_GCCTRL 0x0060
27#define SM_RTC_CTRL 0x0080
28#define SM_RTC_VAL 0x0084
29#define SM_RTC_TOP 0x0088
30#define SM_RTC_IER 0x0090
31#define SM_RTC_IDR 0x0094
32#define SM_RTC_IMR 0x0098
33#define SM_RTC_ISR 0x009c
34#define SM_RTC_ICR 0x00a0
35#define SM_WDT_CTRL 0x00b0
36#define SM_WDT_CLR 0x00b4
37#define SM_WDT_EXT 0x00b8
38#define SM_RC_RCAUSE 0x00c0
39#define SM_EIM_IER 0x0100
40#define SM_EIM_IDR 0x0104
41#define SM_EIM_IMR 0x0108
42#define SM_EIM_ISR 0x010c
43#define SM_EIM_ICR 0x0110
44#define SM_EIM_MODE 0x0114
45#define SM_EIM_EDGE 0x0118
46#define SM_EIM_LEVEL 0x011c
47#define SM_EIM_TEST 0x0120
48#define SM_EIM_NMIC 0x0124
49
50/* Bitfields in PM_MCCTRL */
51
52/* Bitfields in PM_CKSEL */
53#define SM_CPUSEL_OFFSET 0
54#define SM_CPUSEL_SIZE 3
55#define SM_CPUDIV_OFFSET 7
56#define SM_CPUDIV_SIZE 1
57#define SM_HSBSEL_OFFSET 8
58#define SM_HSBSEL_SIZE 3
59#define SM_HSBDIV_OFFSET 15
60#define SM_HSBDIV_SIZE 1
61#define SM_PBASEL_OFFSET 16
62#define SM_PBASEL_SIZE 3
63#define SM_PBADIV_OFFSET 23
64#define SM_PBADIV_SIZE 1
65#define SM_PBBSEL_OFFSET 24
66#define SM_PBBSEL_SIZE 3
67#define SM_PBBDIV_OFFSET 31
68#define SM_PBBDIV_SIZE 1
69
70/* Bitfields in PM_CPU_MASK */
71
72/* Bitfields in PM_HSB_MASK */
73
74/* Bitfields in PM_PBA_MASK */
75
76/* Bitfields in PM_PBB_MASK */
77
78/* Bitfields in PM_PLL0 */
79#define SM_PLLEN_OFFSET 0
80#define SM_PLLEN_SIZE 1
81#define SM_PLLOSC_OFFSET 1
82#define SM_PLLOSC_SIZE 1
83#define SM_PLLOPT_OFFSET 2
84#define SM_PLLOPT_SIZE 3
85#define SM_PLLDIV_OFFSET 8
86#define SM_PLLDIV_SIZE 8
87#define SM_PLLMUL_OFFSET 16
88#define SM_PLLMUL_SIZE 8
89#define SM_PLLCOUNT_OFFSET 24
90#define SM_PLLCOUNT_SIZE 6
91#define SM_PLLTEST_OFFSET 31
92#define SM_PLLTEST_SIZE 1
93
94/* Bitfields in PM_PLL1 */
95
96/* Bitfields in PM_VCTRL */
97#define SM_VAUTO_OFFSET 0
98#define SM_VAUTO_SIZE 1
99#define SM_PM_VCTRL_VAL_OFFSET 8
100#define SM_PM_VCTRL_VAL_SIZE 7
101
102/* Bitfields in PM_VMREF */
103#define SM_REFSEL_OFFSET 0
104#define SM_REFSEL_SIZE 4
105
106/* Bitfields in PM_VMV */
107#define SM_PM_VMV_VAL_OFFSET 0
108#define SM_PM_VMV_VAL_SIZE 8
109
110/* Bitfields in PM_IER */
111
112/* Bitfields in PM_IDR */
113
114/* Bitfields in PM_IMR */
115
116/* Bitfields in PM_ISR */
117
118/* Bitfields in PM_ICR */
119#define SM_LOCK0_OFFSET 0
120#define SM_LOCK0_SIZE 1
121#define SM_LOCK1_OFFSET 1
122#define SM_LOCK1_SIZE 1
123#define SM_WAKE_OFFSET 2
124#define SM_WAKE_SIZE 1
125#define SM_VOK_OFFSET 3
126#define SM_VOK_SIZE 1
127#define SM_VMRDY_OFFSET 4
128#define SM_VMRDY_SIZE 1
129#define SM_CKRDY_OFFSET 5
130#define SM_CKRDY_SIZE 1
131
132/* Bitfields in PM_GCCTRL */
133#define SM_OSCSEL_OFFSET 0
134#define SM_OSCSEL_SIZE 1
135#define SM_PLLSEL_OFFSET 1
136#define SM_PLLSEL_SIZE 1
137#define SM_CEN_OFFSET 2
138#define SM_CEN_SIZE 1
139#define SM_CPC_OFFSET 3
140#define SM_CPC_SIZE 1
141#define SM_DIVEN_OFFSET 4
142#define SM_DIVEN_SIZE 1
143#define SM_DIV_OFFSET 8
144#define SM_DIV_SIZE 8
145
146/* Bitfields in RTC_CTRL */
147#define SM_PCLR_OFFSET 1
148#define SM_PCLR_SIZE 1
149#define SM_TOPEN_OFFSET 2
150#define SM_TOPEN_SIZE 1
151#define SM_CLKEN_OFFSET 3
152#define SM_CLKEN_SIZE 1
153#define SM_PSEL_OFFSET 8
154#define SM_PSEL_SIZE 16
155
156/* Bitfields in RTC_VAL */
157#define SM_RTC_VAL_VAL_OFFSET 0
158#define SM_RTC_VAL_VAL_SIZE 31
159
160/* Bitfields in RTC_TOP */
161#define SM_RTC_TOP_VAL_OFFSET 0
162#define SM_RTC_TOP_VAL_SIZE 32
163
164/* Bitfields in RTC_IER */
165
166/* Bitfields in RTC_IDR */
167
168/* Bitfields in RTC_IMR */
169
170/* Bitfields in RTC_ISR */
171
172/* Bitfields in RTC_ICR */
173#define SM_TOPI_OFFSET 0
174#define SM_TOPI_SIZE 1
175
176/* Bitfields in WDT_CTRL */
177#define SM_KEY_OFFSET 24
178#define SM_KEY_SIZE 8
179
180/* Bitfields in WDT_CLR */
181
182/* Bitfields in WDT_EXT */
183
184/* Bitfields in RC_RCAUSE */
185#define SM_POR_OFFSET 0
186#define SM_POR_SIZE 1
187#define SM_BOD_OFFSET 1
188#define SM_BOD_SIZE 1
189#define SM_EXT_OFFSET 2
190#define SM_EXT_SIZE 1
191#define SM_WDT_OFFSET 3
192#define SM_WDT_SIZE 1
193#define SM_NTAE_OFFSET 4
194#define SM_NTAE_SIZE 1
195#define SM_SERP_OFFSET 5
196#define SM_SERP_SIZE 1
197
198/* Bitfields in EIM_IER */
199
200/* Bitfields in EIM_IDR */
201
202/* Bitfields in EIM_IMR */
203
204/* Bitfields in EIM_ISR */
205
206/* Bitfields in EIM_ICR */
207
208/* Bitfields in EIM_MODE */
209
210/* Bitfields in EIM_EDGE */
211#define SM_INT0_OFFSET 0
212#define SM_INT0_SIZE 1
213#define SM_INT1_OFFSET 1
214#define SM_INT1_SIZE 1
215#define SM_INT2_OFFSET 2
216#define SM_INT2_SIZE 1
217#define SM_INT3_OFFSET 3
218#define SM_INT3_SIZE 1
219
220/* Bitfields in EIM_LEVEL */
221
222/* Bitfields in EIM_TEST */
223#define SM_TESTEN_OFFSET 31
224#define SM_TESTEN_SIZE 1
225
226/* Bitfields in EIM_NMIC */
227#define SM_EN_OFFSET 0
228#define SM_EN_SIZE 1
229
230/* Bit manipulation macros */
231#define SM_BIT(name) (1 << SM_##name##_OFFSET)
232#define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
233#define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
234#define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
235
236/* Register access macros */
237#define sm_readl(port,reg) readl((port)->regs + SM_##reg)
238#define sm_writel(port,reg,value) writel((value), (port)->regs + SM_##reg)
239
240#endif /* __ASM_AVR32_SM_H__ */
diff --git a/arch/avr32/mm/Makefile b/arch/avr32/mm/Makefile
new file mode 100644
index 000000000000..0066491f90d4
--- /dev/null
+++ b/arch/avr32/mm/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the Linux/AVR32 kernel.
3#
4
5obj-y += init.o clear_page.o copy_page.o dma-coherent.o
6obj-y += ioremap.o cache.o fault.o tlb.o
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
new file mode 100644
index 000000000000..450515b245a0
--- /dev/null
+++ b/arch/avr32/mm/cache.c
@@ -0,0 +1,150 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/highmem.h>
10#include <linux/unistd.h>
11
12#include <asm/cacheflush.h>
13#include <asm/cachectl.h>
14#include <asm/processor.h>
15#include <asm/uaccess.h>
16
17/*
18 * If you attempt to flush anything more than this, you need superuser
19 * privileges. The value is completely arbitrary.
20 */
21#define CACHEFLUSH_MAX_LEN 1024
22
23void invalidate_dcache_region(void *start, size_t size)
24{
25 unsigned long v, begin, end, linesz;
26
27 linesz = boot_cpu_data.dcache.linesz;
28
29 //printk("invalidate dcache: %p + %u\n", start, size);
30
31 /* You asked for it, you got it */
32 begin = (unsigned long)start & ~(linesz - 1);
33 end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
34
35 for (v = begin; v < end; v += linesz)
36 invalidate_dcache_line((void *)v);
37}
38
39void clean_dcache_region(void *start, size_t size)
40{
41 unsigned long v, begin, end, linesz;
42
43 linesz = boot_cpu_data.dcache.linesz;
44 begin = (unsigned long)start & ~(linesz - 1);
45 end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
46
47 for (v = begin; v < end; v += linesz)
48 clean_dcache_line((void *)v);
49 flush_write_buffer();
50}
51
52void flush_dcache_region(void *start, size_t size)
53{
54 unsigned long v, begin, end, linesz;
55
56 linesz = boot_cpu_data.dcache.linesz;
57 begin = (unsigned long)start & ~(linesz - 1);
58 end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
59
60 for (v = begin; v < end; v += linesz)
61 flush_dcache_line((void *)v);
62 flush_write_buffer();
63}
64
65void invalidate_icache_region(void *start, size_t size)
66{
67 unsigned long v, begin, end, linesz;
68
69 linesz = boot_cpu_data.icache.linesz;
70 begin = (unsigned long)start & ~(linesz - 1);
71 end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1);
72
73 for (v = begin; v < end; v += linesz)
74 invalidate_icache_line((void *)v);
75}
76
77static inline void __flush_icache_range(unsigned long start, unsigned long end)
78{
79 unsigned long v, linesz;
80
81 linesz = boot_cpu_data.dcache.linesz;
82 for (v = start; v < end; v += linesz) {
83 clean_dcache_line((void *)v);
84 invalidate_icache_line((void *)v);
85 }
86
87 flush_write_buffer();
88}
89
90/*
91 * This one is called after a module has been loaded.
92 */
93void flush_icache_range(unsigned long start, unsigned long end)
94{
95 unsigned long linesz;
96
97 linesz = boot_cpu_data.dcache.linesz;
98 __flush_icache_range(start & ~(linesz - 1),
99 (end + linesz - 1) & ~(linesz - 1));
100}
101
102/*
103 * This one is called from do_no_page(), do_swap_page() and install_page().
104 */
105void flush_icache_page(struct vm_area_struct *vma, struct page *page)
106{
107 if (vma->vm_flags & VM_EXEC) {
108 void *v = kmap(page);
109 __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE);
110 kunmap(v);
111 }
112}
113
114/*
115 * This one is used by copy_to_user_page()
116 */
117void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
118 unsigned long addr, int len)
119{
120 if (vma->vm_flags & VM_EXEC)
121 flush_icache_range(addr, addr + len);
122}
123
124asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len)
125{
126 int ret;
127
128 if (len > CACHEFLUSH_MAX_LEN) {
129 ret = -EPERM;
130 if (!capable(CAP_SYS_ADMIN))
131 goto out;
132 }
133
134 ret = -EFAULT;
135 if (!access_ok(VERIFY_WRITE, addr, len))
136 goto out;
137
138 switch (operation) {
139 case CACHE_IFLUSH:
140 flush_icache_range((unsigned long)addr,
141 (unsigned long)addr + len);
142 ret = 0;
143 break;
144 default:
145 ret = -EINVAL;
146 }
147
148out:
149 return ret;
150}
diff --git a/arch/avr32/mm/clear_page.S b/arch/avr32/mm/clear_page.S
new file mode 100644
index 000000000000..5d70dca00699
--- /dev/null
+++ b/arch/avr32/mm/clear_page.S
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/linkage.h>
10#include <asm/page.h>
11
12/*
13 * clear_page
14 * r12: P1 address (to)
15 */
16 .text
17 .global clear_page
18clear_page:
19 sub r9, r12, -PAGE_SIZE
20 mov r10, 0
21 mov r11, 0
220: st.d r12++, r10
23 cp r12, r9
24 brne 0b
25 mov pc, lr
diff --git a/arch/avr32/mm/copy_page.S b/arch/avr32/mm/copy_page.S
new file mode 100644
index 000000000000..c2b3752946b8
--- /dev/null
+++ b/arch/avr32/mm/copy_page.S
@@ -0,0 +1,28 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/linkage.h>
9#include <asm/page.h>
10
11/*
12 * copy_page
13 *
14 * r12 to (P1 address)
15 * r11 from (P1 address)
16 * r8-r10 scratch
17 */
18 .text
19 .global copy_page
20copy_page:
21 sub r10, r11, -(1 << PAGE_SHIFT)
22 /* pref r11[0] */
231: /* pref r11[8] */
24 ld.d r8, r11++
25 st.d r12++, r8
26 cp r11, r10
27 brlo 1b
28 mov pc, lr
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
new file mode 100644
index 000000000000..44ab8a7bdae2
--- /dev/null
+++ b/arch/avr32/mm/dma-coherent.c
@@ -0,0 +1,139 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/dma-mapping.h>
10
11#include <asm/addrspace.h>
12#include <asm/cacheflush.h>
13
14void dma_cache_sync(void *vaddr, size_t size, int direction)
15{
16 /*
17 * No need to sync an uncached area
18 */
19 if (PXSEG(vaddr) == P2SEG)
20 return;
21
22 switch (direction) {
23 case DMA_FROM_DEVICE: /* invalidate only */
24 dma_cache_inv(vaddr, size);
25 break;
26 case DMA_TO_DEVICE: /* writeback only */
27 dma_cache_wback(vaddr, size);
28 break;
29 case DMA_BIDIRECTIONAL: /* writeback and invalidate */
30 dma_cache_wback_inv(vaddr, size);
31 break;
32 default:
33 BUG();
34 }
35}
36EXPORT_SYMBOL(dma_cache_sync);
37
38static struct page *__dma_alloc(struct device *dev, size_t size,
39 dma_addr_t *handle, gfp_t gfp)
40{
41 struct page *page, *free, *end;
42 int order;
43
44 size = PAGE_ALIGN(size);
45 order = get_order(size);
46
47 page = alloc_pages(gfp, order);
48 if (!page)
49 return NULL;
50 split_page(page, order);
51
52 /*
53 * When accessing physical memory with valid cache data, we
54 * get a cache hit even if the virtual memory region is marked
55 * as uncached.
56 *
57 * Since the memory is newly allocated, there is no point in
58 * doing a writeback. If the previous owner cares, he should
59 * have flushed the cache before releasing the memory.
60 */
61 invalidate_dcache_region(phys_to_virt(page_to_phys(page)), size);
62
63 *handle = page_to_bus(page);
64 free = page + (size >> PAGE_SHIFT);
65 end = page + (1 << order);
66
67 /*
68 * Free any unused pages
69 */
70 while (free < end) {
71 __free_page(free);
72 free++;
73 }
74
75 return page;
76}
77
78static void __dma_free(struct device *dev, size_t size,
79 struct page *page, dma_addr_t handle)
80{
81 struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
82
83 while (page < end)
84 __free_page(page++);
85}
86
87void *dma_alloc_coherent(struct device *dev, size_t size,
88 dma_addr_t *handle, gfp_t gfp)
89{
90 struct page *page;
91 void *ret = NULL;
92
93 page = __dma_alloc(dev, size, handle, gfp);
94 if (page)
95 ret = phys_to_uncached(page_to_phys(page));
96
97 return ret;
98}
99EXPORT_SYMBOL(dma_alloc_coherent);
100
101void dma_free_coherent(struct device *dev, size_t size,
102 void *cpu_addr, dma_addr_t handle)
103{
104 void *addr = phys_to_cached(uncached_to_phys(cpu_addr));
105 struct page *page;
106
107 pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n",
108 cpu_addr, (unsigned long)handle, (unsigned)size);
109 BUG_ON(!virt_addr_valid(addr));
110 page = virt_to_page(addr);
111 __dma_free(dev, size, page, handle);
112}
113EXPORT_SYMBOL(dma_free_coherent);
114
115#if 0
116void *dma_alloc_writecombine(struct device *dev, size_t size,
117 dma_addr_t *handle, gfp_t gfp)
118{
119 struct page *page;
120
121 page = __dma_alloc(dev, size, handle, gfp);
122
123 /* Now, map the page into P3 with write-combining turned on */
124 return __ioremap(page_to_phys(page), size, _PAGE_BUFFER);
125}
126EXPORT_SYMBOL(dma_alloc_writecombine);
127
128void dma_free_writecombine(struct device *dev, size_t size,
129 void *cpu_addr, dma_addr_t handle)
130{
131 struct page *page;
132
133 iounmap(cpu_addr);
134
135 page = bus_to_page(handle);
136 __dma_free(dev, size, page, handle);
137}
138EXPORT_SYMBOL(dma_free_writecombine);
139#endif
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
new file mode 100644
index 000000000000..678557260a35
--- /dev/null
+++ b/arch/avr32/mm/fault.c
@@ -0,0 +1,315 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * Based on linux/arch/sh/mm/fault.c:
5 * Copyright (C) 1999 Niibe Yutaka
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/pagemap.h>
15
16#include <asm/kdebug.h>
17#include <asm/mmu_context.h>
18#include <asm/sysreg.h>
19#include <asm/uaccess.h>
20#include <asm/tlb.h>
21
22#ifdef DEBUG
23static void dump_code(unsigned long pc)
24{
25 char *p = (char *)pc;
26 char val;
27 int i;
28
29
30 printk(KERN_DEBUG "Code:");
31 for (i = 0; i < 16; i++) {
32 if (__get_user(val, p + i))
33 break;
34 printk(" %02x", val);
35 }
36 printk("\n");
37}
38#endif
39
40#ifdef CONFIG_KPROBES
41ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
42
43/* Hook to register for page fault notifications */
44int register_page_fault_notifier(struct notifier_block *nb)
45{
46 return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
47}
48
49int unregister_page_fault_notifier(struct notifier_block *nb)
50{
51 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
52}
53
54static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
55 int trap, int sig)
56{
57 struct die_args args = {
58 .regs = regs,
59 .trapnr = trap,
60 };
61 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
62}
63#else
64static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
65 int trap, int sig)
66{
67 return NOTIFY_DONE;
68}
69#endif
70
71/*
72 * This routine handles page faults. It determines the address and the
73 * problem, and then passes it off to one of the appropriate routines.
74 *
75 * ecr is the Exception Cause Register. Possible values are:
76 * 5: Page not found (instruction access)
77 * 6: Protection fault (instruction access)
78 * 12: Page not found (read access)
79 * 13: Page not found (write access)
80 * 14: Protection fault (read access)
81 * 15: Protection fault (write access)
82 */
83asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
84{
85 struct task_struct *tsk;
86 struct mm_struct *mm;
87 struct vm_area_struct *vma;
88 const struct exception_table_entry *fixup;
89 unsigned long address;
90 unsigned long page;
91 int writeaccess = 0;
92
93 if (notify_page_fault(DIE_PAGE_FAULT, regs,
94 ecr, SIGSEGV) == NOTIFY_STOP)
95 return;
96
97 address = sysreg_read(TLBEAR);
98
99 tsk = current;
100 mm = tsk->mm;
101
102 /*
103 * If we're in an interrupt or have no user context, we must
104 * not take the fault...
105 */
106 if (in_atomic() || !mm || regs->sr & SYSREG_BIT(GM))
107 goto no_context;
108
109 local_irq_enable();
110
111 down_read(&mm->mmap_sem);
112
113 vma = find_vma(mm, address);
114 if (!vma)
115 goto bad_area;
116 if (vma->vm_start <= address)
117 goto good_area;
118 if (!(vma->vm_flags & VM_GROWSDOWN))
119 goto bad_area;
120 if (expand_stack(vma, address))
121 goto bad_area;
122
123 /*
124 * Ok, we have a good vm_area for this memory access, so we
125 * can handle it...
126 */
127good_area:
128 //pr_debug("good area: vm_flags = 0x%lx\n", vma->vm_flags);
129 switch (ecr) {
130 case ECR_PROTECTION_X:
131 case ECR_TLB_MISS_X:
132 if (!(vma->vm_flags & VM_EXEC))
133 goto bad_area;
134 break;
135 case ECR_PROTECTION_R:
136 case ECR_TLB_MISS_R:
137 if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
138 goto bad_area;
139 break;
140 case ECR_PROTECTION_W:
141 case ECR_TLB_MISS_W:
142 if (!(vma->vm_flags & VM_WRITE))
143 goto bad_area;
144 writeaccess = 1;
145 break;
146 default:
147 panic("Unhandled case %lu in do_page_fault!", ecr);
148 }
149
150 /*
151 * If for any reason at all we couldn't handle the fault, make
152 * sure we exit gracefully rather than endlessly redo the
153 * fault.
154 */
155survive:
156 switch (handle_mm_fault(mm, vma, address, writeaccess)) {
157 case VM_FAULT_MINOR:
158 tsk->min_flt++;
159 break;
160 case VM_FAULT_MAJOR:
161 tsk->maj_flt++;
162 break;
163 case VM_FAULT_SIGBUS:
164 goto do_sigbus;
165 case VM_FAULT_OOM:
166 goto out_of_memory;
167 default:
168 BUG();
169 }
170
171 up_read(&mm->mmap_sem);
172 return;
173
174 /*
175 * Something tried to access memory that isn't in our memory
176 * map. Fix it, but check if it's kernel or user first...
177 */
178bad_area:
179 pr_debug("Bad area [%s:%u]: addr %08lx, ecr %lu\n",
180 tsk->comm, tsk->pid, address, ecr);
181
182 up_read(&mm->mmap_sem);
183
184 if (user_mode(regs)) {
185 /* Hmm...we have to pass address and ecr somehow... */
186 /* tsk->thread.address = address;
187 tsk->thread.error_code = ecr; */
188#ifdef DEBUG
189 show_regs(regs);
190 dump_code(regs->pc);
191
192 page = sysreg_read(PTBR);
193 printk("ptbr = %08lx", page);
194 if (page) {
195 page = ((unsigned long *)page)[address >> 22];
196 printk(" pgd = %08lx", page);
197 if (page & _PAGE_PRESENT) {
198 page &= PAGE_MASK;
199 address &= 0x003ff000;
200 page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
201 printk(" pte = %08lx\n", page);
202 }
203 }
204#endif
205 pr_debug("Sending SIGSEGV to PID %d...\n",
206 tsk->pid);
207 force_sig(SIGSEGV, tsk);
208 return;
209 }
210
211no_context:
212 pr_debug("No context\n");
213
214 /* Are we prepared to handle this kernel fault? */
215 fixup = search_exception_tables(regs->pc);
216 if (fixup) {
217 regs->pc = fixup->fixup;
218 pr_debug("Found fixup at %08lx\n", fixup->fixup);
219 return;
220 }
221
222 /*
223 * Oops. The kernel tried to access some bad page. We'll have
224 * to terminate things with extreme prejudice.
225 */
226 if (address < PAGE_SIZE)
227 printk(KERN_ALERT
228 "Unable to handle kernel NULL pointer dereference");
229 else
230 printk(KERN_ALERT
231 "Unable to handle kernel paging request");
232 printk(" at virtual address %08lx\n", address);
233 printk(KERN_ALERT "pc = %08lx\n", regs->pc);
234
235 page = sysreg_read(PTBR);
236 printk(KERN_ALERT "ptbr = %08lx", page);
237 if (page) {
238 page = ((unsigned long *)page)[address >> 22];
239 printk(" pgd = %08lx", page);
240 if (page & _PAGE_PRESENT) {
241 page &= PAGE_MASK;
242 address &= 0x003ff000;
243 page = ((unsigned long *)__va(page))[address >> PAGE_SHIFT];
244 printk(" pte = %08lx\n", page);
245 }
246 }
247 die("\nOops", regs, ecr);
248 do_exit(SIGKILL);
249
250 /*
251 * We ran out of memory, or some other thing happened to us
252 * that made us unable to handle the page fault gracefully.
253 */
254out_of_memory:
255 printk("Out of memory\n");
256 up_read(&mm->mmap_sem);
257 if (current->pid == 1) {
258 yield();
259 down_read(&mm->mmap_sem);
260 goto survive;
261 }
262 printk("VM: Killing process %s\n", tsk->comm);
263 if (user_mode(regs))
264 do_exit(SIGKILL);
265 goto no_context;
266
267do_sigbus:
268 up_read(&mm->mmap_sem);
269
270 /*
271 * Send a sigbus, regardless of whether we were in kernel or
272 * user mode.
273 */
274 /* address, error_code, trap_no, ... */
275#ifdef DEBUG
276 show_regs(regs);
277 dump_code(regs->pc);
278#endif
279 pr_debug("Sending SIGBUS to PID %d...\n", tsk->pid);
280 force_sig(SIGBUS, tsk);
281
282 /* Kernel mode? Handle exceptions or die */
283 if (!user_mode(regs))
284 goto no_context;
285}
286
287asmlinkage void do_bus_error(unsigned long addr, int write_access,
288 struct pt_regs *regs)
289{
290 printk(KERN_ALERT
291 "Bus error at physical address 0x%08lx (%s access)\n",
292 addr, write_access ? "write" : "read");
293 printk(KERN_INFO "DTLB dump:\n");
294 dump_dtlb();
295 die("Bus Error", regs, write_access);
296 do_exit(SIGKILL);
297}
298
299/*
300 * This functionality is currently not possible to implement because
301 * we're using segmentation to ensure a fixed mapping of the kernel
302 * virtual address space.
303 *
304 * It would be possible to implement this, but it would require us to
305 * disable segmentation at startup and load the kernel mappings into
306 * the TLB like any other pages. There will be lots of trickery to
307 * avoid recursive invocation of the TLB miss handler, though...
308 */
309#ifdef CONFIG_DEBUG_PAGEALLOC
310void kernel_map_pages(struct page *page, int numpages, int enable)
311{
312
313}
314EXPORT_SYMBOL(kernel_map_pages);
315#endif
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
new file mode 100644
index 000000000000..3e6c41039808
--- /dev/null
+++ b/arch/avr32/mm/init.c
@@ -0,0 +1,480 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/mm.h>
11#include <linux/swap.h>
12#include <linux/init.h>
13#include <linux/initrd.h>
14#include <linux/mmzone.h>
15#include <linux/bootmem.h>
16#include <linux/pagemap.h>
17#include <linux/pfn.h>
18#include <linux/nodemask.h>
19
20#include <asm/page.h>
21#include <asm/mmu_context.h>
22#include <asm/tlb.h>
23#include <asm/io.h>
24#include <asm/dma.h>
25#include <asm/setup.h>
26#include <asm/sections.h>
27
28DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
29
30pgd_t swapper_pg_dir[PTRS_PER_PGD];
31
32struct page *empty_zero_page;
33
34/*
35 * Cache of MMU context last used.
36 */
37unsigned long mmu_context_cache = NO_CONTEXT;
38
39#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
40#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
41
42void show_mem(void)
43{
44 int total = 0, reserved = 0, cached = 0;
45 int slab = 0, free = 0, shared = 0;
46 pg_data_t *pgdat;
47
48 printk("Mem-info:\n");
49 show_free_areas();
50
51 for_each_online_pgdat(pgdat) {
52 struct page *page, *end;
53
54 page = pgdat->node_mem_map;
55 end = page + pgdat->node_spanned_pages;
56
57 do {
58 total++;
59 if (PageReserved(page))
60 reserved++;
61 else if (PageSwapCache(page))
62 cached++;
63 else if (PageSlab(page))
64 slab++;
65 else if (!page_count(page))
66 free++;
67 else
68 shared += page_count(page) - 1;
69 page++;
70 } while (page < end);
71 }
72
73 printk ("%d pages of RAM\n", total);
74 printk ("%d free pages\n", free);
75 printk ("%d reserved pages\n", reserved);
76 printk ("%d slab pages\n", slab);
77 printk ("%d pages shared\n", shared);
78 printk ("%d pages swap cached\n", cached);
79}
80
81static void __init print_memory_map(const char *what,
82 struct tag_mem_range *mem)
83{
84 printk ("%s:\n", what);
85 for (; mem; mem = mem->next) {
86 printk (" %08lx - %08lx\n",
87 (unsigned long)mem->addr,
88 (unsigned long)(mem->addr + mem->size));
89 }
90}
91
92#define MAX_LOWMEM HIGHMEM_START
93#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM)
94
95/*
96 * Sort a list of memory regions in-place by ascending address.
97 *
98 * We're using bubble sort because we only have singly linked lists
99 * with few elements.
100 */
101static void __init sort_mem_list(struct tag_mem_range **pmem)
102{
103 int done;
104 struct tag_mem_range **a, **b;
105
106 if (!*pmem)
107 return;
108
109 do {
110 done = 1;
111 a = pmem, b = &(*pmem)->next;
112 while (*b) {
113 if ((*a)->addr > (*b)->addr) {
114 struct tag_mem_range *tmp;
115 tmp = (*b)->next;
116 (*b)->next = *a;
117 *a = *b;
118 *b = tmp;
119 done = 0;
120 }
121 a = &(*a)->next;
122 b = &(*a)->next;
123 }
124 } while (!done);
125}
126
127/*
128 * Find a free memory region large enough for storing the
129 * bootmem bitmap.
130 */
131static unsigned long __init
132find_bootmap_pfn(const struct tag_mem_range *mem)
133{
134 unsigned long bootmap_pages, bootmap_len;
135 unsigned long node_pages = PFN_UP(mem->size);
136 unsigned long bootmap_addr = mem->addr;
137 struct tag_mem_range *reserved = mem_reserved;
138 struct tag_mem_range *ramdisk = mem_ramdisk;
139 unsigned long kern_start = virt_to_phys(_stext);
140 unsigned long kern_end = virt_to_phys(_end);
141
142 bootmap_pages = bootmem_bootmap_pages(node_pages);
143 bootmap_len = bootmap_pages << PAGE_SHIFT;
144
145 /*
146 * Find a large enough region without reserved pages for
147 * storing the bootmem bitmap. We can take advantage of the
148 * fact that all lists have been sorted.
149 *
150 * We have to check explicitly reserved regions as well as the
151 * kernel image and any RAMDISK images...
152 *
153 * Oh, and we have to make sure we don't overwrite the taglist
154 * since we're going to use it until the bootmem allocator is
155 * fully up and running.
156 */
157 while (1) {
158 if ((bootmap_addr < kern_end) &&
159 ((bootmap_addr + bootmap_len) > kern_start))
160 bootmap_addr = kern_end;
161
162 while (reserved &&
163 (bootmap_addr >= (reserved->addr + reserved->size)))
164 reserved = reserved->next;
165
166 if (reserved &&
167 ((bootmap_addr + bootmap_len) >= reserved->addr)) {
168 bootmap_addr = reserved->addr + reserved->size;
169 continue;
170 }
171
172 while (ramdisk &&
173 (bootmap_addr >= (ramdisk->addr + ramdisk->size)))
174 ramdisk = ramdisk->next;
175
176 if (!ramdisk ||
177 ((bootmap_addr + bootmap_len) < ramdisk->addr))
178 break;
179
180 bootmap_addr = ramdisk->addr + ramdisk->size;
181 }
182
183 if ((PFN_UP(bootmap_addr) + bootmap_len) >= (mem->addr + mem->size))
184 return ~0UL;
185
186 return PFN_UP(bootmap_addr);
187}
188
189void __init setup_bootmem(void)
190{
191 unsigned bootmap_size;
192 unsigned long first_pfn, bootmap_pfn, pages;
193 unsigned long max_pfn, max_low_pfn;
194 unsigned long kern_start = virt_to_phys(_stext);
195 unsigned long kern_end = virt_to_phys(_end);
196 unsigned node = 0;
197 struct tag_mem_range *bank, *res;
198
199 sort_mem_list(&mem_phys);
200 sort_mem_list(&mem_reserved);
201
202 print_memory_map("Physical memory", mem_phys);
203 print_memory_map("Reserved memory", mem_reserved);
204
205 nodes_clear(node_online_map);
206
207 if (mem_ramdisk) {
208#ifdef CONFIG_BLK_DEV_INITRD
209 initrd_start = __va(mem_ramdisk->addr);
210 initrd_end = initrd_start + mem_ramdisk->size;
211
212 print_memory_map("RAMDISK images", mem_ramdisk);
213 if (mem_ramdisk->next)
214 printk(KERN_WARNING
215 "Warning: Only the first RAMDISK image "
216 "will be used\n");
217 sort_mem_list(&mem_ramdisk);
218#else
219 printk(KERN_WARNING "RAM disk image present, but "
220 "no initrd support in kernel!\n");
221#endif
222 }
223
224 if (mem_phys->next)
225 printk(KERN_WARNING "Only using first memory bank\n");
226
227 for (bank = mem_phys; bank; bank = NULL) {
228 first_pfn = PFN_UP(bank->addr);
229 max_low_pfn = max_pfn = PFN_DOWN(bank->addr + bank->size);
230 bootmap_pfn = find_bootmap_pfn(bank);
231 if (bootmap_pfn > max_pfn)
232 panic("No space for bootmem bitmap!\n");
233
234 if (max_low_pfn > MAX_LOWMEM_PFN) {
235 max_low_pfn = MAX_LOWMEM_PFN;
236#ifndef CONFIG_HIGHMEM
237 /*
238 * Lowmem is memory that can be addressed
239 * directly through P1/P2
240 */
241 printk(KERN_WARNING
242 "Node %u: Only %ld MiB of memory will be used.\n",
243 node, MAX_LOWMEM >> 20);
244 printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
245#else
246#error HIGHMEM is not supported by AVR32 yet
247#endif
248 }
249
250 /* Initialize the boot-time allocator with low memory only. */
251 bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn,
252 first_pfn, max_low_pfn);
253
254 printk("Node %u: bdata = %p, bdata->node_bootmem_map = %p\n",
255 node, NODE_DATA(node)->bdata,
256 NODE_DATA(node)->bdata->node_bootmem_map);
257
258 /*
259 * Register fully available RAM pages with the bootmem
260 * allocator.
261 */
262 pages = max_low_pfn - first_pfn;
263 free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn),
264 PFN_PHYS(pages));
265
266 /*
267 * Reserve space for the kernel image (if present in
268 * this node)...
269 */
270 if ((kern_start >= PFN_PHYS(first_pfn)) &&
271 (kern_start < PFN_PHYS(max_pfn))) {
272 printk("Node %u: Kernel image %08lx - %08lx\n",
273 node, kern_start, kern_end);
274 reserve_bootmem_node(NODE_DATA(node), kern_start,
275 kern_end - kern_start);
276 }
277
278 /* ...the bootmem bitmap... */
279 reserve_bootmem_node(NODE_DATA(node),
280 PFN_PHYS(bootmap_pfn),
281 bootmap_size);
282
283 /* ...any RAMDISK images... */
284 for (res = mem_ramdisk; res; res = res->next) {
285 if (res->addr > PFN_PHYS(max_pfn))
286 break;
287
288 if (res->addr >= PFN_PHYS(first_pfn)) {
289 printk("Node %u: RAMDISK %08lx - %08lx\n",
290 node,
291 (unsigned long)res->addr,
292 (unsigned long)(res->addr + res->size));
293 reserve_bootmem_node(NODE_DATA(node),
294 res->addr, res->size);
295 }
296 }
297
298 /* ...and any other reserved regions. */
299 for (res = mem_reserved; res; res = res->next) {
300 if (res->addr > PFN_PHYS(max_pfn))
301 break;
302
303 if (res->addr >= PFN_PHYS(first_pfn)) {
304 printk("Node %u: Reserved %08lx - %08lx\n",
305 node,
306 (unsigned long)res->addr,
307 (unsigned long)(res->addr + res->size));
308 reserve_bootmem_node(NODE_DATA(node),
309 res->addr, res->size);
310 }
311 }
312
313 node_set_online(node);
314 }
315}
316
317/*
318 * paging_init() sets up the page tables
319 *
320 * This routine also unmaps the page at virtual kernel address 0, so
321 * that we can trap those pesky NULL-reference errors in the kernel.
322 */
323void __init paging_init(void)
324{
325 extern unsigned long _evba;
326 void *zero_page;
327 int nid;
328
329 /*
330 * Make sure we can handle exceptions before enabling
331 * paging. Not that we should ever _get_ any exceptions this
332 * early, but you never know...
333 */
334 printk("Exception vectors start at %p\n", &_evba);
335 sysreg_write(EVBA, (unsigned long)&_evba);
336
337 /*
338 * Since we are ready to handle exceptions now, we should let
339 * the CPU generate them...
340 */
341 __asm__ __volatile__ ("csrf %0" : : "i"(SR_EM_BIT));
342
343 /*
344 * Allocate the zero page. The allocator will panic if it
345 * can't satisfy the request, so no need to check.
346 */
347 zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0),
348 PAGE_SIZE);
349
350 {
351 pgd_t *pg_dir;
352 int i;
353
354 pg_dir = swapper_pg_dir;
355 sysreg_write(PTBR, (unsigned long)pg_dir);
356
357 for (i = 0; i < PTRS_PER_PGD; i++)
358 pgd_val(pg_dir[i]) = 0;
359
360 enable_mmu();
361 printk ("CPU: Paging enabled\n");
362 }
363
364 for_each_online_node(nid) {
365 pg_data_t *pgdat = NODE_DATA(nid);
366 unsigned long zones_size[MAX_NR_ZONES];
367 unsigned long low, start_pfn;
368
369 start_pfn = pgdat->bdata->node_boot_start;
370 start_pfn >>= PAGE_SHIFT;
371 low = pgdat->bdata->node_low_pfn;
372
373 memset(zones_size, 0, sizeof(zones_size));
374 zones_size[ZONE_NORMAL] = low - start_pfn;
375
376 printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
377 nid, start_pfn, low);
378
379 free_area_init_node(nid, pgdat, zones_size, start_pfn, NULL);
380
381 printk("Node %u: mem_map starts at %p\n",
382 pgdat->node_id, pgdat->node_mem_map);
383 }
384
385 mem_map = NODE_DATA(0)->node_mem_map;
386
387 memset(zero_page, 0, PAGE_SIZE);
388 empty_zero_page = virt_to_page(zero_page);
389 flush_dcache_page(empty_zero_page);
390}
391
392void __init mem_init(void)
393{
394 int codesize, reservedpages, datasize, initsize;
395 int nid, i;
396
397 reservedpages = 0;
398 high_memory = NULL;
399
400 /* this will put all low memory onto the freelists */
401 for_each_online_node(nid) {
402 pg_data_t *pgdat = NODE_DATA(nid);
403 unsigned long node_pages = 0;
404 void *node_high_memory;
405
406 num_physpages += pgdat->node_present_pages;
407
408 if (pgdat->node_spanned_pages != 0)
409 node_pages = free_all_bootmem_node(pgdat);
410
411 totalram_pages += node_pages;
412
413 for (i = 0; i < node_pages; i++)
414 if (PageReserved(pgdat->node_mem_map + i))
415 reservedpages++;
416
417 node_high_memory = (void *)((pgdat->node_start_pfn
418 + pgdat->node_spanned_pages)
419 << PAGE_SHIFT);
420 if (node_high_memory > high_memory)
421 high_memory = node_high_memory;
422 }
423
424 max_mapnr = MAP_NR(high_memory);
425
426 codesize = (unsigned long)_etext - (unsigned long)_text;
427 datasize = (unsigned long)_edata - (unsigned long)_data;
428 initsize = (unsigned long)__init_end - (unsigned long)__init_begin;
429
430 printk ("Memory: %luk/%luk available (%dk kernel code, "
431 "%dk reserved, %dk data, %dk init)\n",
432 (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10),
433 totalram_pages << (PAGE_SHIFT - 10),
434 codesize >> 10,
435 reservedpages << (PAGE_SHIFT - 10),
436 datasize >> 10,
437 initsize >> 10);
438}
439
440static inline void free_area(unsigned long addr, unsigned long end, char *s)
441{
442 unsigned int size = (end - addr) >> 10;
443
444 for (; addr < end; addr += PAGE_SIZE) {
445 struct page *page = virt_to_page(addr);
446 ClearPageReserved(page);
447 init_page_count(page);
448 free_page(addr);
449 totalram_pages++;
450 }
451
452 if (size && s)
453 printk(KERN_INFO "Freeing %s memory: %dK (%lx - %lx)\n",
454 s, size, end - (size << 10), end);
455}
456
457void free_initmem(void)
458{
459 free_area((unsigned long)__init_begin, (unsigned long)__init_end,
460 "init");
461}
462
463#ifdef CONFIG_BLK_DEV_INITRD
464
465static int keep_initrd;
466
467void free_initrd_mem(unsigned long start, unsigned long end)
468{
469 if (!keep_initrd)
470 free_area(start, end, "initrd");
471}
472
473static int __init keepinitrd_setup(char *__unused)
474{
475 keep_initrd = 1;
476 return 1;
477}
478
479__setup("keepinitrd", keepinitrd_setup);
480#endif
diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c
new file mode 100644
index 000000000000..536021877df6
--- /dev/null
+++ b/arch/avr32/mm/ioremap.c
@@ -0,0 +1,197 @@
1/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/vmalloc.h>
9#include <linux/module.h>
10
11#include <asm/io.h>
12#include <asm/pgtable.h>
13#include <asm/cacheflush.h>
14#include <asm/tlbflush.h>
15#include <asm/addrspace.h>
16
17static inline int remap_area_pte(pte_t *pte, unsigned long address,
18 unsigned long end, unsigned long phys_addr,
19 pgprot_t prot)
20{
21 unsigned long pfn;
22
23 pfn = phys_addr >> PAGE_SHIFT;
24 do {
25 WARN_ON(!pte_none(*pte));
26
27 set_pte(pte, pfn_pte(pfn, prot));
28 address += PAGE_SIZE;
29 pfn++;
30 pte++;
31 } while (address && (address < end));
32
33 return 0;
34}
35
36static inline int remap_area_pmd(pmd_t *pmd, unsigned long address,
37 unsigned long end, unsigned long phys_addr,
38 pgprot_t prot)
39{
40 unsigned long next;
41
42 phys_addr -= address;
43
44 do {
45 pte_t *pte = pte_alloc_kernel(pmd, address);
46 if (!pte)
47 return -ENOMEM;
48
49 next = (address + PMD_SIZE) & PMD_MASK;
50 if (remap_area_pte(pte, address, next,
51 address + phys_addr, prot))
52 return -ENOMEM;
53
54 address = next;
55 pmd++;
56 } while (address && (address < end));
57 return 0;
58}
59
60static int remap_area_pud(pud_t *pud, unsigned long address,
61 unsigned long end, unsigned long phys_addr,
62 pgprot_t prot)
63{
64 unsigned long next;
65
66 phys_addr -= address;
67
68 do {
69 pmd_t *pmd = pmd_alloc(&init_mm, pud, address);
70 if (!pmd)
71 return -ENOMEM;
72 next = (address + PUD_SIZE) & PUD_MASK;
73 if (remap_area_pmd(pmd, address, next,
74 phys_addr + address, prot))
75 return -ENOMEM;
76
77 address = next;
78 pud++;
79 } while (address && address < end);
80
81 return 0;
82}
83
84static int remap_area_pages(unsigned long address, unsigned long phys_addr,
85 size_t size, pgprot_t prot)
86{
87 unsigned long end = address + size;
88 unsigned long next;
89 pgd_t *pgd;
90 int err = 0;
91
92 phys_addr -= address;
93
94 pgd = pgd_offset_k(address);
95 flush_cache_all();
96 BUG_ON(address >= end);
97
98 spin_lock(&init_mm.page_table_lock);
99 do {
100 pud_t *pud = pud_alloc(&init_mm, pgd, address);
101
102 err = -ENOMEM;
103 if (!pud)
104 break;
105
106 next = (address + PGDIR_SIZE) & PGDIR_MASK;
107 if (next < address || next > end)
108 next = end;
109 err = remap_area_pud(pud, address, next,
110 phys_addr + address, prot);
111 if (err)
112 break;
113
114 address = next;
115 pgd++;
116 } while (address && (address < end));
117
118 spin_unlock(&init_mm.page_table_lock);
119 flush_tlb_all();
120 return err;
121}
122
123/*
124 * Re-map an arbitrary physical address space into the kernel virtual
125 * address space. Needed when the kernel wants to access physical
126 * memory directly.
127 */
128void __iomem *__ioremap(unsigned long phys_addr, size_t size,
129 unsigned long flags)
130{
131 void *addr;
132 struct vm_struct *area;
133 unsigned long offset, last_addr;
134 pgprot_t prot;
135
136 /*
137 * Check if we can simply use the P4 segment. This area is
138 * uncacheable, so if caching/buffering is requested, we can't
139 * use it.
140 */
141 if ((phys_addr >= P4SEG) && (flags == 0))
142 return (void __iomem *)phys_addr;
143
144 /* Don't allow wraparound or zero size */
145 last_addr = phys_addr + size - 1;
146 if (!size || last_addr < phys_addr)
147 return NULL;
148
149 /*
150 * XXX: When mapping regular RAM, we'd better make damn sure
151 * it's never used for anything else. But this is really the
152 * caller's responsibility...
153 */
154 if (PHYSADDR(P2SEGADDR(phys_addr)) == phys_addr)
155 return (void __iomem *)P2SEGADDR(phys_addr);
156
157 /* Mappings have to be page-aligned */
158 offset = phys_addr & ~PAGE_MASK;
159 phys_addr &= PAGE_MASK;
160 size = PAGE_ALIGN(last_addr + 1) - phys_addr;
161
162 prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
163 | _PAGE_ACCESSED | _PAGE_TYPE_SMALL | flags);
164
165 /*
166 * Ok, go for it..
167 */
168 area = get_vm_area(size, VM_IOREMAP);
169 if (!area)
170 return NULL;
171 area->phys_addr = phys_addr;
172 addr = area->addr;
173 if (remap_area_pages((unsigned long)addr, phys_addr, size, prot)) {
174 vunmap(addr);
175 return NULL;
176 }
177
178 return (void __iomem *)(offset + (char *)addr);
179}
180EXPORT_SYMBOL(__ioremap);
181
182void __iounmap(void __iomem *addr)
183{
184 struct vm_struct *p;
185
186 if ((unsigned long)addr >= P4SEG)
187 return;
188
189 p = remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
190 if (unlikely(!p)) {
191 printk (KERN_ERR "iounmap: bad address %p\n", addr);
192 return;
193 }
194
195 kfree (p);
196}
197EXPORT_SYMBOL(__iounmap);
diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c
new file mode 100644
index 000000000000..5d0523bbe298
--- /dev/null
+++ b/arch/avr32/mm/tlb.c
@@ -0,0 +1,378 @@
1/*
2 * AVR32 TLB operations
3 *
4 * Copyright (C) 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/mm.h>
11
12#include <asm/mmu_context.h>
13
14#define _TLBEHI_I 0x100
15
16void show_dtlb_entry(unsigned int index)
17{
18 unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
19
20 local_irq_save(flags);
21 mmucr_save = sysreg_read(MMUCR);
22 tlbehi_save = sysreg_read(TLBEHI);
23 mmucr = mmucr_save & 0x13;
24 mmucr |= index << 14;
25 sysreg_write(MMUCR, mmucr);
26
27 asm volatile("tlbr" : : : "memory");
28 cpu_sync_pipeline();
29
30 tlbehi = sysreg_read(TLBEHI);
31 tlbelo = sysreg_read(TLBELO);
32
33 printk("%2u: %c %c %02x %05x %05x %o %o %c %c %c %c\n",
34 index,
35 (tlbehi & 0x200)?'1':'0',
36 (tlbelo & 0x100)?'1':'0',
37 (tlbehi & 0xff),
38 (tlbehi >> 12), (tlbelo >> 12),
39 (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
40 (tlbelo & 0x200)?'1':'0',
41 (tlbelo & 0x080)?'1':'0',
42 (tlbelo & 0x001)?'1':'0',
43 (tlbelo & 0x002)?'1':'0');
44
45 sysreg_write(MMUCR, mmucr_save);
46 sysreg_write(TLBEHI, tlbehi_save);
47 cpu_sync_pipeline();
48 local_irq_restore(flags);
49}
50
51void dump_dtlb(void)
52{
53 unsigned int i;
54
55 printk("ID V G ASID VPN PFN AP SZ C B W D\n");
56 for (i = 0; i < 32; i++)
57 show_dtlb_entry(i);
58}
59
60static unsigned long last_mmucr;
61
62static inline void set_replacement_pointer(unsigned shift)
63{
64 unsigned long mmucr, mmucr_save;
65
66 mmucr = mmucr_save = sysreg_read(MMUCR);
67
68 /* Does this mapping already exist? */
69 __asm__ __volatile__(
70 " tlbs\n"
71 " mfsr %0, %1"
72 : "=r"(mmucr)
73 : "i"(SYSREG_MMUCR));
74
75 if (mmucr & SYSREG_BIT(MMUCR_N)) {
76 /* Not found -- pick a not-recently-accessed entry */
77 unsigned long rp;
78 unsigned long tlbar = sysreg_read(TLBARLO);
79
80 rp = 32 - fls(tlbar);
81 if (rp == 32) {
82 rp = 0;
83 sysreg_write(TLBARLO, -1L);
84 }
85
86 mmucr &= 0x13;
87 mmucr |= (rp << shift);
88
89 sysreg_write(MMUCR, mmucr);
90 }
91
92 last_mmucr = mmucr;
93}
94
95static void update_dtlb(unsigned long address, pte_t pte, unsigned long asid)
96{
97 unsigned long vpn;
98
99 vpn = (address & MMU_VPN_MASK) | _TLBEHI_VALID | asid;
100 sysreg_write(TLBEHI, vpn);
101 cpu_sync_pipeline();
102
103 set_replacement_pointer(14);
104
105 sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);
106
107 /* Let's go */
108 asm volatile("nop\n\ttlbw" : : : "memory");
109 cpu_sync_pipeline();
110}
111
112void update_mmu_cache(struct vm_area_struct *vma,
113 unsigned long address, pte_t pte)
114{
115 unsigned long flags;
116
117 /* ptrace may call this routine */
118 if (vma && current->active_mm != vma->vm_mm)
119 return;
120
121 local_irq_save(flags);
122 update_dtlb(address, pte, get_asid());
123 local_irq_restore(flags);
124}
125
126void __flush_tlb_page(unsigned long asid, unsigned long page)
127{
128 unsigned long mmucr, tlbehi;
129
130 page |= asid;
131 sysreg_write(TLBEHI, page);
132 cpu_sync_pipeline();
133 asm volatile("tlbs");
134 mmucr = sysreg_read(MMUCR);
135
136 if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
137 unsigned long tlbarlo;
138 unsigned long entry;
139
140 /* Clear the "valid" bit */
141 tlbehi = sysreg_read(TLBEHI);
142 tlbehi &= ~_TLBEHI_VALID;
143 sysreg_write(TLBEHI, tlbehi);
144 cpu_sync_pipeline();
145
146 /* mark the entry as "not accessed" */
147 entry = (mmucr >> 14) & 0x3f;
148 tlbarlo = sysreg_read(TLBARLO);
149 tlbarlo |= (0x80000000 >> entry);
150 sysreg_write(TLBARLO, tlbarlo);
151
152 /* update the entry with valid bit clear */
153 asm volatile("tlbw");
154 cpu_sync_pipeline();
155 }
156}
157
158void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
159{
160 if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
161 unsigned long flags, asid;
162 unsigned long saved_asid = MMU_NO_ASID;
163
164 asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
165 page &= PAGE_MASK;
166
167 local_irq_save(flags);
168 if (vma->vm_mm != current->mm) {
169 saved_asid = get_asid();
170 set_asid(asid);
171 }
172
173 __flush_tlb_page(asid, page);
174
175 if (saved_asid != MMU_NO_ASID)
176 set_asid(saved_asid);
177 local_irq_restore(flags);
178 }
179}
180
181void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
182 unsigned long end)
183{
184 struct mm_struct *mm = vma->vm_mm;
185
186 if (mm->context != NO_CONTEXT) {
187 unsigned long flags;
188 int size;
189
190 local_irq_save(flags);
191 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
192 if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
193 mm->context = NO_CONTEXT;
194 if (mm == current->mm)
195 activate_context(mm);
196 } else {
197 unsigned long asid = mm->context & MMU_CONTEXT_ASID_MASK;
198 unsigned long saved_asid = MMU_NO_ASID;
199
200 start &= PAGE_MASK;
201 end += (PAGE_SIZE - 1);
202 end &= PAGE_MASK;
203 if (mm != current->mm) {
204 saved_asid = get_asid();
205 set_asid(asid);
206 }
207
208 while (start < end) {
209 __flush_tlb_page(asid, start);
210 start += PAGE_SIZE;
211 }
212 if (saved_asid != MMU_NO_ASID)
213 set_asid(saved_asid);
214 }
215 local_irq_restore(flags);
216 }
217}
218
219/*
220 * TODO: If this is only called for addresses > TASK_SIZE, we can probably
221 * skip the ASID stuff and just use the Global bit...
222 */
223void flush_tlb_kernel_range(unsigned long start, unsigned long end)
224{
225 unsigned long flags;
226 int size;
227
228 local_irq_save(flags);
229 size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
230 if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
231 flush_tlb_all();
232 } else {
233 unsigned long asid = init_mm.context & MMU_CONTEXT_ASID_MASK;
234 unsigned long saved_asid = get_asid();
235
236 start &= PAGE_MASK;
237 end += (PAGE_SIZE - 1);
238 end &= PAGE_MASK;
239 set_asid(asid);
240 while (start < end) {
241 __flush_tlb_page(asid, start);
242 start += PAGE_SIZE;
243 }
244 set_asid(saved_asid);
245 }
246 local_irq_restore(flags);
247}
248
249void flush_tlb_mm(struct mm_struct *mm)
250{
251 /* Invalidate all TLB entries of this process by getting a new ASID */
252 if (mm->context != NO_CONTEXT) {
253 unsigned long flags;
254
255 local_irq_save(flags);
256 mm->context = NO_CONTEXT;
257 if (mm == current->mm)
258 activate_context(mm);
259 local_irq_restore(flags);
260 }
261}
262
263void flush_tlb_all(void)
264{
265 unsigned long flags;
266
267 local_irq_save(flags);
268 sysreg_write(MMUCR, sysreg_read(MMUCR) | SYSREG_BIT(MMUCR_I));
269 local_irq_restore(flags);
270}
271
272#ifdef CONFIG_PROC_FS
273
274#include <linux/seq_file.h>
275#include <linux/proc_fs.h>
276#include <linux/init.h>
277
278static void *tlb_start(struct seq_file *tlb, loff_t *pos)
279{
280 static unsigned long tlb_index;
281
282 if (*pos >= 32)
283 return NULL;
284
285 tlb_index = 0;
286 return &tlb_index;
287}
288
289static void *tlb_next(struct seq_file *tlb, void *v, loff_t *pos)
290{
291 unsigned long *index = v;
292
293 if (*index >= 31)
294 return NULL;
295
296 ++*pos;
297 ++*index;
298 return index;
299}
300
301static void tlb_stop(struct seq_file *tlb, void *v)
302{
303
304}
305
306static int tlb_show(struct seq_file *tlb, void *v)
307{
308 unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
309 unsigned long *index = v;
310
311 if (*index == 0)
312 seq_puts(tlb, "ID V G ASID VPN PFN AP SZ C B W D\n");
313
314 BUG_ON(*index >= 32);
315
316 local_irq_save(flags);
317 mmucr_save = sysreg_read(MMUCR);
318 tlbehi_save = sysreg_read(TLBEHI);
319 mmucr = mmucr_save & 0x13;
320 mmucr |= *index << 14;
321 sysreg_write(MMUCR, mmucr);
322
323 asm volatile("tlbr" : : : "memory");
324 cpu_sync_pipeline();
325
326 tlbehi = sysreg_read(TLBEHI);
327 tlbelo = sysreg_read(TLBELO);
328
329 sysreg_write(MMUCR, mmucr_save);
330 sysreg_write(TLBEHI, tlbehi_save);
331 cpu_sync_pipeline();
332 local_irq_restore(flags);
333
334 seq_printf(tlb, "%2lu: %c %c %02x %05x %05x %o %o %c %c %c %c\n",
335 *index,
336 (tlbehi & 0x200)?'1':'0',
337 (tlbelo & 0x100)?'1':'0',
338 (tlbehi & 0xff),
339 (tlbehi >> 12), (tlbelo >> 12),
340 (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
341 (tlbelo & 0x200)?'1':'0',
342 (tlbelo & 0x080)?'1':'0',
343 (tlbelo & 0x001)?'1':'0',
344 (tlbelo & 0x002)?'1':'0');
345
346 return 0;
347}
348
349static struct seq_operations tlb_ops = {
350 .start = tlb_start,
351 .next = tlb_next,
352 .stop = tlb_stop,
353 .show = tlb_show,
354};
355
356static int tlb_open(struct inode *inode, struct file *file)
357{
358 return seq_open(file, &tlb_ops);
359}
360
361static struct file_operations proc_tlb_operations = {
362 .open = tlb_open,
363 .read = seq_read,
364 .llseek = seq_lseek,
365 .release = seq_release,
366};
367
368static int __init proctlb_init(void)
369{
370 struct proc_dir_entry *entry;
371
372 entry = create_proc_entry("tlb", 0, NULL);
373 if (entry)
374 entry->proc_fops = &proc_tlb_operations;
375 return 0;
376}
377late_initcall(proctlb_init);
378#endif /* CONFIG_PROC_FS */
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index a601a17cf568..f7b171b92ea2 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -27,7 +27,11 @@ config GENERIC_CALIBRATE_DELAY
27 27
28config GENERIC_HARDIRQS 28config GENERIC_HARDIRQS
29 bool 29 bool
30 default n 30 default y
31
32config GENERIC_HARDIRQS_NO__DO_IRQ
33 bool
34 default y
31 35
32config GENERIC_TIME 36config GENERIC_TIME
33 bool 37 bool
@@ -251,6 +255,12 @@ config MB93091_NO_MB
251endchoice 255endchoice
252endif 256endif
253 257
258config FUJITSU_MB93493
259 bool "MB93493 Multimedia chip"
260 help
261 Select this option if the MB93493 multimedia chip is going to be
262 used.
263
254choice 264choice
255 prompt "GP-Relative data support" 265 prompt "GP-Relative data support"
256 default GPREL_DATA_8 266 default GPREL_DATA_8
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index 5a827b349b5e..32db3499c461 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -10,15 +10,14 @@ extra-y:= head.o init_task.o vmlinux.lds
10obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \ 10obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
11 process.o traps.o ptrace.o signal.o dma.o \ 11 process.o traps.o ptrace.o signal.o dma.o \
12 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \ 12 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
13 debug-stub.o irq.o irq-routing.o sleep.o uaccess.o 13 debug-stub.o irq.o sleep.o uaccess.o
14 14
15obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o 15obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
16 16
17obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o 17obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o
18obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o
19obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
20obj-$(CONFIG_PM) += pm.o cmode.o 18obj-$(CONFIG_PM) += pm.o cmode.o
21obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o 19obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
20obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
22obj-$(CONFIG_SYSCTL) += sysctl.o 21obj-$(CONFIG_SYSCTL) += sysctl.o
23obj-$(CONFIG_FUTEX) += futex.o 22obj-$(CONFIG_FUTEX) += futex.o
24obj-$(CONFIG_MODULES) += module.o 23obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c
index 1381abcd5cc9..369bc0a7443d 100644
--- a/arch/frv/kernel/irq-mb93091.c
+++ b/arch/frv/kernel/irq-mb93091.c
@@ -24,7 +24,6 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28 27
29#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) 28#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
30 29
@@ -33,83 +32,131 @@
33#define __get_IFR() ({ __reg16(0xffc0000c); }) 32#define __get_IFR() ({ __reg16(0xffc0000c); })
34#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0) 33#define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0)
35 34
36static void frv_fpga_doirq(struct irq_source *source);
37static void frv_fpga_control(struct irq_group *group, int irq, int on);
38 35
39/*****************************************************************************/
40/* 36/*
41 * FPGA IRQ multiplexor 37 * on-motherboard FPGA PIC operations
42 */ 38 */
43static struct irq_source frv_fpga[4] = { 39static void frv_fpga_mask(unsigned int irq)
44#define __FPGA(X, M) \ 40{
45 [X] = { \ 41 uint16_t imr = __get_IMR();
46 .muxname = "fpga."#X, \
47 .irqmask = M, \
48 .doirq = frv_fpga_doirq, \
49 }
50 42
51 __FPGA(0, 0x0028), 43 imr |= 1 << (irq - IRQ_BASE_FPGA);
52 __FPGA(1, 0x0050),
53 __FPGA(2, 0x1c00),
54 __FPGA(3, 0x6386),
55};
56 44
57static struct irq_group frv_fpga_irqs = { 45 __set_IMR(imr);
58 .first_irq = IRQ_BASE_FPGA, 46}
59 .control = frv_fpga_control,
60 .sources = {
61 [ 1] = &frv_fpga[3],
62 [ 2] = &frv_fpga[3],
63 [ 3] = &frv_fpga[0],
64 [ 4] = &frv_fpga[1],
65 [ 5] = &frv_fpga[0],
66 [ 6] = &frv_fpga[1],
67 [ 7] = &frv_fpga[3],
68 [ 8] = &frv_fpga[3],
69 [ 9] = &frv_fpga[3],
70 [10] = &frv_fpga[2],
71 [11] = &frv_fpga[2],
72 [12] = &frv_fpga[2],
73 [13] = &frv_fpga[3],
74 [14] = &frv_fpga[3],
75 },
76};
77 47
48static void frv_fpga_ack(unsigned int irq)
49{
50 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
51}
78 52
79static void frv_fpga_control(struct irq_group *group, int index, int on) 53static void frv_fpga_mask_ack(unsigned int irq)
80{ 54{
81 uint16_t imr = __get_IMR(); 55 uint16_t imr = __get_IMR();
82 56
83 if (on) 57 imr |= 1 << (irq - IRQ_BASE_FPGA);
84 imr &= ~(1 << index); 58 __set_IMR(imr);
85 else 59
86 imr |= 1 << index; 60 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
61}
62
63static void frv_fpga_unmask(unsigned int irq)
64{
65 uint16_t imr = __get_IMR();
66
67 imr &= ~(1 << (irq - IRQ_BASE_FPGA));
87 68
88 __set_IMR(imr); 69 __set_IMR(imr);
89} 70}
90 71
91static void frv_fpga_doirq(struct irq_source *source) 72static struct irq_chip frv_fpga_pic = {
73 .name = "mb93091",
74 .ack = frv_fpga_ack,
75 .mask = frv_fpga_mask,
76 .mask_ack = frv_fpga_mask_ack,
77 .unmask = frv_fpga_unmask,
78};
79
80/*
81 * FPGA PIC interrupt handler
82 */
83static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
92{ 84{
93 uint16_t mask, imr; 85 uint16_t imr, mask = (unsigned long) _mask;
94 86
95 imr = __get_IMR(); 87 imr = __get_IMR();
96 mask = source->irqmask & ~imr & __get_IFR(); 88 mask = mask & ~imr & __get_IFR();
97 if (mask) { 89
98 __set_IMR(imr | mask); 90 /* poll all the triggered IRQs */
99 __clr_IFR(mask); 91 while (mask) {
100 distribute_irqs(&frv_fpga_irqs, mask); 92 int irq;
101 __set_IMR(imr); 93
94 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
95 irq = 31 - irq;
96 mask &= ~(1 << irq);
97
98 generic_handle_irq(IRQ_BASE_FPGA + irq, regs);
102 } 99 }
100
101 return IRQ_HANDLED;
103} 102}
104 103
104/*
105 * define an interrupt action for each FPGA PIC output
106 * - use dev_id to indicate the FPGA PIC input to output mappings
107 */
108static struct irqaction fpga_irq[4] = {
109 [0] = {
110 .handler = fpga_interrupt,
111 .flags = IRQF_DISABLED | IRQF_SHARED,
112 .mask = CPU_MASK_NONE,
113 .name = "fpga.0",
114 .dev_id = (void *) 0x0028UL,
115 },
116 [1] = {
117 .handler = fpga_interrupt,
118 .flags = IRQF_DISABLED | IRQF_SHARED,
119 .mask = CPU_MASK_NONE,
120 .name = "fpga.1",
121 .dev_id = (void *) 0x0050UL,
122 },
123 [2] = {
124 .handler = fpga_interrupt,
125 .flags = IRQF_DISABLED | IRQF_SHARED,
126 .mask = CPU_MASK_NONE,
127 .name = "fpga.2",
128 .dev_id = (void *) 0x1c00UL,
129 },
130 [3] = {
131 .handler = fpga_interrupt,
132 .flags = IRQF_DISABLED | IRQF_SHARED,
133 .mask = CPU_MASK_NONE,
134 .name = "fpga.3",
135 .dev_id = (void *) 0x6386UL,
136 }
137};
138
139/*
140 * initialise the motherboard FPGA's PIC
141 */
105void __init fpga_init(void) 142void __init fpga_init(void)
106{ 143{
144 int irq;
145
146 /* all PIC inputs are all set to be low-level driven, apart from the
147 * NMI button (15) which is fixed at falling-edge
148 */
107 __set_IMR(0x7ffe); 149 __set_IMR(0x7ffe);
108 __clr_IFR(0x0000); 150 __clr_IFR(0x0000);
109 151
110 frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0); 152 for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
111 frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1); 153 set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
112 frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2); 154
113 frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3); 155 set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
114 frv_irq_set_group(&frv_fpga_irqs); 156
157 /* the FPGA drives the first four external IRQ inputs on the CPU PIC */
158 setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
159 setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]);
160 setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]);
161 setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]);
115} 162}
diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c
index 48b2a6420888..a43a22158956 100644
--- a/arch/frv/kernel/irq-mb93093.c
+++ b/arch/frv/kernel/irq-mb93093.c
@@ -1,6 +1,6 @@
1/* irq-mb93093.c: MB93093 FPGA interrupt handling 1/* irq-mb93093.c: MB93093 FPGA interrupt handling
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28 27
29#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR))) 28#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
30 29
@@ -33,66 +32,102 @@
33#define __get_IFR() ({ __reg16(0x02); }) 32#define __get_IFR() ({ __reg16(0x02); })
34#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0) 33#define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0)
35 34
36static void frv_fpga_doirq(struct irq_source *source);
37static void frv_fpga_control(struct irq_group *group, int irq, int on);
38
39/*****************************************************************************/
40/* 35/*
41 * FPGA IRQ multiplexor 36 * off-CPU FPGA PIC operations
42 */ 37 */
43static struct irq_source frv_fpga[4] = { 38static void frv_fpga_mask(unsigned int irq)
44#define __FPGA(X, M) \ 39{
45 [X] = { \ 40 uint16_t imr = __get_IMR();
46 .muxname = "fpga."#X, \
47 .irqmask = M, \
48 .doirq = frv_fpga_doirq, \
49 }
50 41
51 __FPGA(0, 0x0700), 42 imr |= 1 << (irq - IRQ_BASE_FPGA);
52}; 43 __set_IMR(imr);
44}
53 45
54static struct irq_group frv_fpga_irqs = { 46static void frv_fpga_ack(unsigned int irq)
55 .first_irq = IRQ_BASE_FPGA, 47{
56 .control = frv_fpga_control, 48 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
57 .sources = { 49}
58 [ 8] = &frv_fpga[0], 50
59 [ 9] = &frv_fpga[0], 51static void frv_fpga_mask_ack(unsigned int irq)
60 [10] = &frv_fpga[0], 52{
61 }, 53 uint16_t imr = __get_IMR();
62};
63 54
55 imr |= 1 << (irq - IRQ_BASE_FPGA);
56 __set_IMR(imr);
57
58 __clr_IFR(1 << (irq - IRQ_BASE_FPGA));
59}
64 60
65static void frv_fpga_control(struct irq_group *group, int index, int on) 61static void frv_fpga_unmask(unsigned int irq)
66{ 62{
67 uint16_t imr = __get_IMR(); 63 uint16_t imr = __get_IMR();
68 64
69 if (on) 65 imr &= ~(1 << (irq - IRQ_BASE_FPGA));
70 imr &= ~(1 << index);
71 else
72 imr |= 1 << index;
73 66
74 __set_IMR(imr); 67 __set_IMR(imr);
75} 68}
76 69
77static void frv_fpga_doirq(struct irq_source *source) 70static struct irq_chip frv_fpga_pic = {
71 .name = "mb93093",
72 .ack = frv_fpga_ack,
73 .mask = frv_fpga_mask,
74 .mask_ack = frv_fpga_mask_ack,
75 .unmask = frv_fpga_unmask,
76 .end = frv_fpga_end,
77};
78
79/*
80 * FPGA PIC interrupt handler
81 */
82static irqreturn_t fpga_interrupt(int irq, void *_mask, struct pt_regs *regs)
78{ 83{
79 uint16_t mask, imr; 84 uint16_t imr, mask = (unsigned long) _mask;
80 85
81 imr = __get_IMR(); 86 imr = __get_IMR();
82 mask = source->irqmask & ~imr & __get_IFR(); 87 mask = mask & ~imr & __get_IFR();
83 if (mask) { 88
84 __set_IMR(imr | mask); 89 /* poll all the triggered IRQs */
85 __clr_IFR(mask); 90 while (mask) {
86 distribute_irqs(&frv_fpga_irqs, mask); 91 int irq;
87 __set_IMR(imr); 92
93 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
94 irq = 31 - irq;
95 mask &= ~(1 << irq);
96
97 generic_irq_handle(IRQ_BASE_FPGA + irq, regs);
88 } 98 }
99
100 return IRQ_HANDLED;
89} 101}
90 102
103/*
104 * define an interrupt action for each FPGA PIC output
105 * - use dev_id to indicate the FPGA PIC input to output mappings
106 */
107static struct irqaction fpga_irq[1] = {
108 [0] = {
109 .handler = fpga_interrupt,
110 .flags = IRQF_DISABLED,
111 .mask = CPU_MASK_NONE,
112 .name = "fpga.0",
113 .dev_id = (void *) 0x0700UL,
114 }
115};
116
117/*
118 * initialise the motherboard FPGA's PIC
119 */
91void __init fpga_init(void) 120void __init fpga_init(void)
92{ 121{
122 int irq;
123
124 /* all PIC inputs are all set to be edge triggered */
93 __set_IMR(0x0700); 125 __set_IMR(0x0700);
94 __clr_IFR(0x0000); 126 __clr_IFR(0x0000);
95 127
96 frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2); 128 for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
97 frv_irq_set_group(&frv_fpga_irqs); 129 set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
130
131 /* the FPGA drives external IRQ input #2 on the CPU PIC */
132 setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
98} 133}
diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c
index 988d035640e1..39c0188a3498 100644
--- a/arch/frv/kernel/irq-mb93493.c
+++ b/arch/frv/kernel/irq-mb93493.c
@@ -1,6 +1,6 @@
1/* irq-mb93493.c: MB93493 companion chip interrupt handler 1/* irq-mb93493.c: MB93493 companion chip interrupt handler
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -24,84 +24,126 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/irq.h> 25#include <asm/irq.h>
26#include <asm/irc-regs.h> 26#include <asm/irc-regs.h>
27#include <asm/irq-routing.h>
28#include <asm/mb93493-irqs.h> 27#include <asm/mb93493-irqs.h>
28#include <asm/mb93493-regs.h>
29 29
30static void frv_mb93493_doirq(struct irq_source *source); 30#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493))
31
32#define IRQ_ROUTING \
33 (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \
34 IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \
35 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \
36 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \
37 IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \
38 IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \
39 IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \
40 IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \
41 IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \
42 IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN))
31 43
32/*****************************************************************************/
33/* 44/*
34 * MB93493 companion chip IRQ multiplexor 45 * daughter board PIC operations
46 * - there is no way to ACK interrupts in the MB93493 chip
35 */ 47 */
36static struct irq_source frv_mb93493[2] = { 48static void frv_mb93493_mask(unsigned int irq)
37 [0] = {
38 .muxname = "mb93493.0",
39 .muxdata = __region_CS3 + 0x3d0,
40 .doirq = frv_mb93493_doirq,
41 .irqmask = 0x0000,
42 },
43 [1] = {
44 .muxname = "mb93493.1",
45 .muxdata = __region_CS3 + 0x3d4,
46 .doirq = frv_mb93493_doirq,
47 .irqmask = 0x0000,
48 },
49};
50
51static void frv_mb93493_control(struct irq_group *group, int index, int on)
52{ 49{
53 struct irq_source *source;
54 uint32_t iqsr; 50 uint32_t iqsr;
51 volatile void *piqsr;
55 52
56 if ((frv_mb93493[0].irqmask & (1 << index))) 53 if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
57 source = &frv_mb93493[0]; 54 piqsr = __addr_MB93493_IQSR(1);
58 else 55 else
59 source = &frv_mb93493[1]; 56 piqsr = __addr_MB93493_IQSR(0);
57
58 iqsr = readl(piqsr);
59 iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
60 writel(iqsr, piqsr);
61}
60 62
61 iqsr = readl(source->muxdata); 63static void frv_mb93493_ack(unsigned int irq)
62 if (on) 64{
63 iqsr |= 1 << (index + 16); 65}
66
67static void frv_mb93493_unmask(unsigned int irq)
68{
69 uint32_t iqsr;
70 volatile void *piqsr;
71
72 if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
73 piqsr = __addr_MB93493_IQSR(1);
64 else 74 else
65 iqsr &= ~(1 << (index + 16)); 75 piqsr = __addr_MB93493_IQSR(0);
66 76
67 writel(iqsr, source->muxdata); 77 iqsr = readl(piqsr);
78 iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
79 writel(iqsr, piqsr);
68} 80}
69 81
70static struct irq_group frv_mb93493_irqs = { 82static struct irq_chip frv_mb93493_pic = {
71 .first_irq = IRQ_BASE_MB93493, 83 .name = "mb93093",
72 .control = frv_mb93493_control, 84 .ack = frv_mb93493_ack,
85 .mask = frv_mb93493_mask,
86 .mask_ack = frv_mb93493_mask,
87 .unmask = frv_mb93493_unmask,
73}; 88};
74 89
75static void frv_mb93493_doirq(struct irq_source *source) 90/*
91 * MB93493 PIC interrupt handler
92 */
93static irqreturn_t mb93493_interrupt(int irq, void *_piqsr, struct pt_regs *regs)
76{ 94{
77 uint32_t mask = readl(source->muxdata); 95 volatile void *piqsr = _piqsr;
78 mask = mask & (mask >> 16) & 0xffff; 96 uint32_t iqsr;
79 97
80 if (mask) 98 iqsr = readl(piqsr);
81 distribute_irqs(&frv_mb93493_irqs, mask); 99 iqsr = iqsr & (iqsr >> 16) & 0xffff;
82}
83 100
84static void __init mb93493_irq_route(int irq, int source) 101 /* poll all the triggered IRQs */
85{ 102 while (iqsr) {
86 frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493); 103 int irq;
87 frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source]; 104
105 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr));
106 irq = 31 - irq;
107 iqsr &= ~(1 << irq);
108
109 generic_handle_irq(IRQ_BASE_MB93493 + irq, regs);
110 }
111
112 return IRQ_HANDLED;
88} 113}
89 114
90void __init route_mb93493_irqs(void) 115/*
116 * define an interrupt action for each MB93493 PIC output
117 * - use dev_id to indicate the MB93493 PIC input to output mappings
118 */
119static struct irqaction mb93493_irq[2] = {
120 [0] = {
121 .handler = mb93493_interrupt,
122 .flags = IRQF_DISABLED | IRQF_SHARED,
123 .mask = CPU_MASK_NONE,
124 .name = "mb93493.0",
125 .dev_id = (void *) __addr_MB93493_IQSR(0),
126 },
127 [1] = {
128 .handler = mb93493_interrupt,
129 .flags = IRQF_DISABLED | IRQF_SHARED,
130 .mask = CPU_MASK_NONE,
131 .name = "mb93493.1",
132 .dev_id = (void *) __addr_MB93493_IQSR(1),
133 }
134};
135
136/*
137 * initialise the motherboard MB93493's PIC
138 */
139void __init mb93493_init(void)
91{ 140{
92 frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0); 141 int irq;
93 frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1); 142
94 143 for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
95 frv_irq_set_group(&frv_mb93493_irqs); 144 set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);
96 145
97 mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE); 146 /* the MB93493 drives external IRQ inputs on the CPU PIC */
98 mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE); 147 setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
99 mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE); 148 setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]);
100 mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE);
101 mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE);
102 mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE);
103 mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE);
104 mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE);
105 mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE);
106 mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE);
107} 149}
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
deleted file mode 100644
index 53886adf47de..000000000000
--- a/arch/frv/kernel/irq-routing.c
+++ /dev/null
@@ -1,291 +0,0 @@
1/* irq-routing.c: IRQ routing
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/sched.h>
13#include <linux/random.h>
14#include <linux/init.h>
15#include <linux/serial_reg.h>
16#include <asm/io.h>
17#include <asm/irq-routing.h>
18#include <asm/irc-regs.h>
19#include <asm/serial-regs.h>
20#include <asm/dma.h>
21
22struct irq_level frv_irq_levels[16] = {
23 [0 ... 15] = {
24 .lock = SPIN_LOCK_UNLOCKED,
25 }
26};
27
28struct irq_group *irq_groups[NR_IRQ_GROUPS];
29
30extern struct irq_group frv_cpu_irqs;
31
32void __init frv_irq_route(struct irq_source *source, int irqlevel)
33{
34 source->level = &frv_irq_levels[irqlevel];
35 source->next = frv_irq_levels[irqlevel].sources;
36 frv_irq_levels[irqlevel].sources = source;
37}
38
39void __init frv_irq_route_external(struct irq_source *source, int irq)
40{
41 int irqlevel = 0;
42
43 switch (irq) {
44 case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break;
45 case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break;
46 case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break;
47 case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break;
48 case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break;
49 case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break;
50 case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break;
51 case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break;
52 default: BUG();
53 }
54
55 source->level = &frv_irq_levels[irqlevel];
56 source->next = frv_irq_levels[irqlevel].sources;
57 frv_irq_levels[irqlevel].sources = source;
58}
59
60void __init frv_irq_set_group(struct irq_group *group)
61{
62 irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group;
63}
64
65void distribute_irqs(struct irq_group *group, unsigned long irqmask)
66{
67 struct irqaction *action;
68 int irq;
69
70 while (irqmask) {
71 asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask));
72 if (irq < 0 || irq > 31)
73 asm volatile("break");
74 irq = 31 - irq;
75
76 irqmask &= ~(1 << irq);
77 action = group->actions[irq];
78
79 irq += group->first_irq;
80
81 if (action) {
82 int status = 0;
83
84// if (!(action->flags & IRQF_DISABLED))
85// local_irq_enable();
86
87 do {
88 status |= action->flags;
89 action->handler(irq, action->dev_id, __frame);
90 action = action->next;
91 } while (action);
92
93 if (status & IRQF_SAMPLE_RANDOM)
94 add_interrupt_randomness(irq);
95 local_irq_disable();
96 }
97 }
98}
99
100/*****************************************************************************/
101/*
102 * CPU UART interrupts
103 */
104static void frv_cpuuart_doirq(struct irq_source *source)
105{
106// uint8_t iir = readb(source->muxdata + UART_IIR * 8);
107// if ((iir & 0x0f) != UART_IIR_NO_INT)
108 distribute_irqs(&frv_cpu_irqs, source->irqmask);
109}
110
111struct irq_source frv_cpuuart[2] = {
112#define __CPUUART(X, A) \
113 [X] = { \
114 .muxname = "uart", \
115 .muxdata = (volatile void __iomem *)(unsigned long)A,\
116 .irqmask = 1 << IRQ_CPU_UART##X, \
117 .doirq = frv_cpuuart_doirq, \
118 }
119
120 __CPUUART(0, UART0_BASE),
121 __CPUUART(1, UART1_BASE),
122};
123
124/*****************************************************************************/
125/*
126 * CPU DMA interrupts
127 */
128static void frv_cpudma_doirq(struct irq_source *source)
129{
130 uint32_t cstr = readl(source->muxdata + DMAC_CSTRx);
131 if (cstr & DMAC_CSTRx_INT)
132 distribute_irqs(&frv_cpu_irqs, source->irqmask);
133}
134
135struct irq_source frv_cpudma[8] = {
136#define __CPUDMA(X, A) \
137 [X] = { \
138 .muxname = "dma", \
139 .muxdata = (volatile void __iomem *)(unsigned long)A,\
140 .irqmask = 1 << IRQ_CPU_DMA##X, \
141 .doirq = frv_cpudma_doirq, \
142 }
143
144 __CPUDMA(0, 0xfe000900),
145 __CPUDMA(1, 0xfe000980),
146 __CPUDMA(2, 0xfe000a00),
147 __CPUDMA(3, 0xfe000a80),
148 __CPUDMA(4, 0xfe001000),
149 __CPUDMA(5, 0xfe001080),
150 __CPUDMA(6, 0xfe001100),
151 __CPUDMA(7, 0xfe001180),
152};
153
154/*****************************************************************************/
155/*
156 * CPU timer interrupts - can't tell whether they've generated an interrupt or not
157 */
158static void frv_cputimer_doirq(struct irq_source *source)
159{
160 distribute_irqs(&frv_cpu_irqs, source->irqmask);
161}
162
163struct irq_source frv_cputimer[3] = {
164#define __CPUTIMER(X) \
165 [X] = { \
166 .muxname = "timer", \
167 .muxdata = NULL, \
168 .irqmask = 1 << IRQ_CPU_TIMER##X, \
169 .doirq = frv_cputimer_doirq, \
170 }
171
172 __CPUTIMER(0),
173 __CPUTIMER(1),
174 __CPUTIMER(2),
175};
176
177/*****************************************************************************/
178/*
179 * external CPU interrupts - can't tell directly whether they've generated an interrupt or not
180 */
181static void frv_cpuexternal_doirq(struct irq_source *source)
182{
183 distribute_irqs(&frv_cpu_irqs, source->irqmask);
184}
185
186struct irq_source frv_cpuexternal[8] = {
187#define __CPUEXTERNAL(X) \
188 [X] = { \
189 .muxname = "ext", \
190 .muxdata = NULL, \
191 .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \
192 .doirq = frv_cpuexternal_doirq, \
193 }
194
195 __CPUEXTERNAL(0),
196 __CPUEXTERNAL(1),
197 __CPUEXTERNAL(2),
198 __CPUEXTERNAL(3),
199 __CPUEXTERNAL(4),
200 __CPUEXTERNAL(5),
201 __CPUEXTERNAL(6),
202 __CPUEXTERNAL(7),
203};
204
205#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
206
207struct irq_group frv_cpu_irqs = {
208 .sources = {
209 [IRQ_CPU_UART0] = &frv_cpuuart[0],
210 [IRQ_CPU_UART1] = &frv_cpuuart[1],
211 [IRQ_CPU_TIMER0] = &frv_cputimer[0],
212 [IRQ_CPU_TIMER1] = &frv_cputimer[1],
213 [IRQ_CPU_TIMER2] = &frv_cputimer[2],
214 [IRQ_CPU_DMA0] = &frv_cpudma[0],
215 [IRQ_CPU_DMA1] = &frv_cpudma[1],
216 [IRQ_CPU_DMA2] = &frv_cpudma[2],
217 [IRQ_CPU_DMA3] = &frv_cpudma[3],
218 [IRQ_CPU_DMA4] = &frv_cpudma[4],
219 [IRQ_CPU_DMA5] = &frv_cpudma[5],
220 [IRQ_CPU_DMA6] = &frv_cpudma[6],
221 [IRQ_CPU_DMA7] = &frv_cpudma[7],
222 [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0],
223 [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1],
224 [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2],
225 [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3],
226 [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4],
227 [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5],
228 [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6],
229 [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7],
230 },
231};
232
233/*****************************************************************************/
234/*
235 * route the CPU's interrupt sources
236 */
237void __init route_cpu_irqs(void)
238{
239 frv_irq_set_group(&frv_cpu_irqs);
240
241 __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */
242 __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */
243
244 /* route UART and error interrupts */
245 frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL);
246 frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL);
247
248 set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
249
250 /* route DMA channel interrupts */
251 frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL);
252 frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL);
253 frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL);
254 frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL);
255 frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL);
256 frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL);
257 frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL);
258 frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL);
259
260 set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL);
261 set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL);
262
263 /* route timer interrupts */
264 frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL);
265 frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL);
266 frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL);
267
268 set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
269
270 /* route external interrupts */
271 frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL);
272 frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL);
273 frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL);
274 frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL);
275 frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL);
276 frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL);
277 frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL);
278 frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL);
279
280 set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL);
281 set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL);
282
283#if defined(CONFIG_MB93091_VDK)
284 __set_TM1(0x55550000); /* XIRQ7-0 all active low */
285#elif defined(CONFIG_MB93093_PDK)
286 __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
287#else
288#error dont know external IRQ trigger levels for this setup
289#endif
290
291} /* end route_cpu_irqs() */
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 08967010be04..5ac041c7c0a4 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -1,6 +1,6 @@
1/* irq.c: FRV IRQ handling 1/* irq.c: FRV IRQ handling
2 * 2 *
3 * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -9,13 +9,6 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12/*
13 * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
14 *
15 * IRQs are in fact implemented a bit like signal handlers for the kernel.
16 * Naturally it's not a 1:1 relation, but there are similarities.
17 */
18
19#include <linux/ptrace.h> 12#include <linux/ptrace.h>
20#include <linux/errno.h> 13#include <linux/errno.h>
21#include <linux/signal.h> 14#include <linux/signal.h>
@@ -43,19 +36,16 @@
43#include <asm/delay.h> 36#include <asm/delay.h>
44#include <asm/irq.h> 37#include <asm/irq.h>
45#include <asm/irc-regs.h> 38#include <asm/irc-regs.h>
46#include <asm/irq-routing.h>
47#include <asm/gdb-stub.h> 39#include <asm/gdb-stub.h>
48 40
49extern void __init fpga_init(void); 41#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16))
50extern void __init route_mb93493_irqs(void);
51
52static void register_irq_proc (unsigned int irq);
53 42
54/* 43extern void __init fpga_init(void);
55 * Special irq handlers. 44#ifdef CONFIG_FUJITSU_MB93493
56 */ 45extern void __init mb93493_init(void);
46#endif
57 47
58irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; } 48#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR))
59 49
60atomic_t irq_err_count; 50atomic_t irq_err_count;
61 51
@@ -64,215 +54,86 @@ atomic_t irq_err_count;
64 */ 54 */
65int show_interrupts(struct seq_file *p, void *v) 55int show_interrupts(struct seq_file *p, void *v)
66{ 56{
67 struct irqaction *action; 57 int i = *(loff_t *) v, cpu;
68 struct irq_group *group; 58 struct irqaction * action;
69 unsigned long flags; 59 unsigned long flags;
70 int level, grp, ix, i, j;
71
72 i = *(loff_t *) v;
73
74 switch (i) {
75 case 0:
76 seq_printf(p, " ");
77 for_each_online_cpu(j)
78 seq_printf(p, "CPU%d ",j);
79
80 seq_putc(p, '\n');
81 break;
82 60
83 case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP: 61 if (i == 0) {
84 local_irq_save(flags); 62 char cpuname[12];
85
86 grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP;
87 group = irq_groups[grp];
88 if (!group)
89 goto skip;
90
91 ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP;
92 action = group->actions[ix];
93 if (!action)
94 goto skip;
95
96 seq_printf(p, "%3d: ", i - 1);
97
98#ifndef CONFIG_SMP
99 seq_printf(p, "%10u ", kstat_irqs(i));
100#else
101 for_each_online_cpu(j)
102 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]);
103#endif
104
105 level = group->sources[ix]->level - frv_irq_levels;
106
107 seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level);
108 seq_printf(p, " %s", action->name);
109
110 for (action = action->next; action; action = action->next)
111 seq_printf(p, ", %s", action->name);
112 63
64 seq_printf(p, " ");
65 for_each_present_cpu(cpu) {
66 sprintf(cpuname, "CPU%d", cpu);
67 seq_printf(p, " %10s", cpuname);
68 }
113 seq_putc(p, '\n'); 69 seq_putc(p, '\n');
114skip: 70 }
115 local_irq_restore(flags);
116 break;
117 71
118 case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1: 72 if (i < NR_IRQS) {
119 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 73 spin_lock_irqsave(&irq_desc[i].lock, flags);
120 break; 74 action = irq_desc[i].action;
75 if (action) {
76 seq_printf(p, "%3d: ", i);
77 for_each_present_cpu(cpu)
78 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
79 seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
80 seq_printf(p, " %s", action->name);
81 for (action = action->next;
82 action;
83 action = action->next)
84 seq_printf(p, ", %s", action->name);
85
86 seq_putc(p, '\n');
87 }
121 88
122 default: 89 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
123 break; 90 } else if (i == NR_IRQS) {
91 seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
124 } 92 }
125 93
126 return 0; 94 return 0;
127} 95}
128 96
129
130/* 97/*
131 * Generic enable/disable code: this just calls 98 * on-CPU PIC operations
132 * down into the PIC-specific version for the actual
133 * hardware disable after having gotten the irq
134 * controller lock.
135 */ 99 */
136 100static void frv_cpupic_ack(unsigned int irqlevel)
137/**
138 * disable_irq_nosync - disable an irq without waiting
139 * @irq: Interrupt to disable
140 *
141 * Disable the selected interrupt line. Disables and Enables are
142 * nested.
143 * Unlike disable_irq(), this function does not ensure existing
144 * instances of the IRQ handler have completed before returning.
145 *
146 * This function may be called from IRQ context.
147 */
148
149void disable_irq_nosync(unsigned int irq)
150{ 101{
151 struct irq_source *source; 102 __clr_RC(irqlevel);
152 struct irq_group *group; 103 __clr_IRL();
153 struct irq_level *level;
154 unsigned long flags;
155 int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
156
157 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
158 if (!group)
159 BUG();
160
161 source = group->sources[idx];
162 if (!source)
163 BUG();
164
165 level = source->level;
166
167 spin_lock_irqsave(&level->lock, flags);
168
169 if (group->control) {
170 if (!group->disable_cnt[idx]++)
171 group->control(group, idx, 0);
172 } else if (!level->disable_count++) {
173 __set_MASK(level - frv_irq_levels);
174 }
175
176 spin_unlock_irqrestore(&level->lock, flags);
177} 104}
178 105
179EXPORT_SYMBOL(disable_irq_nosync); 106static void frv_cpupic_mask(unsigned int irqlevel)
180
181/**
182 * disable_irq - disable an irq and wait for completion
183 * @irq: Interrupt to disable
184 *
185 * Disable the selected interrupt line. Enables and Disables are
186 * nested.
187 * This function waits for any pending IRQ handlers for this interrupt
188 * to complete before returning. If you use this function while
189 * holding a resource the IRQ handler may need you will deadlock.
190 *
191 * This function may be called - with care - from IRQ context.
192 */
193
194void disable_irq(unsigned int irq)
195{ 107{
196 disable_irq_nosync(irq); 108 __set_MASK(irqlevel);
197
198#ifdef CONFIG_SMP
199 if (!local_irq_count(smp_processor_id())) {
200 do {
201 barrier();
202 } while (irq_desc[irq].status & IRQ_INPROGRESS);
203 }
204#endif
205} 109}
206 110
207EXPORT_SYMBOL(disable_irq); 111static void frv_cpupic_mask_ack(unsigned int irqlevel)
208
209/**
210 * enable_irq - enable handling of an irq
211 * @irq: Interrupt to enable
212 *
213 * Undoes the effect of one call to disable_irq(). If this
214 * matches the last disable, processing of interrupts on this
215 * IRQ line is re-enabled.
216 *
217 * This function may be called from IRQ context.
218 */
219
220void enable_irq(unsigned int irq)
221{ 112{
222 struct irq_source *source; 113 __set_MASK(irqlevel);
223 struct irq_group *group; 114 __clr_RC(irqlevel);
224 struct irq_level *level; 115 __clr_IRL();
225 unsigned long flags; 116}
226 int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1);
227 int count;
228
229 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
230 if (!group)
231 BUG();
232
233 source = group->sources[idx];
234 if (!source)
235 BUG();
236
237 level = source->level;
238
239 spin_lock_irqsave(&level->lock, flags);
240
241 if (group->control)
242 count = group->disable_cnt[idx];
243 else
244 count = level->disable_count;
245
246 switch (count) {
247 case 1:
248 if (group->control) {
249 if (group->actions[idx])
250 group->control(group, idx, 1);
251 } else {
252 if (level->usage)
253 __clr_MASK(level - frv_irq_levels);
254 }
255 /* fall-through */
256
257 default:
258 count--;
259 break;
260
261 case 0:
262 printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0));
263 }
264 117
265 if (group->control) 118static void frv_cpupic_unmask(unsigned int irqlevel)
266 group->disable_cnt[idx] = count; 119{
267 else 120 __clr_MASK(irqlevel);
268 level->disable_count = count; 121}
269 122
270 spin_unlock_irqrestore(&level->lock, flags); 123static void frv_cpupic_end(unsigned int irqlevel)
124{
125 __clr_MASK(irqlevel);
271} 126}
272 127
273EXPORT_SYMBOL(enable_irq); 128static struct irq_chip frv_cpu_pic = {
129 .name = "cpu",
130 .ack = frv_cpupic_ack,
131 .mask = frv_cpupic_mask,
132 .mask_ack = frv_cpupic_mask_ack,
133 .unmask = frv_cpupic_unmask,
134 .end = frv_cpupic_end,
135};
274 136
275/*****************************************************************************/
276/* 137/*
277 * handles all normal device IRQ's 138 * handles all normal device IRQ's
278 * - registers are referred to by the __frame variable (GR28) 139 * - registers are referred to by the __frame variable (GR28)
@@ -281,463 +142,65 @@ EXPORT_SYMBOL(enable_irq);
281 */ 142 */
282asmlinkage void do_IRQ(void) 143asmlinkage void do_IRQ(void)
283{ 144{
284 struct irq_source *source;
285 int level, cpu;
286
287 irq_enter(); 145 irq_enter();
288 146 generic_handle_irq(__get_IRL(), __frame);
289 level = (__frame->tbr >> 4) & 0xf;
290 cpu = smp_processor_id();
291
292 if ((unsigned long) __frame - (unsigned long) (current + 1) < 512)
293 BUG();
294
295 __set_MASK(level);
296 __clr_RC(level);
297 __clr_IRL();
298
299 kstat_this_cpu.irqs[level]++;
300
301 for (source = frv_irq_levels[level].sources; source; source = source->next)
302 source->doirq(source);
303
304 __clr_MASK(level);
305
306 irq_exit(); 147 irq_exit();
148}
307 149
308} /* end do_IRQ() */
309
310/*****************************************************************************/
311/* 150/*
312 * handles all NMIs when not co-opted by the debugger 151 * handles all NMIs when not co-opted by the debugger
313 * - registers are referred to by the __frame variable (GR28) 152 * - registers are referred to by the __frame variable (GR28)
314 */ 153 */
315asmlinkage void do_NMI(void) 154asmlinkage void do_NMI(void)
316{ 155{
317} /* end do_NMI() */
318
319/*****************************************************************************/
320/**
321 * request_irq - allocate an interrupt line
322 * @irq: Interrupt line to allocate
323 * @handler: Function to be called when the IRQ occurs
324 * @irqflags: Interrupt type flags
325 * @devname: An ascii name for the claiming device
326 * @dev_id: A cookie passed back to the handler function
327 *
328 * This call allocates interrupt resources and enables the
329 * interrupt line and IRQ handling. From the point this
330 * call is made your handler function may be invoked. Since
331 * your handler function must clear any interrupt the board
332 * raises, you must take care both to initialise your hardware
333 * and to set up the interrupt handler in the right order.
334 *
335 * Dev_id must be globally unique. Normally the address of the
336 * device data structure is used as the cookie. Since the handler
337 * receives this value it makes sense to use it.
338 *
339 * If your interrupt is shared you must pass a non NULL dev_id
340 * as this is required when freeing the interrupt.
341 *
342 * Flags:
343 *
344 * IRQF_SHARED Interrupt is shared
345 *
346 * IRQF_DISABLED Disable local interrupts while processing
347 *
348 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
349 *
350 */
351
352int request_irq(unsigned int irq,
353 irqreturn_t (*handler)(int, void *, struct pt_regs *),
354 unsigned long irqflags,
355 const char * devname,
356 void *dev_id)
357{
358 int retval;
359 struct irqaction *action;
360
361#if 1
362 /*
363 * Sanity-check: shared interrupts should REALLY pass in
364 * a real dev-ID, otherwise we'll have trouble later trying
365 * to figure out which interrupt is which (messes up the
366 * interrupt freeing logic etc).
367 */
368 if (irqflags & IRQF_SHARED) {
369 if (!dev_id)
370 printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n",
371 devname, (&irq)[-1]);
372 }
373#endif
374
375 if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
376 return -EINVAL;
377 if (!handler)
378 return -EINVAL;
379
380 action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
381 if (!action)
382 return -ENOMEM;
383
384 action->handler = handler;
385 action->flags = irqflags;
386 action->mask = CPU_MASK_NONE;
387 action->name = devname;
388 action->next = NULL;
389 action->dev_id = dev_id;
390
391 retval = setup_irq(irq, action);
392 if (retval)
393 kfree(action);
394 return retval;
395}
396
397EXPORT_SYMBOL(request_irq);
398
399/**
400 * free_irq - free an interrupt
401 * @irq: Interrupt line to free
402 * @dev_id: Device identity to free
403 *
404 * Remove an interrupt handler. The handler is removed and if the
405 * interrupt line is no longer in use by any driver it is disabled.
406 * On a shared IRQ the caller must ensure the interrupt is disabled
407 * on the card it drives before calling this function. The function
408 * does not return until any executing interrupts for this IRQ
409 * have completed.
410 *
411 * This function may be called from interrupt context.
412 *
413 * Bugs: Attempting to free an irq in a handler for the same irq hangs
414 * the machine.
415 */
416
417void free_irq(unsigned int irq, void *dev_id)
418{
419 struct irq_source *source;
420 struct irq_group *group;
421 struct irq_level *level;
422 struct irqaction **p, **pp;
423 unsigned long flags;
424
425 if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS)
426 return;
427
428 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
429 if (!group)
430 BUG();
431
432 source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
433 if (!source)
434 BUG();
435
436 level = source->level;
437 p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
438
439 spin_lock_irqsave(&level->lock, flags);
440
441 for (pp = p; *pp; pp = &(*pp)->next) {
442 struct irqaction *action = *pp;
443
444 if (action->dev_id != dev_id)
445 continue;
446
447 /* found it - remove from the list of entries */
448 *pp = action->next;
449
450 level->usage--;
451
452 if (p == pp && group->control)
453 group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0);
454
455 if (level->usage == 0)
456 __set_MASK(level - frv_irq_levels);
457
458 spin_unlock_irqrestore(&level->lock,flags);
459
460#ifdef CONFIG_SMP
461 /* Wait to make sure it's not being used on another CPU */
462 while (desc->status & IRQ_INPROGRESS)
463 barrier();
464#endif
465 kfree(action);
466 return;
467 }
468}
469
470EXPORT_SYMBOL(free_irq);
471
472/*
473 * IRQ autodetection code..
474 *
475 * This depends on the fact that any interrupt that comes in on to an
476 * unassigned IRQ will cause GxICR_DETECT to be set
477 */
478
479static DECLARE_MUTEX(probe_sem);
480
481/**
482 * probe_irq_on - begin an interrupt autodetect
483 *
484 * Commence probing for an interrupt. The interrupts are scanned
485 * and a mask of potential interrupt lines is returned.
486 *
487 */
488
489unsigned long probe_irq_on(void)
490{
491 down(&probe_sem);
492 return 0;
493} 156}
494 157
495EXPORT_SYMBOL(probe_irq_on);
496
497/* 158/*
498 * Return a mask of triggered interrupts (this 159 * initialise the interrupt system
499 * can handle only legacy ISA interrupts).
500 */
501
502/**
503 * probe_irq_mask - scan a bitmap of interrupt lines
504 * @val: mask of interrupts to consider
505 *
506 * Scan the ISA bus interrupt lines and return a bitmap of
507 * active interrupts. The interrupt probe logic state is then
508 * returned to its previous value.
509 *
510 * Note: we need to scan all the irq's even though we will
511 * only return ISA irq numbers - just so that we reset them
512 * all to a known state.
513 */
514unsigned int probe_irq_mask(unsigned long xmask)
515{
516 up(&probe_sem);
517 return 0;
518}
519
520EXPORT_SYMBOL(probe_irq_mask);
521
522/*
523 * Return the one interrupt that triggered (this can
524 * handle any interrupt source).
525 */
526
527/**
528 * probe_irq_off - end an interrupt autodetect
529 * @xmask: mask of potential interrupts (unused)
530 *
531 * Scans the unused interrupt lines and returns the line which
532 * appears to have triggered the interrupt. If no interrupt was
533 * found then zero is returned. If more than one interrupt is
534 * found then minus the first candidate is returned to indicate
535 * their is doubt.
536 *
537 * The interrupt probe logic state is returned to its previous
538 * value.
539 *
540 * BUGS: When used in a module (which arguably shouldnt happen)
541 * nothing prevents two IRQ probe callers from overlapping. The
542 * results of this are non-optimal.
543 */ 160 */
544 161void __init init_IRQ(void)
545int probe_irq_off(unsigned long xmask)
546{
547 up(&probe_sem);
548 return -1;
549}
550
551EXPORT_SYMBOL(probe_irq_off);
552
553/* this was setup_x86_irq but it seems pretty generic */
554int setup_irq(unsigned int irq, struct irqaction *new)
555{
556 struct irq_source *source;
557 struct irq_group *group;
558 struct irq_level *level;
559 struct irqaction **p, **pp;
560 unsigned long flags;
561
562 group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP];
563 if (!group)
564 BUG();
565
566 source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
567 if (!source)
568 BUG();
569
570 level = source->level;
571
572 p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)];
573
574 /*
575 * Some drivers like serial.c use request_irq() heavily,
576 * so we have to be careful not to interfere with a
577 * running system.
578 */
579 if (new->flags & IRQF_SAMPLE_RANDOM) {
580 /*
581 * This function might sleep, we want to call it first,
582 * outside of the atomic block.
583 * Yes, this might clear the entropy pool if the wrong
584 * driver is attempted to be loaded, without actually
585 * installing a new handler, but is this really a problem,
586 * only the sysadmin is able to do this.
587 */
588 rand_initialize_irq(irq);
589 }
590
591 /* must juggle the interrupt processing stuff with interrupts disabled */
592 spin_lock_irqsave(&level->lock, flags);
593
594 /* can't share interrupts unless all parties agree to */
595 if (level->usage != 0 && !(level->flags & new->flags & IRQF_SHARED)) {
596 spin_unlock_irqrestore(&level->lock,flags);
597 return -EBUSY;
598 }
599
600 /* add new interrupt at end of irq queue */
601 pp = p;
602 while (*pp)
603 pp = &(*pp)->next;
604
605 *pp = new;
606
607 level->usage++;
608 level->flags = new->flags;
609
610 /* turn the interrupts on */
611 if (level->usage == 1)
612 __clr_MASK(level - frv_irq_levels);
613
614 if (p == pp && group->control)
615 group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1);
616
617 spin_unlock_irqrestore(&level->lock, flags);
618 register_irq_proc(irq);
619 return 0;
620}
621
622static struct proc_dir_entry * root_irq_dir;
623static struct proc_dir_entry * irq_dir [NR_IRQS];
624
625#define HEX_DIGITS 8
626
627static unsigned int parse_hex_value (const char __user *buffer,
628 unsigned long count, unsigned long *ret)
629{
630 unsigned char hexnum [HEX_DIGITS];
631 unsigned long value;
632 int i;
633
634 if (!count)
635 return -EINVAL;
636 if (count > HEX_DIGITS)
637 count = HEX_DIGITS;
638 if (copy_from_user(hexnum, buffer, count))
639 return -EFAULT;
640
641 /*
642 * Parse the first 8 characters as a hex string, any non-hex char
643 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
644 */
645 value = 0;
646
647 for (i = 0; i < count; i++) {
648 unsigned int c = hexnum[i];
649
650 switch (c) {
651 case '0' ... '9': c -= '0'; break;
652 case 'a' ... 'f': c -= 'a'-10; break;
653 case 'A' ... 'F': c -= 'A'-10; break;
654 default:
655 goto out;
656 }
657 value = (value << 4) | c;
658 }
659out:
660 *ret = value;
661 return 0;
662}
663
664
665static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
666 int count, int *eof, void *data)
667{
668 unsigned long *mask = (unsigned long *) data;
669 if (count < HEX_DIGITS+1)
670 return -EINVAL;
671 return sprintf (page, "%08lx\n", *mask);
672}
673
674static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
675 unsigned long count, void *data)
676{
677 unsigned long *mask = (unsigned long *) data, full_count = count, err;
678 unsigned long new_value;
679
680 show_state();
681 err = parse_hex_value(buffer, count, &new_value);
682 if (err)
683 return err;
684
685 *mask = new_value;
686 return full_count;
687}
688
689#define MAX_NAMELEN 10
690
691static void register_irq_proc (unsigned int irq)
692{
693 char name [MAX_NAMELEN];
694
695 if (!root_irq_dir || irq_dir[irq])
696 return;
697
698 memset(name, 0, MAX_NAMELEN);
699 sprintf(name, "%d", irq);
700
701 /* create /proc/irq/1234 */
702 irq_dir[irq] = proc_mkdir(name, root_irq_dir);
703}
704
705unsigned long prof_cpu_mask = -1;
706
707void init_irq_proc (void)
708{ 162{
709 struct proc_dir_entry *entry; 163 int level;
710 int i;
711 164
712 /* create /proc/irq */ 165 for (level = 1; level <= 14; level++)
713 root_irq_dir = proc_mkdir("irq", NULL); 166 set_irq_chip_and_handler(level, &frv_cpu_pic,
167 handle_level_irq);
714 168
715 /* create /proc/irq/prof_cpu_mask */ 169 set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
716 entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
717 if (!entry)
718 return;
719 170
720 entry->nlink = 1; 171 /* set the trigger levels for internal interrupt sources
721 entry->data = (void *)&prof_cpu_mask; 172 * - timers all falling-edge
722 entry->read_proc = prof_cpu_mask_read_proc; 173 * - ERR0 is rising-edge
723 entry->write_proc = prof_cpu_mask_write_proc; 174 * - all others are high-level
724
725 /*
726 * Create entries for all existing IRQs.
727 */ 175 */
728 for (i = 0; i < NR_IRQS; i++) 176 __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */
729 register_irq_proc(i); 177 __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */
730} 178
179 /* route internal interrupts */
180 set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL,
181 IRQ_DMA0_LEVEL);
182 set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL);
183 set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL,
184 IRQ_UART1_LEVEL, IRQ_UART0_LEVEL);
185 set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL,
186 IRQ_DMA4_LEVEL);
187
188 /* route external interrupts */
189 set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL,
190 IRQ_XIRQ4_LEVEL);
191 set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL,
192 IRQ_XIRQ0_LEVEL);
193
194#if defined(CONFIG_MB93091_VDK)
195 __set_TM1(0x55550000); /* XIRQ7-0 all active low */
196#elif defined(CONFIG_MB93093_PDK)
197 __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */
198#else
199#error dont know external IRQ trigger levels for this setup
200#endif
731 201
732/*****************************************************************************/
733/*
734 * initialise the interrupt system
735 */
736void __init init_IRQ(void)
737{
738 route_cpu_irqs();
739 fpga_init(); 202 fpga_init();
740#ifdef CONFIG_FUJITSU_MB93493 203#ifdef CONFIG_FUJITSU_MB93493
741 route_mb93493_irqs(); 204 mb93493_init();
742#endif 205#endif
743} /* end init_IRQ() */ 206}
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index af08ccd4ed6e..d96a57e5f030 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -43,7 +43,6 @@
43#include <asm/mb-regs.h> 43#include <asm/mb-regs.h>
44#include <asm/mb93493-regs.h> 44#include <asm/mb93493-regs.h>
45#include <asm/gdb-stub.h> 45#include <asm/gdb-stub.h>
46#include <asm/irq-routing.h>
47#include <asm/io.h> 46#include <asm/io.h>
48 47
49#ifdef CONFIG_BLK_DEV_INITRD 48#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 68a77fe3bb40..3d0284bccb94 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -26,7 +26,6 @@
26#include <asm/timer-regs.h> 26#include <asm/timer-regs.h>
27#include <asm/mb-regs.h> 27#include <asm/mb-regs.h>
28#include <asm/mb86943a.h> 28#include <asm/mb86943a.h>
29#include <asm/irq-routing.h>
30 29
31#include <linux/timex.h> 30#include <linux/timex.h>
32 31
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 2278c80bd88c..ba587523c015 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -15,7 +15,6 @@
15 15
16#include <asm/io.h> 16#include <asm/io.h>
17#include <asm/smp.h> 17#include <asm/smp.h>
18#include <asm/irq-routing.h>
19 18
20#include "pci-frv.h" 19#include "pci-frv.h"
21 20
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index b5b4286f9dd4..3f3a0ed3539b 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -98,7 +98,7 @@ void show_mem(void)
98 */ 98 */
99void __init paging_init(void) 99void __init paging_init(void)
100{ 100{
101 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 101 unsigned long zones_size[MAX_NR_ZONES] = {0, };
102 102
103 /* allocate some pages for kernel housekeeping tasks */ 103 /* allocate some pages for kernel housekeeping tasks */
104 empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); 104 empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
index d3d40bdc2d6a..e4f4199f97ab 100644
--- a/arch/h8300/mm/init.c
+++ b/arch/h8300/mm/init.c
@@ -138,7 +138,7 @@ void paging_init(void)
138#endif 138#endif
139 139
140 { 140 {
141 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 141 unsigned long zones_size[MAX_NR_ZONES] = {0, };
142 142
143 zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT; 143 zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
144 zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; 144 zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b2751eadbc56..6189b0c28d6f 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -494,7 +494,7 @@ config HIGHMEM64G
494endchoice 494endchoice
495 495
496choice 496choice
497 depends on EXPERIMENTAL && !X86_PAE 497 depends on EXPERIMENTAL
498 prompt "Memory split" if EMBEDDED 498 prompt "Memory split" if EMBEDDED
499 default VMSPLIT_3G 499 default VMSPLIT_3G
500 help 500 help
@@ -516,6 +516,7 @@ choice
516 config VMSPLIT_3G 516 config VMSPLIT_3G
517 bool "3G/1G user/kernel split" 517 bool "3G/1G user/kernel split"
518 config VMSPLIT_3G_OPT 518 config VMSPLIT_3G_OPT
519 depends on !HIGHMEM
519 bool "3G/1G user/kernel split (for full 1G low memory)" 520 bool "3G/1G user/kernel split (for full 1G low memory)"
520 config VMSPLIT_2G 521 config VMSPLIT_2G
521 bool "2G/2G user/kernel split" 522 bool "2G/2G user/kernel split"
@@ -794,6 +795,7 @@ config HOTPLUG_CPU
794config COMPAT_VDSO 795config COMPAT_VDSO
795 bool "Compat VDSO support" 796 bool "Compat VDSO support"
796 default y 797 default y
798 depends on !PARAVIRT
797 help 799 help
798 Map the VDSO to the predictable old-style address too. 800 Map the VDSO to the predictable old-style address too.
799 ---help--- 801 ---help---
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 8591f2fa920c..ff9ce4b5eaa8 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1154,9 +1154,11 @@ out:
1154 1154
1155static void set_time(void) 1155static void set_time(void)
1156{ 1156{
1157 struct timespec ts;
1157 if (got_clock_diff) { /* Must know time zone in order to set clock */ 1158 if (got_clock_diff) { /* Must know time zone in order to set clock */
1158 xtime.tv_sec = get_cmos_time() + clock_cmos_diff; 1159 ts.tv_sec = get_cmos_time() + clock_cmos_diff;
1159 xtime.tv_nsec = 0; 1160 ts.tv_nsec = 0;
1161 do_settimeofday(&ts);
1160 } 1162 }
1161} 1163}
1162 1164
@@ -1232,13 +1234,8 @@ static int suspend(int vetoable)
1232 restore_processor_state(); 1234 restore_processor_state();
1233 1235
1234 local_irq_disable(); 1236 local_irq_disable();
1235 write_seqlock(&xtime_lock);
1236 spin_lock(&i8253_lock);
1237 reinit_timer();
1238 set_time(); 1237 set_time();
1239 1238 reinit_timer();
1240 spin_unlock(&i8253_lock);
1241 write_sequnlock(&xtime_lock);
1242 1239
1243 if (err == APM_NO_ERROR) 1240 if (err == APM_NO_ERROR)
1244 err = APM_SUCCESS; 1241 err = APM_SUCCESS;
@@ -1365,9 +1362,7 @@ static void check_events(void)
1365 ignore_bounce = 1; 1362 ignore_bounce = 1;
1366 if ((event != APM_NORMAL_RESUME) 1363 if ((event != APM_NORMAL_RESUME)
1367 || (ignore_normal_resume == 0)) { 1364 || (ignore_normal_resume == 0)) {
1368 write_seqlock_irq(&xtime_lock);
1369 set_time(); 1365 set_time();
1370 write_sequnlock_irq(&xtime_lock);
1371 device_resume(); 1366 device_resume();
1372 pm_send_all(PM_RESUME, (void *)0); 1367 pm_send_all(PM_RESUME, (void *)0);
1373 queue_event(event, NULL); 1368 queue_event(event, NULL);
@@ -1383,9 +1378,7 @@ static void check_events(void)
1383 break; 1378 break;
1384 1379
1385 case APM_UPDATE_TIME: 1380 case APM_UPDATE_TIME:
1386 write_seqlock_irq(&xtime_lock);
1387 set_time(); 1381 set_time();
1388 write_sequnlock_irq(&xtime_lock);
1389 break; 1382 break;
1390 1383
1391 case APM_CRITICAL_SUSPEND: 1384 case APM_CRITICAL_SUSPEND:
@@ -2339,6 +2332,7 @@ static int __init apm_init(void)
2339 ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD); 2332 ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
2340 if (ret < 0) { 2333 if (ret < 0) {
2341 printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n"); 2334 printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
2335 remove_proc_entry("apm", NULL);
2342 return -ENOMEM; 2336 return -ENOMEM;
2343 } 2337 }
2344 2338
@@ -2348,7 +2342,13 @@ static int __init apm_init(void)
2348 return 0; 2342 return 0;
2349 } 2343 }
2350 2344
2351 misc_register(&apm_device); 2345 /*
2346 * Note we don't actually care if the misc_device cannot be registered.
2347 * this driver can do its job without it, even if userspace can't
2348 * control it. just log the error
2349 */
2350 if (misc_register(&apm_device))
2351 printk(KERN_WARNING "apm: Could not register misc device.\n");
2352 2352
2353 if (HZ != 100) 2353 if (HZ != 100)
2354 idle_period = (idle_period * HZ) / 100; 2354 idle_period = (idle_period * HZ) / 100;
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index 169ac8e0db68..0b61eed8bbd8 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -243,7 +243,7 @@ static DEFINE_SPINLOCK(set_atomicity_lock);
243 * has been called. 243 * has been called.
244 */ 244 */
245 245
246static void prepare_set(void) 246static void prepare_set(void) __acquires(set_atomicity_lock)
247{ 247{
248 unsigned long cr0; 248 unsigned long cr0;
249 249
@@ -274,7 +274,7 @@ static void prepare_set(void)
274 mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); 274 mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
275} 275}
276 276
277static void post_set(void) 277static void post_set(void) __releases(set_atomicity_lock)
278{ 278{
279 /* Flush TLBs (no need to flush caches - they are disabled) */ 279 /* Flush TLBs (no need to flush caches - they are disabled) */
280 __flush_tlb(); 280 __flush_tlb();
diff --git a/arch/i386/kernel/efi_stub.S b/arch/i386/kernel/efi_stub.S
index d3ee73a3eee3..ef00bb77d7e4 100644
--- a/arch/i386/kernel/efi_stub.S
+++ b/arch/i386/kernel/efi_stub.S
@@ -7,7 +7,6 @@
7 7
8#include <linux/linkage.h> 8#include <linux/linkage.h>
9#include <asm/page.h> 9#include <asm/page.h>
10#include <asm/pgtable.h>
11 10
12/* 11/*
13 * efi_call_phys(void *, ...) is a function with variable parameters. 12 * efi_call_phys(void *, ...) is a function with variable parameters.
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 54cfeabbc5e4..84278e0093a2 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -145,14 +145,10 @@ real_mode_gdt_entries [3] =
145 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ 145 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
146}; 146};
147 147
148static struct 148static struct Xgt_desc_struct
149{ 149real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
150 unsigned short size __attribute__ ((packed)); 150real_mode_idt = { 0x3ff, 0 },
151 unsigned long long * base __attribute__ ((packed)); 151no_idt = { 0, 0 };
152}
153real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
154real_mode_idt = { 0x3ff, NULL },
155no_idt = { 0, NULL };
156 152
157 153
158/* This is 16-bit protected mode code to disable paging and the cache, 154/* This is 16-bit protected mode code to disable paging and the cache,
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f1682206d304..16d99444cf66 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -53,6 +53,7 @@
53#include <asm/apic.h> 53#include <asm/apic.h>
54#include <asm/e820.h> 54#include <asm/e820.h>
55#include <asm/mpspec.h> 55#include <asm/mpspec.h>
56#include <asm/mmzone.h>
56#include <asm/setup.h> 57#include <asm/setup.h>
57#include <asm/arch_hooks.h> 58#include <asm/arch_hooks.h>
58#include <asm/sections.h> 59#include <asm/sections.h>
@@ -934,6 +935,24 @@ static void __init parse_cmdline_early (char ** cmdline_p)
934} 935}
935 936
936/* 937/*
938 * reservetop=size reserves a hole at the top of the kernel address space which
939 * a hypervisor can load into later. Needed for dynamically loaded hypervisors,
940 * so relocating the fixmap can be done before paging initialization.
941 */
942static int __init parse_reservetop(char *arg)
943{
944 unsigned long address;
945
946 if (!arg)
947 return -EINVAL;
948
949 address = memparse(arg, &arg);
950 reserve_top_address(address);
951 return 0;
952}
953early_param("reservetop", parse_reservetop);
954
955/*
937 * Callback for efi_memory_walk. 956 * Callback for efi_memory_walk.
938 */ 957 */
939static int __init 958static int __init
@@ -1181,7 +1200,7 @@ static unsigned long __init setup_memory(void)
1181 1200
1182void __init zone_sizes_init(void) 1201void __init zone_sizes_init(void)
1183{ 1202{
1184 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 1203 unsigned long zones_size[MAX_NR_ZONES] = { 0, };
1185 unsigned int max_dma, low; 1204 unsigned int max_dma, low;
1186 1205
1187 max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; 1206 max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
@@ -1258,7 +1277,7 @@ void __init setup_bootmem_allocator(void)
1258 */ 1277 */
1259 find_smp_config(); 1278 find_smp_config();
1260#endif 1279#endif
1261 1280 numa_kva_reserve();
1262#ifdef CONFIG_BLK_DEV_INITRD 1281#ifdef CONFIG_BLK_DEV_INITRD
1263 if (LOADER_TYPE && INITRD_START) { 1282 if (LOADER_TYPE && INITRD_START) {
1264 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { 1283 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index c10789d7a9d3..465188e2d701 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -634,3 +634,69 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
634 } 634 }
635} 635}
636 636
637/*
638 * this function sends a 'generic call function' IPI to one other CPU
639 * in the system.
640 *
641 * cpu is a standard Linux logical CPU number.
642 */
643static void
644__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
645 int nonatomic, int wait)
646{
647 struct call_data_struct data;
648 int cpus = 1;
649
650 data.func = func;
651 data.info = info;
652 atomic_set(&data.started, 0);
653 data.wait = wait;
654 if (wait)
655 atomic_set(&data.finished, 0);
656
657 call_data = &data;
658 wmb();
659 /* Send a message to all other CPUs and wait for them to respond */
660 send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
661
662 /* Wait for response */
663 while (atomic_read(&data.started) != cpus)
664 cpu_relax();
665
666 if (!wait)
667 return;
668
669 while (atomic_read(&data.finished) != cpus)
670 cpu_relax();
671}
672
673/*
674 * smp_call_function_single - Run a function on another CPU
675 * @func: The function to run. This must be fast and non-blocking.
676 * @info: An arbitrary pointer to pass to the function.
677 * @nonatomic: Currently unused.
678 * @wait: If true, wait until function has completed on other CPUs.
679 *
680 * Retrurns 0 on success, else a negative status code.
681 *
682 * Does not return until the remote CPU is nearly ready to execute <func>
683 * or is or has executed.
684 */
685
686int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
687 int nonatomic, int wait)
688{
689 /* prevent preemption and reschedule on another processor */
690 int me = get_cpu();
691 if (cpu == me) {
692 WARN_ON(1);
693 put_cpu();
694 return -EBUSY;
695 }
696 spin_lock_bh(&call_lock);
697 __smp_call_function_single(cpu, func, info, nonatomic, wait);
698 spin_unlock_bh(&call_lock);
699 put_cpu();
700 return 0;
701}
702EXPORT_SYMBOL(smp_call_function_single);
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index b1809c9a0899..83db411b3aa7 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -42,7 +42,7 @@
42#define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) 42#define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8)
43static u8 pxm_bitmap[PXM_BITMAP_LEN]; /* bitmap of proximity domains */ 43static u8 pxm_bitmap[PXM_BITMAP_LEN]; /* bitmap of proximity domains */
44 44
45#define MAX_CHUNKS_PER_NODE 4 45#define MAX_CHUNKS_PER_NODE 3
46#define MAXCHUNKS (MAX_CHUNKS_PER_NODE * MAX_NUMNODES) 46#define MAXCHUNKS (MAX_CHUNKS_PER_NODE * MAX_NUMNODES)
47struct node_memory_chunk_s { 47struct node_memory_chunk_s {
48 unsigned long start_pfn; 48 unsigned long start_pfn;
@@ -135,9 +135,6 @@ static void __init parse_memory_affinity_structure (char *sratp)
135 "enabled and removable" : "enabled" ) ); 135 "enabled and removable" : "enabled" ) );
136} 136}
137 137
138#if MAX_NR_ZONES != 4
139#error "MAX_NR_ZONES != 4, chunk_to_zone requires review"
140#endif
141/* Take a chunk of pages from page frame cstart to cend and count the number 138/* Take a chunk of pages from page frame cstart to cend and count the number
142 * of pages in each zone, returned via zones[]. 139 * of pages in each zone, returned via zones[].
143 */ 140 */
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index edd00f6cee37..1302e4ab3c4f 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -270,16 +270,19 @@ void notify_arch_cmos_timer(void)
270 mod_timer(&sync_cmos_timer, jiffies + 1); 270 mod_timer(&sync_cmos_timer, jiffies + 1);
271} 271}
272 272
273static long clock_cmos_diff, sleep_start; 273static long clock_cmos_diff;
274static unsigned long sleep_start;
274 275
275static int timer_suspend(struct sys_device *dev, pm_message_t state) 276static int timer_suspend(struct sys_device *dev, pm_message_t state)
276{ 277{
277 /* 278 /*
278 * Estimate time zone so that set_time can update the clock 279 * Estimate time zone so that set_time can update the clock
279 */ 280 */
280 clock_cmos_diff = -get_cmos_time(); 281 unsigned long ctime = get_cmos_time();
282
283 clock_cmos_diff = -ctime;
281 clock_cmos_diff += get_seconds(); 284 clock_cmos_diff += get_seconds();
282 sleep_start = get_cmos_time(); 285 sleep_start = ctime;
283 return 0; 286 return 0;
284} 287}
285 288
@@ -287,18 +290,29 @@ static int timer_resume(struct sys_device *dev)
287{ 290{
288 unsigned long flags; 291 unsigned long flags;
289 unsigned long sec; 292 unsigned long sec;
290 unsigned long sleep_length; 293 unsigned long ctime = get_cmos_time();
291 294 long sleep_length = (ctime - sleep_start) * HZ;
295 struct timespec ts;
296
297 if (sleep_length < 0) {
298 printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
299 /* The time after the resume must not be earlier than the time
300 * before the suspend or some nasty things will happen
301 */
302 sleep_length = 0;
303 ctime = sleep_start;
304 }
292#ifdef CONFIG_HPET_TIMER 305#ifdef CONFIG_HPET_TIMER
293 if (is_hpet_enabled()) 306 if (is_hpet_enabled())
294 hpet_reenable(); 307 hpet_reenable();
295#endif 308#endif
296 setup_pit_timer(); 309 setup_pit_timer();
297 sec = get_cmos_time() + clock_cmos_diff; 310
298 sleep_length = (get_cmos_time() - sleep_start) * HZ; 311 sec = ctime + clock_cmos_diff;
312 ts.tv_sec = sec;
313 ts.tv_nsec = 0;
314 do_settimeofday(&ts);
299 write_seqlock_irqsave(&xtime_lock, flags); 315 write_seqlock_irqsave(&xtime_lock, flags);
300 xtime.tv_sec = sec;
301 xtime.tv_nsec = 0;
302 jiffies_64 += sleep_length; 316 jiffies_64 += sleep_length;
303 wall_jiffies += sleep_length; 317 wall_jiffies += sleep_length;
304 write_sequnlock_irqrestore(&xtime_lock, flags); 318 write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -334,10 +348,11 @@ extern void (*late_time_init)(void);
334/* Duplicate of time_init() below, with hpet_enable part added */ 348/* Duplicate of time_init() below, with hpet_enable part added */
335static void __init hpet_time_init(void) 349static void __init hpet_time_init(void)
336{ 350{
337 xtime.tv_sec = get_cmos_time(); 351 struct timespec ts;
338 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 352 ts.tv_sec = get_cmos_time();
339 set_normalized_timespec(&wall_to_monotonic, 353 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
340 -xtime.tv_sec, -xtime.tv_nsec); 354
355 do_settimeofday(&ts);
341 356
342 if ((hpet_enable() >= 0) && hpet_use_timer) { 357 if ((hpet_enable() >= 0) && hpet_use_timer) {
343 printk("Using HPET for base-timer\n"); 358 printk("Using HPET for base-timer\n");
@@ -349,6 +364,7 @@ static void __init hpet_time_init(void)
349 364
350void __init time_init(void) 365void __init time_init(void)
351{ 366{
367 struct timespec ts;
352#ifdef CONFIG_HPET_TIMER 368#ifdef CONFIG_HPET_TIMER
353 if (is_hpet_capable()) { 369 if (is_hpet_capable()) {
354 /* 370 /*
@@ -359,10 +375,10 @@ void __init time_init(void)
359 return; 375 return;
360 } 376 }
361#endif 377#endif
362 xtime.tv_sec = get_cmos_time(); 378 ts.tv_sec = get_cmos_time();
363 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); 379 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
364 set_normalized_timespec(&wall_to_monotonic, 380
365 -xtime.tv_sec, -xtime.tv_nsec); 381 do_settimeofday(&ts);
366 382
367 time_init_hook(); 383 time_init_hook();
368} 384}
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 14a1376fedd1..6bf14a4e995e 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -301,23 +301,25 @@ int hpet_rtc_timer_init(void)
301 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; 301 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
302 302
303 local_irq_save(flags); 303 local_irq_save(flags);
304
304 cnt = hpet_readl(HPET_COUNTER); 305 cnt = hpet_readl(HPET_COUNTER);
305 cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); 306 cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
306 hpet_writel(cnt, HPET_T1_CMP); 307 hpet_writel(cnt, HPET_T1_CMP);
307 hpet_t1_cmp = cnt; 308 hpet_t1_cmp = cnt;
308 local_irq_restore(flags);
309 309
310 cfg = hpet_readl(HPET_T1_CFG); 310 cfg = hpet_readl(HPET_T1_CFG);
311 cfg &= ~HPET_TN_PERIODIC; 311 cfg &= ~HPET_TN_PERIODIC;
312 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; 312 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
313 hpet_writel(cfg, HPET_T1_CFG); 313 hpet_writel(cfg, HPET_T1_CFG);
314 314
315 local_irq_restore(flags);
316
315 return 1; 317 return 1;
316} 318}
317 319
318static void hpet_rtc_timer_reinit(void) 320static void hpet_rtc_timer_reinit(void)
319{ 321{
320 unsigned int cfg, cnt; 322 unsigned int cfg, cnt, ticks_per_int, lost_ints;
321 323
322 if (unlikely(!(PIE_on | AIE_on | UIE_on))) { 324 if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
323 cfg = hpet_readl(HPET_T1_CFG); 325 cfg = hpet_readl(HPET_T1_CFG);
@@ -332,10 +334,33 @@ static void hpet_rtc_timer_reinit(void)
332 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; 334 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
333 335
334 /* It is more accurate to use the comparator value than current count.*/ 336 /* It is more accurate to use the comparator value than current count.*/
335 cnt = hpet_t1_cmp; 337 ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
336 cnt += hpet_tick*HZ/hpet_rtc_int_freq; 338 hpet_t1_cmp += ticks_per_int;
337 hpet_writel(cnt, HPET_T1_CMP); 339 hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
338 hpet_t1_cmp = cnt; 340
341 /*
342 * If the interrupt handler was delayed too long, the write above tries
343 * to schedule the next interrupt in the past and the hardware would
344 * not interrupt until the counter had wrapped around.
345 * So we have to check that the comparator wasn't set to a past time.
346 */
347 cnt = hpet_readl(HPET_COUNTER);
348 if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
349 lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
350 /* Make sure that, even with the time needed to execute
351 * this code, the next scheduled interrupt has been moved
352 * back to the future: */
353 lost_ints++;
354
355 hpet_t1_cmp += lost_ints * ticks_per_int;
356 hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
357
358 if (PIE_on)
359 PIE_count += lost_ints;
360
361 printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
362 hpet_rtc_int_freq);
363 }
339} 364}
340 365
341/* 366/*
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7e9edafffd8a..4fcc6690be99 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -313,6 +313,8 @@ void show_registers(struct pt_regs *regs)
313 */ 313 */
314 if (in_kernel) { 314 if (in_kernel) {
315 u8 __user *eip; 315 u8 __user *eip;
316 int code_bytes = 64;
317 unsigned char c;
316 318
317 printk("\n" KERN_EMERG "Stack: "); 319 printk("\n" KERN_EMERG "Stack: ");
318 show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); 320 show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
@@ -320,9 +322,12 @@ void show_registers(struct pt_regs *regs)
320 printk(KERN_EMERG "Code: "); 322 printk(KERN_EMERG "Code: ");
321 323
322 eip = (u8 __user *)regs->eip - 43; 324 eip = (u8 __user *)regs->eip - 43;
323 for (i = 0; i < 64; i++, eip++) { 325 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
324 unsigned char c; 326 /* try starting at EIP */
325 327 eip = (u8 __user *)regs->eip;
328 code_bytes = 32;
329 }
330 for (i = 0; i < code_bytes; i++, eip++) {
326 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { 331 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
327 printk(" Bad EIP value."); 332 printk(" Bad EIP value.");
328 break; 333 break;
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 2d4f1386e2b1..1e7ac1c44ddc 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
13OUTPUT_ARCH(i386) 13OUTPUT_ARCH(i386)
14ENTRY(phys_startup_32) 14ENTRY(phys_startup_32)
15jiffies = jiffies_64; 15jiffies = jiffies_64;
16
17PHDRS {
18 text PT_LOAD FLAGS(5); /* R_E */
19 data PT_LOAD FLAGS(7); /* RWE */
20 note PT_NOTE FLAGS(4); /* R__ */
21}
16SECTIONS 22SECTIONS
17{ 23{
18 . = __KERNEL_START; 24 . = __KERNEL_START;
@@ -26,7 +32,7 @@ SECTIONS
26 KPROBES_TEXT 32 KPROBES_TEXT
27 *(.fixup) 33 *(.fixup)
28 *(.gnu.warning) 34 *(.gnu.warning)
29 } = 0x9090 35 } :text = 0x9090
30 36
31 _etext = .; /* End of text section */ 37 _etext = .; /* End of text section */
32 38
@@ -48,7 +54,7 @@ SECTIONS
48 .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ 54 .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
49 *(.data) 55 *(.data)
50 CONSTRUCTORS 56 CONSTRUCTORS
51 } 57 } :data
52 58
53 . = ALIGN(4096); 59 . = ALIGN(4096);
54 __nosave_begin = .; 60 __nosave_begin = .;
@@ -184,4 +190,6 @@ SECTIONS
184 STABS_DEBUG 190 STABS_DEBUG
185 191
186 DWARF_DEBUG 192 DWARF_DEBUG
193
194 NOTES
187} 195}
diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
index 50f6de6ff64d..f39887359e8e 100644
--- a/arch/i386/mach-voyager/voyager_thread.c
+++ b/arch/i386/mach-voyager/voyager_thread.c
@@ -130,7 +130,6 @@ thread(void *unused)
130 init_timer(&wakeup_timer); 130 init_timer(&wakeup_timer);
131 131
132 sigfillset(&current->blocked); 132 sigfillset(&current->blocked);
133 current->signal->tty = NULL;
134 133
135 printk(KERN_NOTICE "Voyager starting monitor thread\n"); 134 printk(KERN_NOTICE "Voyager starting monitor thread\n");
136 135
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 7c392dc553b8..fb5d8b747de4 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -117,7 +117,8 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
117 117
118void *node_remap_end_vaddr[MAX_NUMNODES]; 118void *node_remap_end_vaddr[MAX_NUMNODES];
119void *node_remap_alloc_vaddr[MAX_NUMNODES]; 119void *node_remap_alloc_vaddr[MAX_NUMNODES];
120 120static unsigned long kva_start_pfn;
121static unsigned long kva_pages;
121/* 122/*
122 * FLAT - support for basic PC memory model with discontig enabled, essentially 123 * FLAT - support for basic PC memory model with discontig enabled, essentially
123 * a single node with all available processors in it with a flat 124 * a single node with all available processors in it with a flat
@@ -286,7 +287,6 @@ unsigned long __init setup_memory(void)
286{ 287{
287 int nid; 288 int nid;
288 unsigned long system_start_pfn, system_max_low_pfn; 289 unsigned long system_start_pfn, system_max_low_pfn;
289 unsigned long reserve_pages;
290 290
291 /* 291 /*
292 * When mapping a NUMA machine we allocate the node_mem_map arrays 292 * When mapping a NUMA machine we allocate the node_mem_map arrays
@@ -298,14 +298,23 @@ unsigned long __init setup_memory(void)
298 find_max_pfn(); 298 find_max_pfn();
299 get_memcfg_numa(); 299 get_memcfg_numa();
300 300
301 reserve_pages = calculate_numa_remap_pages(); 301 kva_pages = calculate_numa_remap_pages();
302 302
303 /* partially used pages are not usable - thus round upwards */ 303 /* partially used pages are not usable - thus round upwards */
304 system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end); 304 system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end);
305 305
306 system_max_low_pfn = max_low_pfn = find_max_low_pfn() - reserve_pages; 306 kva_start_pfn = find_max_low_pfn() - kva_pages;
307 printk("reserve_pages = %ld find_max_low_pfn() ~ %ld\n", 307
308 reserve_pages, max_low_pfn + reserve_pages); 308#ifdef CONFIG_BLK_DEV_INITRD
309 /* Numa kva area is below the initrd */
310 if (LOADER_TYPE && INITRD_START)
311 kva_start_pfn = PFN_DOWN(INITRD_START) - kva_pages;
312#endif
313 kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1);
314
315 system_max_low_pfn = max_low_pfn = find_max_low_pfn();
316 printk("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n",
317 kva_start_pfn, max_low_pfn);
309 printk("max_pfn = %ld\n", max_pfn); 318 printk("max_pfn = %ld\n", max_pfn);
310#ifdef CONFIG_HIGHMEM 319#ifdef CONFIG_HIGHMEM
311 highstart_pfn = highend_pfn = max_pfn; 320 highstart_pfn = highend_pfn = max_pfn;
@@ -323,7 +332,7 @@ unsigned long __init setup_memory(void)
323 (ulong) pfn_to_kaddr(max_low_pfn)); 332 (ulong) pfn_to_kaddr(max_low_pfn));
324 for_each_online_node(nid) { 333 for_each_online_node(nid) {
325 node_remap_start_vaddr[nid] = pfn_to_kaddr( 334 node_remap_start_vaddr[nid] = pfn_to_kaddr(
326 highstart_pfn + node_remap_offset[nid]); 335 kva_start_pfn + node_remap_offset[nid]);
327 /* Init the node remap allocator */ 336 /* Init the node remap allocator */
328 node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] + 337 node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
329 (node_remap_size[nid] * PAGE_SIZE); 338 (node_remap_size[nid] * PAGE_SIZE);
@@ -338,7 +347,6 @@ unsigned long __init setup_memory(void)
338 } 347 }
339 printk("High memory starts at vaddr %08lx\n", 348 printk("High memory starts at vaddr %08lx\n",
340 (ulong) pfn_to_kaddr(highstart_pfn)); 349 (ulong) pfn_to_kaddr(highstart_pfn));
341 vmalloc_earlyreserve = reserve_pages * PAGE_SIZE;
342 for_each_online_node(nid) 350 for_each_online_node(nid)
343 find_max_pfn_node(nid); 351 find_max_pfn_node(nid);
344 352
@@ -348,13 +356,18 @@ unsigned long __init setup_memory(void)
348 return max_low_pfn; 356 return max_low_pfn;
349} 357}
350 358
359void __init numa_kva_reserve(void)
360{
361 reserve_bootmem(PFN_PHYS(kva_start_pfn),PFN_PHYS(kva_pages));
362}
363
351void __init zone_sizes_init(void) 364void __init zone_sizes_init(void)
352{ 365{
353 int nid; 366 int nid;
354 367
355 368
356 for_each_online_node(nid) { 369 for_each_online_node(nid) {
357 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 370 unsigned long zones_size[MAX_NR_ZONES] = {0, };
358 unsigned long *zholes_size; 371 unsigned long *zholes_size;
359 unsigned int max_dma; 372 unsigned int max_dma;
360 373
@@ -409,7 +422,7 @@ void __init set_highmem_pages_init(int bad_ppro)
409 zone_end_pfn = zone_start_pfn + zone->spanned_pages; 422 zone_end_pfn = zone_start_pfn + zone->spanned_pages;
410 423
411 printk("Initializing %s for node %d (%08lx:%08lx)\n", 424 printk("Initializing %s for node %d (%08lx:%08lx)\n",
412 zone->name, zone->zone_pgdat->node_id, 425 zone->name, zone_to_nid(zone),
413 zone_start_pfn, zone_end_pfn); 426 zone_start_pfn, zone_end_pfn);
414 427
415 for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) { 428 for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 89e8486aac34..efd0bcdac65d 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -629,6 +629,48 @@ void __init mem_init(void)
629 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) 629 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
630 ); 630 );
631 631
632#if 1 /* double-sanity-check paranoia */
633 printk("virtual kernel memory layout:\n"
634 " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
635#ifdef CONFIG_HIGHMEM
636 " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
637#endif
638 " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
639 " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
640 " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
641 " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
642 " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
643 FIXADDR_START, FIXADDR_TOP,
644 (FIXADDR_TOP - FIXADDR_START) >> 10,
645
646#ifdef CONFIG_HIGHMEM
647 PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
648 (LAST_PKMAP*PAGE_SIZE) >> 10,
649#endif
650
651 VMALLOC_START, VMALLOC_END,
652 (VMALLOC_END - VMALLOC_START) >> 20,
653
654 (unsigned long)__va(0), (unsigned long)high_memory,
655 ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
656
657 (unsigned long)&__init_begin, (unsigned long)&__init_end,
658 ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10,
659
660 (unsigned long)&_etext, (unsigned long)&_edata,
661 ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
662
663 (unsigned long)&_text, (unsigned long)&_etext,
664 ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
665
666#ifdef CONFIG_HIGHMEM
667 BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE > FIXADDR_START);
668 BUG_ON(VMALLOC_END > PKMAP_BASE);
669#endif
670 BUG_ON(VMALLOC_START > VMALLOC_END);
671 BUG_ON((unsigned long)high_memory > VMALLOC_START);
672#endif /* double-sanity-check paranoia */
673
632#ifdef CONFIG_X86_PAE 674#ifdef CONFIG_X86_PAE
633 if (!cpu_has_pae) 675 if (!cpu_has_pae)
634 panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!"); 676 panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
@@ -657,7 +699,7 @@ void __init mem_init(void)
657int arch_add_memory(int nid, u64 start, u64 size) 699int arch_add_memory(int nid, u64 start, u64 size)
658{ 700{
659 struct pglist_data *pgdata = &contig_page_data; 701 struct pglist_data *pgdata = &contig_page_data;
660 struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1; 702 struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
661 unsigned long start_pfn = start >> PAGE_SHIFT; 703 unsigned long start_pfn = start >> PAGE_SHIFT;
662 unsigned long nr_pages = size >> PAGE_SHIFT; 704 unsigned long nr_pages = size >> PAGE_SHIFT;
663 705
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index bd98768d8764..10126e3f8174 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -12,6 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/pagemap.h> 13#include <linux/pagemap.h>
14#include <linux/spinlock.h> 14#include <linux/spinlock.h>
15#include <linux/module.h>
15 16
16#include <asm/system.h> 17#include <asm/system.h>
17#include <asm/pgtable.h> 18#include <asm/pgtable.h>
@@ -60,7 +61,9 @@ void show_mem(void)
60 printk(KERN_INFO "%lu pages writeback\n", 61 printk(KERN_INFO "%lu pages writeback\n",
61 global_page_state(NR_WRITEBACK)); 62 global_page_state(NR_WRITEBACK));
62 printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED)); 63 printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
63 printk(KERN_INFO "%lu pages slab\n", global_page_state(NR_SLAB)); 64 printk(KERN_INFO "%lu pages slab\n",
65 global_page_state(NR_SLAB_RECLAIMABLE) +
66 global_page_state(NR_SLAB_UNRECLAIMABLE));
64 printk(KERN_INFO "%lu pages pagetables\n", 67 printk(KERN_INFO "%lu pages pagetables\n",
65 global_page_state(NR_PAGETABLE)); 68 global_page_state(NR_PAGETABLE));
66} 69}
@@ -137,6 +140,12 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
137 __flush_tlb_one(vaddr); 140 __flush_tlb_one(vaddr);
138} 141}
139 142
143static int fixmaps;
144#ifndef CONFIG_COMPAT_VDSO
145unsigned long __FIXADDR_TOP = 0xfffff000;
146EXPORT_SYMBOL(__FIXADDR_TOP);
147#endif
148
140void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) 149void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
141{ 150{
142 unsigned long address = __fix_to_virt(idx); 151 unsigned long address = __fix_to_virt(idx);
@@ -146,6 +155,25 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
146 return; 155 return;
147 } 156 }
148 set_pte_pfn(address, phys >> PAGE_SHIFT, flags); 157 set_pte_pfn(address, phys >> PAGE_SHIFT, flags);
158 fixmaps++;
159}
160
161/**
162 * reserve_top_address - reserves a hole in the top of kernel address space
163 * @reserve - size of hole to reserve
164 *
165 * Can be used to relocate the fixmap area and poke a hole in the top
166 * of kernel address space to make room for a hypervisor.
167 */
168void reserve_top_address(unsigned long reserve)
169{
170 BUG_ON(fixmaps > 0);
171#ifdef CONFIG_COMPAT_VDSO
172 BUG_ON(reserve != 0);
173#else
174 __FIXADDR_TOP = -reserve - PAGE_SIZE;
175 __VMALLOC_RESERVE += reserve;
176#endif
149} 177}
150 178
151pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) 179pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
index c893b897217f..8a2b50a0aaad 100644
--- a/arch/i386/power/swsusp.S
+++ b/arch/i386/power/swsusp.S
@@ -32,7 +32,7 @@ ENTRY(swsusp_arch_resume)
32 movl $swsusp_pg_dir-__PAGE_OFFSET, %ecx 32 movl $swsusp_pg_dir-__PAGE_OFFSET, %ecx
33 movl %ecx, %cr3 33 movl %ecx, %cr3
34 34
35 movl pagedir_nosave, %edx 35 movl restore_pblist, %edx
36 .p2align 4,,7 36 .p2align 4,,7
37 37
38copy_loop: 38copy_loop:
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index db274da7dba1..f521f2f60a78 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -66,15 +66,6 @@ config IA64_UNCACHED_ALLOCATOR
66 bool 66 bool
67 select GENERIC_ALLOCATOR 67 select GENERIC_ALLOCATOR
68 68
69config DMA_IS_DMA32
70 bool
71 default y
72
73config DMA_IS_NORMAL
74 bool
75 depends on IA64_SGI_SN2
76 default y
77
78config AUDIT_ARCH 69config AUDIT_ARCH
79 bool 70 bool
80 default y 71 default y
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 84a7e52f56f6..7bb7696e4ce2 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -34,6 +34,7 @@
34#include <linux/file.h> 34#include <linux/file.h>
35#include <linux/poll.h> 35#include <linux/poll.h>
36#include <linux/vfs.h> 36#include <linux/vfs.h>
37#include <linux/smp.h>
37#include <linux/pagemap.h> 38#include <linux/pagemap.h>
38#include <linux/mount.h> 39#include <linux/mount.h>
39#include <linux/bitops.h> 40#include <linux/bitops.h>
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 4c73a6763669..c58e933694d5 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -98,7 +98,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
98 98
99 /* attempt to allocate a granule's worth of cached memory pages */ 99 /* attempt to allocate a granule's worth of cached memory pages */
100 100
101 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO, 101 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
102 IA64_GRANULE_SHIFT-PAGE_SHIFT); 102 IA64_GRANULE_SHIFT-PAGE_SHIFT);
103 if (!page) { 103 if (!page) {
104 mutex_unlock(&uc_pool->add_chunk_mutex); 104 mutex_unlock(&uc_pool->add_chunk_mutex);
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 9a8a29339d2d..b632b9c1e3b3 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -32,9 +32,10 @@
32#include <linux/cpumask.h> 32#include <linux/cpumask.h>
33#include <linux/smp_lock.h> 33#include <linux/smp_lock.h>
34#include <linux/nodemask.h> 34#include <linux/nodemask.h>
35#include <linux/smp.h>
36
35#include <asm/processor.h> 37#include <asm/processor.h>
36#include <asm/topology.h> 38#include <asm/topology.h>
37#include <asm/smp.h>
38#include <asm/semaphore.h> 39#include <asm/semaphore.h>
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
40#include <asm/sal.h> 41#include <asm/sal.h>
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index b71348fec1f4..bbd97c85bc5d 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -100,7 +100,7 @@ void free_initrd_mem(unsigned long, unsigned long);
100#ifndef CONFIG_DISCONTIGMEM 100#ifndef CONFIG_DISCONTIGMEM
101unsigned long __init zone_sizes_init(void) 101unsigned long __init zone_sizes_init(void)
102{ 102{
103 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 103 unsigned long zones_size[MAX_NR_ZONES] = {0, };
104 unsigned long max_dma; 104 unsigned long max_dma;
105 unsigned long low; 105 unsigned long low;
106 unsigned long start_pfn; 106 unsigned long start_pfn;
diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
index e4c233eef195..06e538d1be3a 100644
--- a/arch/m68knommu/mm/init.c
+++ b/arch/m68knommu/mm/init.c
@@ -136,7 +136,7 @@ void paging_init(void)
136#endif 136#endif
137 137
138 { 138 {
139 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 139 unsigned long zones_size[MAX_NR_ZONES] = {0, };
140 140
141 zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT; 141 zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
142 zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; 142 zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index 98244d51c154..c4fae8ff4671 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -230,7 +230,7 @@ EXPORT_SYMBOL(au1xxx_ddma_add_device);
230*/ 230*/
231u32 231u32
232au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, 232au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
233 void (*callback)(int, void *, struct pt_regs *), void *callparam) 233 void (*callback)(int, void *), void *callparam)
234{ 234{
235 unsigned long flags; 235 unsigned long flags;
236 u32 used, chan, rv; 236 u32 used, chan, rv;
@@ -248,8 +248,10 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
248 au1xxx_dbdma_init(); 248 au1xxx_dbdma_init();
249 dbdma_initialized = 1; 249 dbdma_initialized = 1;
250 250
251 if ((stp = find_dbdev_id(srcid)) == NULL) return 0; 251 if ((stp = find_dbdev_id(srcid)) == NULL)
252 if ((dtp = find_dbdev_id(destid)) == NULL) return 0; 252 return 0;
253 if ((dtp = find_dbdev_id(destid)) == NULL)
254 return 0;
253 255
254 used = 0; 256 used = 0;
255 rv = 0; 257 rv = 0;
@@ -869,7 +871,7 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
869 au_sync(); 871 au_sync();
870 872
871 if (ctp->chan_callback) 873 if (ctp->chan_callback)
872 (ctp->chan_callback)(irq, ctp->chan_callparam, regs); 874 (ctp->chan_callback)(irq, ctp->chan_callparam);
873 875
874 ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); 876 ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
875 return IRQ_RETVAL(1); 877 return IRQ_RETVAL(1);
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index c52497bb102a..5b06349af2d5 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -163,10 +163,10 @@ static int __init page_is_ram(unsigned long pagenr)
163 163
164void __init paging_init(void) 164void __init paging_init(void)
165{ 165{
166 unsigned long zones_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 }; 166 unsigned long zones_size[] = { 0, };
167 unsigned long max_dma, high, low; 167 unsigned long max_dma, high, low;
168#ifndef CONFIG_FLATMEM 168#ifndef CONFIG_FLATMEM
169 unsigned long zholes_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 }; 169 unsigned long zholes_size[] = { 0, };
170 unsigned long i, j, pfn; 170 unsigned long i, j, pfn;
171#endif 171#endif
172 172
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index efe6971fc800..16e5682b01f1 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -19,6 +19,7 @@
19#include <linux/swap.h> 19#include <linux/swap.h>
20#include <linux/bootmem.h> 20#include <linux/bootmem.h>
21#include <linux/pfn.h> 21#include <linux/pfn.h>
22#include <linux/highmem.h>
22#include <asm/page.h> 23#include <asm/page.h>
23#include <asm/sections.h> 24#include <asm/sections.h>
24 25
@@ -508,7 +509,7 @@ extern unsigned long setup_zero_pages(void);
508 509
509void __init paging_init(void) 510void __init paging_init(void)
510{ 511{
511 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 512 unsigned long zones_size[MAX_NR_ZONES] = {0, };
512 unsigned node; 513 unsigned node;
513 514
514 pagetable_init(); 515 pagetable_init();
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index f2b96f1e0da7..25ad28d63e88 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -551,7 +551,7 @@ void show_mem(void)
551 551
552 printk("Zone list for zone %d on node %d: ", j, i); 552 printk("Zone list for zone %d on node %d: ", j, i);
553 for (k = 0; zl->zones[k] != NULL; k++) 553 for (k = 0; zl->zones[k] != NULL; k++)
554 printk("[%d/%s] ", zl->zones[k]->zone_pgdat->node_id, zl->zones[k]->name); 554 printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name);
555 printk("\n"); 555 printk("\n");
556 } 556 }
557 } 557 }
@@ -809,7 +809,7 @@ void __init paging_init(void)
809 flush_tlb_all_local(NULL); 809 flush_tlb_all_local(NULL);
810 810
811 for (i = 0; i < npmem_ranges; i++) { 811 for (i = 0; i < npmem_ranges; i++) {
812 unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0 }; 812 unsigned long zones_size[MAX_NR_ZONES] = { 0, };
813 813
814 /* We have an IOMMU, so all memory can go into a single 814 /* We have an IOMMU, so all memory can go into a single
815 ZONE_DMA zone. */ 815 ZONE_DMA zone. */
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
index 7369f9a6ad25..69e8f86aa4f8 100644
--- a/arch/powerpc/kernel/swsusp_32.S
+++ b/arch/powerpc/kernel/swsusp_32.S
@@ -159,8 +159,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
159 isync 159 isync
160 160
161 /* Load ptr the list of pages to copy in r3 */ 161 /* Load ptr the list of pages to copy in r3 */
162 lis r11,(pagedir_nosave - KERNELBASE)@h 162 lis r11,(restore_pblist - KERNELBASE)@h
163 ori r11,r11,pagedir_nosave@l 163 ori r11,r11,restore_pblist@l
164 lwz r10,0(r11) 164 lwz r10,0(r11)
165 165
166 /* Copy the pages. This is a very basic implementation, to 166 /* Copy the pages. This is a very basic implementation, to
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index ab3b0765a64e..8aea3698a77b 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -117,8 +117,7 @@ static void appldata_get_mem_data(void *data)
117 mem_data->pgpgout = ev[PGPGOUT] >> 1; 117 mem_data->pgpgout = ev[PGPGOUT] >> 1;
118 mem_data->pswpin = ev[PSWPIN]; 118 mem_data->pswpin = ev[PSWPIN];
119 mem_data->pswpout = ev[PSWPOUT]; 119 mem_data->pswpout = ev[PSWPOUT];
120 mem_data->pgalloc = ev[PGALLOC_HIGH] + ev[PGALLOC_NORMAL] + 120 mem_data->pgalloc = ev[PGALLOC_NORMAL] + ev[PGALLOC_DMA];
121 ev[PGALLOC_DMA];
122 mem_data->pgfault = ev[PGFAULT]; 121 mem_data->pgfault = ev[PGFAULT];
123 mem_data->pgmajfault = ev[PGMAJFAULT]; 122 mem_data->pgmajfault = ev[PGMAJFAULT];
124 123
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 786a44dba5bf..607f50ead1fd 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -15,6 +15,8 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/sysctl.h> 16#include <linux/sysctl.h>
17#include <linux/ctype.h> 17#include <linux/ctype.h>
18#include <linux/swap.h>
19#include <linux/kthread.h>
18 20
19#include <asm/pgalloc.h> 21#include <asm/pgalloc.h>
20#include <asm/uaccess.h> 22#include <asm/uaccess.h>
@@ -34,18 +36,18 @@ struct cmm_page_array {
34 unsigned long pages[CMM_NR_PAGES]; 36 unsigned long pages[CMM_NR_PAGES];
35}; 37};
36 38
37static long cmm_pages = 0; 39static long cmm_pages;
38static long cmm_timed_pages = 0; 40static long cmm_timed_pages;
39static volatile long cmm_pages_target = 0; 41static volatile long cmm_pages_target;
40static volatile long cmm_timed_pages_target = 0; 42static volatile long cmm_timed_pages_target;
41static long cmm_timeout_pages = 0; 43static long cmm_timeout_pages;
42static long cmm_timeout_seconds = 0; 44static long cmm_timeout_seconds;
43 45
44static struct cmm_page_array *cmm_page_list = NULL; 46static struct cmm_page_array *cmm_page_list;
45static struct cmm_page_array *cmm_timed_page_list = NULL; 47static struct cmm_page_array *cmm_timed_page_list;
48static DEFINE_SPINLOCK(cmm_lock);
46 49
47static unsigned long cmm_thread_active = 0; 50static struct task_struct *cmm_thread_ptr;
48static struct work_struct cmm_thread_starter;
49static wait_queue_head_t cmm_thread_wait; 51static wait_queue_head_t cmm_thread_wait;
50static struct timer_list cmm_timer; 52static struct timer_list cmm_timer;
51 53
@@ -53,71 +55,100 @@ static void cmm_timer_fn(unsigned long);
53static void cmm_set_timer(void); 55static void cmm_set_timer(void);
54 56
55static long 57static long
56cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list) 58cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list)
57{ 59{
58 struct cmm_page_array *pa; 60 struct cmm_page_array *pa, *npa;
59 unsigned long page; 61 unsigned long addr;
60 62
61 pa = *list; 63 while (nr) {
62 while (pages) { 64 addr = __get_free_page(GFP_NOIO);
63 page = __get_free_page(GFP_NOIO); 65 if (!addr)
64 if (!page)
65 break; 66 break;
67 spin_lock(&cmm_lock);
68 pa = *list;
66 if (!pa || pa->index >= CMM_NR_PAGES) { 69 if (!pa || pa->index >= CMM_NR_PAGES) {
67 /* Need a new page for the page list. */ 70 /* Need a new page for the page list. */
68 pa = (struct cmm_page_array *) 71 spin_unlock(&cmm_lock);
72 npa = (struct cmm_page_array *)
69 __get_free_page(GFP_NOIO); 73 __get_free_page(GFP_NOIO);
70 if (!pa) { 74 if (!npa) {
71 free_page(page); 75 free_page(addr);
72 break; 76 break;
73 } 77 }
74 pa->next = *list; 78 spin_lock(&cmm_lock);
75 pa->index = 0; 79 pa = *list;
76 *list = pa; 80 if (!pa || pa->index >= CMM_NR_PAGES) {
81 npa->next = pa;
82 npa->index = 0;
83 pa = npa;
84 *list = pa;
85 } else
86 free_page((unsigned long) npa);
77 } 87 }
78 diag10(page); 88 diag10(addr);
79 pa->pages[pa->index++] = page; 89 pa->pages[pa->index++] = addr;
80 (*counter)++; 90 (*counter)++;
81 pages--; 91 spin_unlock(&cmm_lock);
92 nr--;
82 } 93 }
83 return pages; 94 return nr;
84} 95}
85 96
86static void 97static long
87cmm_free_pages(long pages, long *counter, struct cmm_page_array **list) 98cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
88{ 99{
89 struct cmm_page_array *pa; 100 struct cmm_page_array *pa;
90 unsigned long page; 101 unsigned long addr;
91 102
103 spin_lock(&cmm_lock);
92 pa = *list; 104 pa = *list;
93 while (pages) { 105 while (nr) {
94 if (!pa || pa->index <= 0) 106 if (!pa || pa->index <= 0)
95 break; 107 break;
96 page = pa->pages[--pa->index]; 108 addr = pa->pages[--pa->index];
97 if (pa->index == 0) { 109 if (pa->index == 0) {
98 pa = pa->next; 110 pa = pa->next;
99 free_page((unsigned long) *list); 111 free_page((unsigned long) *list);
100 *list = pa; 112 *list = pa;
101 } 113 }
102 free_page(page); 114 free_page(addr);
103 (*counter)--; 115 (*counter)--;
104 pages--; 116 nr--;
105 } 117 }
118 spin_unlock(&cmm_lock);
119 return nr;
106} 120}
107 121
122static int cmm_oom_notify(struct notifier_block *self,
123 unsigned long dummy, void *parm)
124{
125 unsigned long *freed = parm;
126 long nr = 256;
127
128 nr = cmm_free_pages(nr, &cmm_timed_pages, &cmm_timed_page_list);
129 if (nr > 0)
130 nr = cmm_free_pages(nr, &cmm_pages, &cmm_page_list);
131 cmm_pages_target = cmm_pages;
132 cmm_timed_pages_target = cmm_timed_pages;
133 *freed += 256 - nr;
134 return NOTIFY_OK;
135}
136
137static struct notifier_block cmm_oom_nb = {
138 .notifier_call = cmm_oom_notify
139};
140
108static int 141static int
109cmm_thread(void *dummy) 142cmm_thread(void *dummy)
110{ 143{
111 int rc; 144 int rc;
112 145
113 daemonize("cmmthread");
114 while (1) { 146 while (1) {
115 rc = wait_event_interruptible(cmm_thread_wait, 147 rc = wait_event_interruptible(cmm_thread_wait,
116 (cmm_pages != cmm_pages_target || 148 (cmm_pages != cmm_pages_target ||
117 cmm_timed_pages != cmm_timed_pages_target)); 149 cmm_timed_pages != cmm_timed_pages_target ||
118 if (rc == -ERESTARTSYS) { 150 kthread_should_stop()));
119 /* Got kill signal. End thread. */ 151 if (kthread_should_stop() || rc == -ERESTARTSYS) {
120 clear_bit(0, &cmm_thread_active);
121 cmm_pages_target = cmm_pages; 152 cmm_pages_target = cmm_pages;
122 cmm_timed_pages_target = cmm_timed_pages; 153 cmm_timed_pages_target = cmm_timed_pages;
123 break; 154 break;
@@ -143,16 +174,8 @@ cmm_thread(void *dummy)
143} 174}
144 175
145static void 176static void
146cmm_start_thread(void)
147{
148 kernel_thread(cmm_thread, NULL, 0);
149}
150
151static void
152cmm_kick_thread(void) 177cmm_kick_thread(void)
153{ 178{
154 if (!test_and_set_bit(0, &cmm_thread_active))
155 schedule_work(&cmm_thread_starter);
156 wake_up(&cmm_thread_wait); 179 wake_up(&cmm_thread_wait);
157} 180}
158 181
@@ -177,21 +200,21 @@ cmm_set_timer(void)
177static void 200static void
178cmm_timer_fn(unsigned long ignored) 201cmm_timer_fn(unsigned long ignored)
179{ 202{
180 long pages; 203 long nr;
181 204
182 pages = cmm_timed_pages_target - cmm_timeout_pages; 205 nr = cmm_timed_pages_target - cmm_timeout_pages;
183 if (pages < 0) 206 if (nr < 0)
184 cmm_timed_pages_target = 0; 207 cmm_timed_pages_target = 0;
185 else 208 else
186 cmm_timed_pages_target = pages; 209 cmm_timed_pages_target = nr;
187 cmm_kick_thread(); 210 cmm_kick_thread();
188 cmm_set_timer(); 211 cmm_set_timer();
189} 212}
190 213
191void 214void
192cmm_set_pages(long pages) 215cmm_set_pages(long nr)
193{ 216{
194 cmm_pages_target = pages; 217 cmm_pages_target = nr;
195 cmm_kick_thread(); 218 cmm_kick_thread();
196} 219}
197 220
@@ -202,9 +225,9 @@ cmm_get_pages(void)
202} 225}
203 226
204void 227void
205cmm_add_timed_pages(long pages) 228cmm_add_timed_pages(long nr)
206{ 229{
207 cmm_timed_pages_target += pages; 230 cmm_timed_pages_target += nr;
208 cmm_kick_thread(); 231 cmm_kick_thread();
209} 232}
210 233
@@ -215,9 +238,9 @@ cmm_get_timed_pages(void)
215} 238}
216 239
217void 240void
218cmm_set_timeout(long pages, long seconds) 241cmm_set_timeout(long nr, long seconds)
219{ 242{
220 cmm_timeout_pages = pages; 243 cmm_timeout_pages = nr;
221 cmm_timeout_seconds = seconds; 244 cmm_timeout_seconds = seconds;
222 cmm_set_timer(); 245 cmm_set_timer();
223} 246}
@@ -245,7 +268,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
245 void __user *buffer, size_t *lenp, loff_t *ppos) 268 void __user *buffer, size_t *lenp, loff_t *ppos)
246{ 269{
247 char buf[16], *p; 270 char buf[16], *p;
248 long pages; 271 long nr;
249 int len; 272 int len;
250 273
251 if (!*lenp || (*ppos && !write)) { 274 if (!*lenp || (*ppos && !write)) {
@@ -260,17 +283,17 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
260 return -EFAULT; 283 return -EFAULT;
261 buf[sizeof(buf) - 1] = '\0'; 284 buf[sizeof(buf) - 1] = '\0';
262 cmm_skip_blanks(buf, &p); 285 cmm_skip_blanks(buf, &p);
263 pages = simple_strtoul(p, &p, 0); 286 nr = simple_strtoul(p, &p, 0);
264 if (ctl == &cmm_table[0]) 287 if (ctl == &cmm_table[0])
265 cmm_set_pages(pages); 288 cmm_set_pages(nr);
266 else 289 else
267 cmm_add_timed_pages(pages); 290 cmm_add_timed_pages(nr);
268 } else { 291 } else {
269 if (ctl == &cmm_table[0]) 292 if (ctl == &cmm_table[0])
270 pages = cmm_get_pages(); 293 nr = cmm_get_pages();
271 else 294 else
272 pages = cmm_get_timed_pages(); 295 nr = cmm_get_timed_pages();
273 len = sprintf(buf, "%ld\n", pages); 296 len = sprintf(buf, "%ld\n", nr);
274 if (len > *lenp) 297 if (len > *lenp)
275 len = *lenp; 298 len = *lenp;
276 if (copy_to_user(buffer, buf, len)) 299 if (copy_to_user(buffer, buf, len))
@@ -286,7 +309,7 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
286 void __user *buffer, size_t *lenp, loff_t *ppos) 309 void __user *buffer, size_t *lenp, loff_t *ppos)
287{ 310{
288 char buf[64], *p; 311 char buf[64], *p;
289 long pages, seconds; 312 long nr, seconds;
290 int len; 313 int len;
291 314
292 if (!*lenp || (*ppos && !write)) { 315 if (!*lenp || (*ppos && !write)) {
@@ -301,10 +324,10 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
301 return -EFAULT; 324 return -EFAULT;
302 buf[sizeof(buf) - 1] = '\0'; 325 buf[sizeof(buf) - 1] = '\0';
303 cmm_skip_blanks(buf, &p); 326 cmm_skip_blanks(buf, &p);
304 pages = simple_strtoul(p, &p, 0); 327 nr = simple_strtoul(p, &p, 0);
305 cmm_skip_blanks(p, &p); 328 cmm_skip_blanks(p, &p);
306 seconds = simple_strtoul(p, &p, 0); 329 seconds = simple_strtoul(p, &p, 0);
307 cmm_set_timeout(pages, seconds); 330 cmm_set_timeout(nr, seconds);
308 } else { 331 } else {
309 len = sprintf(buf, "%ld %ld\n", 332 len = sprintf(buf, "%ld %ld\n",
310 cmm_timeout_pages, cmm_timeout_seconds); 333 cmm_timeout_pages, cmm_timeout_seconds);
@@ -357,7 +380,7 @@ static struct ctl_table cmm_dir_table[] = {
357static void 380static void
358cmm_smsg_target(char *from, char *msg) 381cmm_smsg_target(char *from, char *msg)
359{ 382{
360 long pages, seconds; 383 long nr, seconds;
361 384
362 if (strlen(sender) > 0 && strcmp(from, sender) != 0) 385 if (strlen(sender) > 0 && strcmp(from, sender) != 0)
363 return; 386 return;
@@ -366,27 +389,27 @@ cmm_smsg_target(char *from, char *msg)
366 if (strncmp(msg, "SHRINK", 6) == 0) { 389 if (strncmp(msg, "SHRINK", 6) == 0) {
367 if (!cmm_skip_blanks(msg + 6, &msg)) 390 if (!cmm_skip_blanks(msg + 6, &msg))
368 return; 391 return;
369 pages = simple_strtoul(msg, &msg, 0); 392 nr = simple_strtoul(msg, &msg, 0);
370 cmm_skip_blanks(msg, &msg); 393 cmm_skip_blanks(msg, &msg);
371 if (*msg == '\0') 394 if (*msg == '\0')
372 cmm_set_pages(pages); 395 cmm_set_pages(nr);
373 } else if (strncmp(msg, "RELEASE", 7) == 0) { 396 } else if (strncmp(msg, "RELEASE", 7) == 0) {
374 if (!cmm_skip_blanks(msg + 7, &msg)) 397 if (!cmm_skip_blanks(msg + 7, &msg))
375 return; 398 return;
376 pages = simple_strtoul(msg, &msg, 0); 399 nr = simple_strtoul(msg, &msg, 0);
377 cmm_skip_blanks(msg, &msg); 400 cmm_skip_blanks(msg, &msg);
378 if (*msg == '\0') 401 if (*msg == '\0')
379 cmm_add_timed_pages(pages); 402 cmm_add_timed_pages(nr);
380 } else if (strncmp(msg, "REUSE", 5) == 0) { 403 } else if (strncmp(msg, "REUSE", 5) == 0) {
381 if (!cmm_skip_blanks(msg + 5, &msg)) 404 if (!cmm_skip_blanks(msg + 5, &msg))
382 return; 405 return;
383 pages = simple_strtoul(msg, &msg, 0); 406 nr = simple_strtoul(msg, &msg, 0);
384 if (!cmm_skip_blanks(msg, &msg)) 407 if (!cmm_skip_blanks(msg, &msg))
385 return; 408 return;
386 seconds = simple_strtoul(msg, &msg, 0); 409 seconds = simple_strtoul(msg, &msg, 0);
387 cmm_skip_blanks(msg, &msg); 410 cmm_skip_blanks(msg, &msg);
388 if (*msg == '\0') 411 if (*msg == '\0')
389 cmm_set_timeout(pages, seconds); 412 cmm_set_timeout(nr, seconds);
390 } 413 }
391} 414}
392#endif 415#endif
@@ -396,21 +419,49 @@ struct ctl_table_header *cmm_sysctl_header;
396static int 419static int
397cmm_init (void) 420cmm_init (void)
398{ 421{
422 int rc = -ENOMEM;
423
399#ifdef CONFIG_CMM_PROC 424#ifdef CONFIG_CMM_PROC
400 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1); 425 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
426 if (!cmm_sysctl_header)
427 goto out;
401#endif 428#endif
402#ifdef CONFIG_CMM_IUCV 429#ifdef CONFIG_CMM_IUCV
403 smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); 430 rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
431 if (rc < 0)
432 goto out_smsg;
404#endif 433#endif
405 INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL); 434 rc = register_oom_notifier(&cmm_oom_nb);
435 if (rc < 0)
436 goto out_oom_notify;
406 init_waitqueue_head(&cmm_thread_wait); 437 init_waitqueue_head(&cmm_thread_wait);
407 init_timer(&cmm_timer); 438 init_timer(&cmm_timer);
408 return 0; 439 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
440 rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
441 if (!rc)
442 goto out;
443 /*
444 * kthread_create failed. undo all the stuff from above again.
445 */
446 unregister_oom_notifier(&cmm_oom_nb);
447
448out_oom_notify:
449#ifdef CONFIG_CMM_IUCV
450 smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
451out_smsg:
452#endif
453#ifdef CONFIG_CMM_PROC
454 unregister_sysctl_table(cmm_sysctl_header);
455#endif
456out:
457 return rc;
409} 458}
410 459
411static void 460static void
412cmm_exit(void) 461cmm_exit(void)
413{ 462{
463 kthread_stop(cmm_thread_ptr);
464 unregister_oom_notifier(&cmm_oom_nb);
414 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); 465 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
415 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); 466 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
416#ifdef CONFIG_CMM_PROC 467#ifdef CONFIG_CMM_PROC
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index ad8ed7d41e16..bf94eedb0a8e 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -30,7 +30,7 @@
30 30
31#define __pte_offset(address) \ 31#define __pte_offset(address) \
32 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 32 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
33#define pte_offset(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \ 33#define pte_offset(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
34 __pte_offset(address)) 34 __pte_offset(address))
35 35
36static inline void cache_wback_all(void) 36static inline void cache_wback_all(void)
diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
index 1169757fb38b..83295bd21aa7 100644
--- a/arch/sh64/mm/init.c
+++ b/arch/sh64/mm/init.c
@@ -110,7 +110,7 @@ void show_mem(void)
110 */ 110 */
111void __init paging_init(void) 111void __init paging_init(void)
112{ 112{
113 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; 113 unsigned long zones_size[MAX_NR_ZONES] = {0, };
114 114
115 pgd_init((unsigned long)swapper_pg_dir); 115 pgd_init((unsigned long)swapper_pg_dir);
116 pgd_init((unsigned long)swapper_pg_dir + 116 pgd_init((unsigned long)swapper_pg_dir +
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 16e13f663ab0..b27a506309ee 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -2175,7 +2175,7 @@ void __init ld_mmu_srmmu(void)
2175 2175
2176 BTFIXUPSET_CALL(pte_pfn, srmmu_pte_pfn, BTFIXUPCALL_NORM); 2176 BTFIXUPSET_CALL(pte_pfn, srmmu_pte_pfn, BTFIXUPCALL_NORM);
2177 BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); 2177 BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
2178 BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); 2178 BTFIXUPSET_CALL(pgd_page_vaddr, srmmu_pgd_page, BTFIXUPCALL_NORM);
2179 2179
2180 BTFIXUPSET_SETHI(none_mask, 0xF0000000); 2180 BTFIXUPSET_SETHI(none_mask, 0xF0000000);
2181 2181
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 7fdddf3c7e16..436021ceb2e7 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -2280,5 +2280,5 @@ void __init ld_mmu_sun4c(void)
2280 2280
2281 /* These should _never_ get called with two level tables. */ 2281 /* These should _never_ get called with two level tables. */
2282 BTFIXUPSET_CALL(pgd_set, sun4c_pgd_set, BTFIXUPCALL_NOP); 2282 BTFIXUPSET_CALL(pgd_set, sun4c_pgd_set, BTFIXUPCALL_NOP);
2283 BTFIXUPSET_CALL(pgd_page, sun4c_pgd_page, BTFIXUPCALL_RETO0); 2283 BTFIXUPSET_CALL(pgd_page_vaddr, sun4c_pgd_page, BTFIXUPCALL_RETO0);
2284} 2284}
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7218c754505b..e82764f75e7f 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -544,7 +544,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
544 544
545 ops = NULL; 545 ops = NULL;
546 data = NULL; 546 data = NULL;
547 for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ 547 for(i = 0; i < ARRAY_SIZE(chan_table); i++){
548 entry = &chan_table[i]; 548 entry = &chan_table[i];
549 if(!strncmp(str, entry->key, strlen(entry->key))){ 549 if(!strncmp(str, entry->key, strlen(entry->key))){
550 ops = entry->ops; 550 ops = entry->ops;
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index b414522f7686..79610b5ce67e 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -497,7 +497,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
497 } 497 }
498 498
499 error = NULL; 499 error = NULL;
500 size = sizeof(default_buf)/sizeof(default_buf[0]); 500 size = ARRAY_SIZE(default_buf);
501 buf = default_buf; 501 buf = default_buf;
502 502
503 while(1){ 503 while(1){
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 9bfd405c3bd8..5b2f5fe9e426 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -16,6 +16,7 @@
16#include "user.h" 16#include "user.h"
17#include "mconsole.h" 17#include "mconsole.h"
18#include "umid.h" 18#include "umid.h"
19#include "user_util.h"
19 20
20static struct mconsole_command commands[] = { 21static struct mconsole_command commands[] = {
21 /* With uts namespaces, uts information becomes process-specific, so 22 /* With uts namespaces, uts information becomes process-specific, so
@@ -65,14 +66,14 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
65 struct mconsole_command *cmd; 66 struct mconsole_command *cmd;
66 int i; 67 int i;
67 68
68 for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){ 69 for(i = 0; i < ARRAY_SIZE(commands); i++){
69 cmd = &commands[i]; 70 cmd = &commands[i];
70 if(!strncmp(req->request.data, cmd->command, 71 if(!strncmp(req->request.data, cmd->command,
71 strlen(cmd->command))){ 72 strlen(cmd->command))){
72 return(cmd); 73 return cmd;
73 } 74 }
74 } 75 }
75 return(NULL); 76 return NULL;
76} 77}
77 78
78#define MIN(a,b) ((a)<(b) ? (a):(b)) 79#define MIN(a,b) ((a)<(b) ? (a):(b))
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 501f95675d89..4a7966b21931 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -31,6 +31,11 @@
31#include "irq_user.h" 31#include "irq_user.h"
32#include "irq_kern.h" 32#include "irq_kern.h"
33 33
34static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
35{
36 memcpy(dev->dev_addr, addr, ETH_ALEN);
37}
38
34#define DRIVER_NAME "uml-netdev" 39#define DRIVER_NAME "uml-netdev"
35 40
36static DEFINE_SPINLOCK(opened_lock); 41static DEFINE_SPINLOCK(opened_lock);
@@ -242,7 +247,7 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
242 struct sockaddr *hwaddr = addr; 247 struct sockaddr *hwaddr = addr;
243 248
244 spin_lock(&lp->lock); 249 spin_lock(&lp->lock);
245 memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); 250 set_ether_mac(dev, hwaddr->sa_data);
246 spin_unlock(&lp->lock); 251 spin_unlock(&lp->lock);
247 252
248 return(0); 253 return(0);
@@ -790,13 +795,6 @@ void dev_ip_addr(void *d, unsigned char *bin_buf)
790 memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address)); 795 memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
791} 796}
792 797
793void set_ether_mac(void *d, unsigned char *addr)
794{
795 struct net_device *dev = d;
796
797 memcpy(dev->dev_addr, addr, ETH_ALEN);
798}
799
800struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) 798struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
801{ 799{
802 if((skb != NULL) && (skb_tailroom(skb) < extra)){ 800 if((skb != NULL) && (skb_tailroom(skb) < extra)){
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 466ff2c2f918..4c767c7adb96 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -76,7 +76,7 @@ int pcap_setup(char *str, char **mac_out, void *data)
76 if(host_if != NULL) 76 if(host_if != NULL)
77 init->host_if = host_if; 77 init->host_if = host_if;
78 78
79 for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){ 79 for(i = 0; i < ARRAY_SIZE(options); i++){
80 if(options[i] == NULL) 80 if(options[i] == NULL)
81 continue; 81 continue;
82 if(!strcmp(options[i], "promisc")) 82 if(!strcmp(options[i], "promisc"))
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index b98bdd8e052a..89e1dc835a5b 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -27,7 +27,6 @@ extern int ncpus;
27extern char *linux_prog; 27extern char *linux_prog;
28extern char *gdb_init; 28extern char *gdb_init;
29extern int kmalloc_ok; 29extern int kmalloc_ok;
30extern int timer_irq_inited;
31extern int jail; 30extern int jail;
32extern int nsyscalls; 31extern int nsyscalls;
33 32
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 1b5c0131a12e..e93c6d3e893b 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -1,9 +1,12 @@
1#ifndef __UML_LONGJMP_H 1#ifndef __UML_LONGJMP_H
2#define __UML_LONGJMP_H 2#define __UML_LONGJMP_H
3 3
4#include <setjmp.h> 4#include "sysdep/archsetjmp.h"
5#include "os.h" 5#include "os.h"
6 6
7extern int setjmp(jmp_buf);
8extern void longjmp(jmp_buf, int);
9
7#define UML_LONGJMP(buf, val) do { \ 10#define UML_LONGJMP(buf, val) do { \
8 longjmp(*buf, val); \ 11 longjmp(*buf, val); \
9} while(0) 12} while(0)
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 800c403920bc..47ef7cb49a8e 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -26,7 +26,6 @@ struct net_user_info {
26 26
27extern void ether_user_init(void *data, void *dev); 27extern void ether_user_init(void *data, void *dev);
28extern void dev_ip_addr(void *d, unsigned char *bin_buf); 28extern void dev_ip_addr(void *d, unsigned char *bin_buf);
29extern void set_ether_mac(void *d, unsigned char *addr);
30extern void iter_addresses(void *d, void (*cb)(unsigned char *, 29extern void iter_addresses(void *d, void (*cb)(unsigned char *,
31 unsigned char *, void *), 30 unsigned char *, void *),
32 void *arg); 31 void *arg);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 5316e8a4a4fd..24fb6d8680e1 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -276,9 +276,11 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
276 276
277extern void switch_timers(int to_real); 277extern void switch_timers(int to_real);
278extern void idle_sleep(int secs); 278extern void idle_sleep(int secs);
279extern int set_interval(int is_virtual);
280#ifdef CONFIG_MODE_TT
279extern void enable_timer(void); 281extern void enable_timer(void);
282#endif
280extern void disable_timer(void); 283extern void disable_timer(void);
281extern void user_time_init(void);
282extern void uml_idle_timer(void); 284extern void uml_idle_timer(void);
283extern unsigned long long os_nsecs(void); 285extern unsigned long long os_nsecs(void);
284 286
@@ -329,6 +331,7 @@ extern void os_set_ioignore(void);
329extern void init_irq_signals(int on_sigstack); 331extern void init_irq_signals(int on_sigstack);
330 332
331/* sigio.c */ 333/* sigio.c */
334extern int add_sigio_fd(int fd);
332extern int ignore_sigio_fd(int fd); 335extern int ignore_sigio_fd(int fd);
333extern void maybe_sigio_broken(int fd, int read); 336extern void maybe_sigio_broken(int fd, int read);
334 337
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 83b688ca198f..f845b3629a6d 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -7,6 +7,7 @@
7#define __REGISTERS_H 7#define __REGISTERS_H
8 8
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/archsetjmp.h"
10 11
11extern void init_thread_registers(union uml_pt_regs *to); 12extern void init_thread_registers(union uml_pt_regs *to);
12extern int save_fp_registers(int pid, unsigned long *fp_regs); 13extern int save_fp_registers(int pid, unsigned long *fp_regs);
@@ -15,6 +16,6 @@ extern void save_registers(int pid, union uml_pt_regs *regs);
15extern void restore_registers(int pid, union uml_pt_regs *regs); 16extern void restore_registers(int pid, union uml_pt_regs *regs);
16extern void init_registers(int pid); 17extern void init_registers(int pid);
17extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); 18extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs);
18extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer); 19extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
19 20
20#endif 21#endif
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
new file mode 100644
index 000000000000..ea1ba3d42aee
--- /dev/null
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -0,0 +1,19 @@
1/*
2 * arch/i386/include/klibc/archsetjmp.h
3 */
4
5#ifndef _KLIBC_ARCHSETJMP_H
6#define _KLIBC_ARCHSETJMP_H
7
8struct __jmp_buf {
9 unsigned int __ebx;
10 unsigned int __esp;
11 unsigned int __ebp;
12 unsigned int __esi;
13 unsigned int __edi;
14 unsigned int __eip;
15};
16
17typedef struct __jmp_buf jmp_buf[1];
18
19#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
deleted file mode 100644
index 07518b162136..000000000000
--- a/arch/um/include/sysdep-i386/signal.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
5
6#ifndef __I386_SIGNAL_H_
7#define __I386_SIGNAL_H_
8
9#include <signal.h>
10
11#define ARCH_SIGHDLR_PARAM int sig
12
13#define ARCH_GET_SIGCONTEXT(sc, sig) \
14 do sc = (struct sigcontext *) (&sig + 1); while(0)
15
16#endif
17
18/*
19 * Overrides for Emacs so that we follow Linus's tabbing style.
20 * Emacs will notice this stuff at the end of the file and automatically
21 * adjust the settings for this buffer only. This must remain at the end
22 * of the file.
23 * ---------------------------------------------------------------------------
24 * Local variables:
25 * c-file-style: "linux"
26 * End:
27 */
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
new file mode 100644
index 000000000000..454fc60aff6d
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -0,0 +1,21 @@
1/*
2 * arch/x86_64/include/klibc/archsetjmp.h
3 */
4
5#ifndef _KLIBC_ARCHSETJMP_H
6#define _KLIBC_ARCHSETJMP_H
7
8struct __jmp_buf {
9 unsigned long __rbx;
10 unsigned long __rsp;
11 unsigned long __rbp;
12 unsigned long __r12;
13 unsigned long __r13;
14 unsigned long __r14;
15 unsigned long __r15;
16 unsigned long __rip;
17};
18
19typedef struct __jmp_buf jmp_buf[1];
20
21#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
deleted file mode 100644
index 6142897af3d1..000000000000
--- a/arch/um/include/sysdep-x86_64/signal.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
5
6#ifndef __X86_64_SIGNAL_H_
7#define __X86_64_SIGNAL_H_
8
9#define ARCH_SIGHDLR_PARAM int sig
10
11#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
12 do { \
13 struct ucontext *__uc; \
14 asm("movq %%rdx, %0" : "=r" (__uc)); \
15 sc = (struct sigcontext *) &__uc->uc_mcontext; \
16 } while(0)
17
18#endif
19
20/*
21 * Overrides for Emacs so that we follow Linus's tabbing style.
22 * Emacs will notice this stuff at the end of the file and automatically
23 * adjust the settings for this buffer only. This must remain at the end
24 * of the file.
25 * ---------------------------------------------------------------------------
26 * Local variables:
27 * c-file-style: "linux"
28 * End:
29 */
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index fc38a6d5906d..0561c43b4685 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -41,9 +41,11 @@ static long execve1(char *file, char __user * __user *argv,
41 long error; 41 long error;
42 42
43#ifdef CONFIG_TTY_LOG 43#ifdef CONFIG_TTY_LOG
44 task_lock(current); 44 mutex_lock(&tty_mutex);
45 task_lock(current); /* FIXME: is this needed ? */
45 log_exec(argv, current->signal->tty); 46 log_exec(argv, current->signal->tty);
46 task_unlock(current); 47 task_unlock(current);
48 mutex_unlock(&tty_mutex);
47#endif 49#endif
48 error = do_execve(file, argv, env, &current->thread.regs); 50 error = do_execve(file, argv, env, &current->thread.regs);
49 if (error == 0){ 51 if (error == 0){
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 589c69a75043..ce7f233fc490 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -142,19 +142,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
142 .events = events, 142 .events = events,
143 .current_events = 0 } ); 143 .current_events = 0 } );
144 144
145 /* Critical section - locked by a spinlock because this stuff can
146 * be changed from interrupt handlers. The stuff above is done
147 * outside the lock because it allocates memory.
148 */
149
150 /* Actually, it only looks like it can be called from interrupt
151 * context. The culprit is reactivate_fd, which calls
152 * maybe_sigio_broken, which calls write_sigio_workaround,
153 * which calls activate_fd. However, write_sigio_workaround should
154 * only be called once, at boot time. That would make it clear that
155 * this is called only from process context, and can be locked with
156 * a semaphore.
157 */
158 spin_lock_irqsave(&irq_lock, flags); 145 spin_lock_irqsave(&irq_lock, flags);
159 for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { 146 for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
160 if ((irq_fd->fd == fd) && (irq_fd->type == type)) { 147 if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
@@ -165,7 +152,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
165 } 152 }
166 } 153 }
167 154
168 /*-------------*/
169 if (type == IRQ_WRITE) 155 if (type == IRQ_WRITE)
170 fd = -1; 156 fd = -1;
171 157
@@ -198,7 +184,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
198 184
199 spin_lock_irqsave(&irq_lock, flags); 185 spin_lock_irqsave(&irq_lock, flags);
200 } 186 }
201 /*-------------*/
202 187
203 *last_irq_ptr = new_fd; 188 *last_irq_ptr = new_fd;
204 last_irq_ptr = &new_fd->next; 189 last_irq_ptr = &new_fd->next;
@@ -210,14 +195,14 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
210 */ 195 */
211 maybe_sigio_broken(fd, (type == IRQ_READ)); 196 maybe_sigio_broken(fd, (type == IRQ_READ));
212 197
213 return(0); 198 return 0;
214 199
215 out_unlock: 200 out_unlock:
216 spin_unlock_irqrestore(&irq_lock, flags); 201 spin_unlock_irqrestore(&irq_lock, flags);
217 out_kfree: 202 out_kfree:
218 kfree(new_fd); 203 kfree(new_fd);
219 out: 204 out:
220 return(err); 205 return err;
221} 206}
222 207
223static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) 208static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
@@ -302,10 +287,7 @@ void reactivate_fd(int fd, int irqnum)
302 os_set_pollfd(i, irq->fd); 287 os_set_pollfd(i, irq->fd);
303 spin_unlock_irqrestore(&irq_lock, flags); 288 spin_unlock_irqrestore(&irq_lock, flags);
304 289
305 /* This calls activate_fd, so it has to be outside the critical 290 add_sigio_fd(fd);
306 * section.
307 */
308 maybe_sigio_broken(fd, (irq->type == IRQ_READ));
309} 291}
310 292
311void deactivate_fd(int fd, int irqnum) 293void deactivate_fd(int fd, int irqnum)
@@ -316,11 +298,15 @@ void deactivate_fd(int fd, int irqnum)
316 298
317 spin_lock_irqsave(&irq_lock, flags); 299 spin_lock_irqsave(&irq_lock, flags);
318 irq = find_irq_by_fd(fd, irqnum, &i); 300 irq = find_irq_by_fd(fd, irqnum, &i);
319 if (irq == NULL) 301 if(irq == NULL){
320 goto out; 302 spin_unlock_irqrestore(&irq_lock, flags);
303 return;
304 }
305
321 os_set_pollfd(i, -1); 306 os_set_pollfd(i, -1);
322 out:
323 spin_unlock_irqrestore(&irq_lock, flags); 307 spin_unlock_irqrestore(&irq_lock, flags);
308
309 ignore_sigio_fd(fd);
324} 310}
325 311
326int deactivate_all_fds(void) 312int deactivate_all_fds(void)
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 61280167c560..93121c6d26e5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -79,8 +79,10 @@ void mem_init(void)
79 79
80 /* this will put all low memory onto the freelists */ 80 /* this will put all low memory onto the freelists */
81 totalram_pages = free_all_bootmem(); 81 totalram_pages = free_all_bootmem();
82#ifdef CONFIG_HIGHMEM
82 totalhigh_pages = highmem >> PAGE_SHIFT; 83 totalhigh_pages = highmem >> PAGE_SHIFT;
83 totalram_pages += totalhigh_pages; 84 totalram_pages += totalhigh_pages;
85#endif
84 num_physpages = totalram_pages; 86 num_physpages = totalram_pages;
85 max_pfn = totalram_pages; 87 max_pfn = totalram_pages;
86 printk(KERN_INFO "Memory: %luk available\n", 88 printk(KERN_INFO "Memory: %luk available\n",
@@ -221,10 +223,13 @@ void paging_init(void)
221 223
222 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 224 empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
223 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); 225 empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
224 for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 226 for(i = 0; i < ARRAY_SIZE(zones_size); i++)
225 zones_size[i] = 0; 227 zones_size[i] = 0;
228
226 zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); 229 zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
230#ifdef CONFIG_HIGHMEM
227 zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; 231 zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
232#endif
228 free_area_init(zones_size); 233 free_area_init(zones_size);
229 234
230 /* 235 /*
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index f6a5a502120b..537895d68ad1 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -23,6 +23,7 @@
23#include "linux/proc_fs.h" 23#include "linux/proc_fs.h"
24#include "linux/ptrace.h" 24#include "linux/ptrace.h"
25#include "linux/random.h" 25#include "linux/random.h"
26#include "linux/personality.h"
26#include "asm/unistd.h" 27#include "asm/unistd.h"
27#include "asm/mman.h" 28#include "asm/mman.h"
28#include "asm/segment.h" 29#include "asm/segment.h"
@@ -476,7 +477,7 @@ int singlestepping(void * t)
476#ifndef arch_align_stack 477#ifndef arch_align_stack
477unsigned long arch_align_stack(unsigned long sp) 478unsigned long arch_align_stack(unsigned long sp)
478{ 479{
479 if (randomize_va_space) 480 if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
480 sp -= get_random_int() % 8192; 481 sp -= get_random_int() % 8192;
481 return sp & ~0xf; 482 return sp & ~0xf;
482} 483}
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 3ef73bf2e781..f602623644aa 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -22,7 +22,7 @@ static void kill_idlers(int me)
22 struct task_struct *p; 22 struct task_struct *p;
23 int i; 23 int i;
24 24
25 for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){ 25 for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
26 p = idle_threads[i]; 26 p = idle_threads[i];
27 if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) 27 if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
28 os_kill_process(p->thread.mode.tt.extern_pid, 0); 28 os_kill_process(p->thread.mode.tt.extern_pid, 0);
@@ -62,14 +62,3 @@ void machine_halt(void)
62{ 62{
63 machine_power_off(); 63 machine_power_off();
64} 64}
65
66/*
67 * Overrides for Emacs so that we follow Linus's tabbing style.
68 * Emacs will notice this stuff at the end of the file and automatically
69 * adjust the settings for this buffer only. This must remain at the end
70 * of the file.
71 * ---------------------------------------------------------------------------
72 * Local variables:
73 * c-file-style: "linux"
74 * End:
75 */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 624ca238d1fd..79c22707a637 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -55,7 +55,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
55 * destroy_context_skas. 55 * destroy_context_skas.
56 */ 56 */
57 57
58 mm->context.skas.last_page_table = pmd_page_kernel(*pmd); 58 mm->context.skas.last_page_table = pmd_page_vaddr(*pmd);
59#ifdef CONFIG_3_LEVEL_PGTABLES 59#ifdef CONFIG_3_LEVEL_PGTABLES
60 mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); 60 mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
61#endif 61#endif
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 552ca1cb9847..2454bbd9555d 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -35,9 +35,6 @@ unsigned long long sched_clock(void)
35 return (unsigned long long)jiffies_64 * (1000000000 / HZ); 35 return (unsigned long long)jiffies_64 * (1000000000 / HZ);
36} 36}
37 37
38/* Changed at early boot */
39int timer_irq_inited = 0;
40
41static unsigned long long prev_nsecs; 38static unsigned long long prev_nsecs;
42#ifdef CONFIG_UML_REAL_TIME_CLOCK 39#ifdef CONFIG_UML_REAL_TIME_CLOCK
43static long long delta; /* Deviation per interval */ 40static long long delta; /* Deviation per interval */
@@ -113,12 +110,13 @@ static void register_timer(void)
113 110
114 err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); 111 err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
115 if(err != 0) 112 if(err != 0)
116 printk(KERN_ERR "timer_init : request_irq failed - " 113 printk(KERN_ERR "register_timer : request_irq failed - "
117 "errno = %d\n", -err); 114 "errno = %d\n", -err);
118 115
119 timer_irq_inited = 1; 116 err = set_interval(1);
120 117 if(err != 0)
121 user_time_init(); 118 printk(KERN_ERR "register_timer : set_interval failed - "
119 "errno = %d\n", -err);
122} 120}
123 121
124extern void (*late_time_init)(void); 122extern void (*late_time_init)(void);
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f5b0636f9ad7..54a5ff25645a 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -16,12 +16,12 @@
16#include "os.h" 16#include "os.h"
17 17
18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 18static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
19 int r, int w, int x, struct host_vm_op *ops, int *index, 19 int r, int w, int x, struct host_vm_op *ops, int *index,
20 int last_filled, union mm_context *mmu, void **flush, 20 int last_filled, union mm_context *mmu, void **flush,
21 int (*do_ops)(union mm_context *, struct host_vm_op *, 21 int (*do_ops)(union mm_context *, struct host_vm_op *,
22 int, int, void **)) 22 int, int, void **))
23{ 23{
24 __u64 offset; 24 __u64 offset;
25 struct host_vm_op *last; 25 struct host_vm_op *last;
26 int fd, ret = 0; 26 int fd, ret = 0;
27 27
@@ -89,7 +89,7 @@ static int add_munmap(unsigned long addr, unsigned long len,
89static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, 89static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
90 int x, struct host_vm_op *ops, int *index, 90 int x, struct host_vm_op *ops, int *index,
91 int last_filled, union mm_context *mmu, void **flush, 91 int last_filled, union mm_context *mmu, void **flush,
92 int (*do_ops)(union mm_context *, struct host_vm_op *, 92 int (*do_ops)(union mm_context *, struct host_vm_op *,
93 int, int, void **)) 93 int, int, void **))
94{ 94{
95 struct host_vm_op *last; 95 struct host_vm_op *last;
@@ -124,105 +124,105 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
124#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) 124#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
125 125
126void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 126void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
127 unsigned long end_addr, int force, 127 unsigned long end_addr, int force,
128 int (*do_ops)(union mm_context *, struct host_vm_op *, 128 int (*do_ops)(union mm_context *, struct host_vm_op *,
129 int, int, void **)) 129 int, int, void **))
130{ 130{
131 pgd_t *npgd; 131 pgd_t *npgd;
132 pud_t *npud; 132 pud_t *npud;
133 pmd_t *npmd; 133 pmd_t *npmd;
134 pte_t *npte; 134 pte_t *npte;
135 union mm_context *mmu = &mm->context; 135 union mm_context *mmu = &mm->context;
136 unsigned long addr, end; 136 unsigned long addr, end;
137 int r, w, x; 137 int r, w, x;
138 struct host_vm_op ops[1]; 138 struct host_vm_op ops[1];
139 void *flush = NULL; 139 void *flush = NULL;
140 int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1; 140 int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
141 int ret = 0; 141 int ret = 0;
142 142
143 if(mm == NULL) return; 143 if(mm == NULL)
144 144 return;
145 ops[0].type = NONE; 145
146 for(addr = start_addr; addr < end_addr && !ret;){ 146 ops[0].type = NONE;
147 npgd = pgd_offset(mm, addr); 147 for(addr = start_addr; addr < end_addr && !ret;){
148 if(!pgd_present(*npgd)){ 148 npgd = pgd_offset(mm, addr);
149 end = ADD_ROUND(addr, PGDIR_SIZE); 149 if(!pgd_present(*npgd)){
150 if(end > end_addr) 150 end = ADD_ROUND(addr, PGDIR_SIZE);
151 end = end_addr; 151 if(end > end_addr)
152 if(force || pgd_newpage(*npgd)){ 152 end = end_addr;
153 ret = add_munmap(addr, end - addr, ops, 153 if(force || pgd_newpage(*npgd)){
154 &op_index, last_op, mmu, 154 ret = add_munmap(addr, end - addr, ops,
155 &flush, do_ops); 155 &op_index, last_op, mmu,
156 pgd_mkuptodate(*npgd); 156 &flush, do_ops);
157 } 157 pgd_mkuptodate(*npgd);
158 addr = end; 158 }
159 continue; 159 addr = end;
160 } 160 continue;
161 161 }
162 npud = pud_offset(npgd, addr); 162
163 if(!pud_present(*npud)){ 163 npud = pud_offset(npgd, addr);
164 end = ADD_ROUND(addr, PUD_SIZE); 164 if(!pud_present(*npud)){
165 if(end > end_addr) 165 end = ADD_ROUND(addr, PUD_SIZE);
166 end = end_addr; 166 if(end > end_addr)
167 if(force || pud_newpage(*npud)){ 167 end = end_addr;
168 ret = add_munmap(addr, end - addr, ops, 168 if(force || pud_newpage(*npud)){
169 &op_index, last_op, mmu, 169 ret = add_munmap(addr, end - addr, ops,
170 &flush, do_ops); 170 &op_index, last_op, mmu,
171 pud_mkuptodate(*npud); 171 &flush, do_ops);
172 } 172 pud_mkuptodate(*npud);
173 addr = end; 173 }
174 continue; 174 addr = end;
175 } 175 continue;
176 176 }
177 npmd = pmd_offset(npud, addr); 177
178 if(!pmd_present(*npmd)){ 178 npmd = pmd_offset(npud, addr);
179 end = ADD_ROUND(addr, PMD_SIZE); 179 if(!pmd_present(*npmd)){
180 if(end > end_addr) 180 end = ADD_ROUND(addr, PMD_SIZE);
181 end = end_addr; 181 if(end > end_addr)
182 if(force || pmd_newpage(*npmd)){ 182 end = end_addr;
183 ret = add_munmap(addr, end - addr, ops, 183 if(force || pmd_newpage(*npmd)){
184 &op_index, last_op, mmu, 184 ret = add_munmap(addr, end - addr, ops,
185 &flush, do_ops); 185 &op_index, last_op, mmu,
186 pmd_mkuptodate(*npmd); 186 &flush, do_ops);
187 } 187 pmd_mkuptodate(*npmd);
188 addr = end; 188 }
189 continue; 189 addr = end;
190 } 190 continue;
191 191 }
192 npte = pte_offset_kernel(npmd, addr); 192
193 r = pte_read(*npte); 193 npte = pte_offset_kernel(npmd, addr);
194 w = pte_write(*npte); 194 r = pte_read(*npte);
195 x = pte_exec(*npte); 195 w = pte_write(*npte);
196 x = pte_exec(*npte);
196 if (!pte_young(*npte)) { 197 if (!pte_young(*npte)) {
197 r = 0; 198 r = 0;
198 w = 0; 199 w = 0;
199 } else if (!pte_dirty(*npte)) { 200 } else if (!pte_dirty(*npte)) {
200 w = 0; 201 w = 0;
201 } 202 }
202 if(force || pte_newpage(*npte)){ 203 if(force || pte_newpage(*npte)){
203 if(pte_present(*npte)) 204 if(pte_present(*npte))
204 ret = add_mmap(addr, 205 ret = add_mmap(addr,
205 pte_val(*npte) & PAGE_MASK, 206 pte_val(*npte) & PAGE_MASK,
206 PAGE_SIZE, r, w, x, ops, 207 PAGE_SIZE, r, w, x, ops,
207 &op_index, last_op, mmu, 208 &op_index, last_op, mmu,
208 &flush, do_ops); 209 &flush, do_ops);
209 else ret = add_munmap(addr, PAGE_SIZE, ops, 210 else ret = add_munmap(addr, PAGE_SIZE, ops,
210 &op_index, last_op, mmu, 211 &op_index, last_op, mmu,
211 &flush, do_ops); 212 &flush, do_ops);
212 } 213 }
213 else if(pte_newprot(*npte)) 214 else if(pte_newprot(*npte))
214 ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, 215 ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
215 &op_index, last_op, mmu, 216 &op_index, last_op, mmu,
216 &flush, do_ops); 217 &flush, do_ops);
217 218
218 *npte = pte_mkuptodate(*npte); 219 *npte = pte_mkuptodate(*npte);
219 addr += PAGE_SIZE; 220 addr += PAGE_SIZE;
220 } 221 }
221
222 if(!ret) 222 if(!ret)
223 ret = (*do_ops)(mmu, ops, op_index, 1, &flush); 223 ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
224 224
225 /* This is not an else because ret is modified above */ 225/* This is not an else because ret is modified above */
226 if(ret) { 226 if(ret) {
227 printk("fix_range_common: failed, killing current process\n"); 227 printk("fix_range_common: failed, killing current process\n");
228 force_sig(SIGKILL, current); 228 force_sig(SIGKILL, current);
@@ -231,160 +231,160 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
231 231
232int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) 232int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
233{ 233{
234 struct mm_struct *mm; 234 struct mm_struct *mm;
235 pgd_t *pgd; 235 pgd_t *pgd;
236 pud_t *pud; 236 pud_t *pud;
237 pmd_t *pmd; 237 pmd_t *pmd;
238 pte_t *pte; 238 pte_t *pte;
239 unsigned long addr, last; 239 unsigned long addr, last;
240 int updated = 0, err; 240 int updated = 0, err;
241 241
242 mm = &init_mm; 242 mm = &init_mm;
243 for(addr = start; addr < end;){ 243 for(addr = start; addr < end;){
244 pgd = pgd_offset(mm, addr); 244 pgd = pgd_offset(mm, addr);
245 if(!pgd_present(*pgd)){ 245 if(!pgd_present(*pgd)){
246 last = ADD_ROUND(addr, PGDIR_SIZE); 246 last = ADD_ROUND(addr, PGDIR_SIZE);
247 if(last > end) 247 if(last > end)
248 last = end; 248 last = end;
249 if(pgd_newpage(*pgd)){ 249 if(pgd_newpage(*pgd)){
250 updated = 1; 250 updated = 1;
251 err = os_unmap_memory((void *) addr, 251 err = os_unmap_memory((void *) addr,
252 last - addr); 252 last - addr);
253 if(err < 0) 253 if(err < 0)
254 panic("munmap failed, errno = %d\n", 254 panic("munmap failed, errno = %d\n",
255 -err); 255 -err);
256 } 256 }
257 addr = last; 257 addr = last;
258 continue; 258 continue;
259 } 259 }
260 260
261 pud = pud_offset(pgd, addr); 261 pud = pud_offset(pgd, addr);
262 if(!pud_present(*pud)){ 262 if(!pud_present(*pud)){
263 last = ADD_ROUND(addr, PUD_SIZE); 263 last = ADD_ROUND(addr, PUD_SIZE);
264 if(last > end) 264 if(last > end)
265 last = end; 265 last = end;
266 if(pud_newpage(*pud)){ 266 if(pud_newpage(*pud)){
267 updated = 1; 267 updated = 1;
268 err = os_unmap_memory((void *) addr, 268 err = os_unmap_memory((void *) addr,
269 last - addr); 269 last - addr);
270 if(err < 0) 270 if(err < 0)
271 panic("munmap failed, errno = %d\n", 271 panic("munmap failed, errno = %d\n",
272 -err); 272 -err);
273 } 273 }
274 addr = last; 274 addr = last;
275 continue; 275 continue;
276 } 276 }
277 277
278 pmd = pmd_offset(pud, addr); 278 pmd = pmd_offset(pud, addr);
279 if(!pmd_present(*pmd)){ 279 if(!pmd_present(*pmd)){
280 last = ADD_ROUND(addr, PMD_SIZE); 280 last = ADD_ROUND(addr, PMD_SIZE);
281 if(last > end) 281 if(last > end)
282 last = end; 282 last = end;
283 if(pmd_newpage(*pmd)){ 283 if(pmd_newpage(*pmd)){
284 updated = 1; 284 updated = 1;
285 err = os_unmap_memory((void *) addr, 285 err = os_unmap_memory((void *) addr,
286 last - addr); 286 last - addr);
287 if(err < 0) 287 if(err < 0)
288 panic("munmap failed, errno = %d\n", 288 panic("munmap failed, errno = %d\n",
289 -err); 289 -err);
290 } 290 }
291 addr = last; 291 addr = last;
292 continue; 292 continue;
293 } 293 }
294 294
295 pte = pte_offset_kernel(pmd, addr); 295 pte = pte_offset_kernel(pmd, addr);
296 if(!pte_present(*pte) || pte_newpage(*pte)){ 296 if(!pte_present(*pte) || pte_newpage(*pte)){
297 updated = 1; 297 updated = 1;
298 err = os_unmap_memory((void *) addr, 298 err = os_unmap_memory((void *) addr,
299 PAGE_SIZE); 299 PAGE_SIZE);
300 if(err < 0) 300 if(err < 0)
301 panic("munmap failed, errno = %d\n", 301 panic("munmap failed, errno = %d\n",
302 -err); 302 -err);
303 if(pte_present(*pte)) 303 if(pte_present(*pte))
304 map_memory(addr, 304 map_memory(addr,
305 pte_val(*pte) & PAGE_MASK, 305 pte_val(*pte) & PAGE_MASK,
306 PAGE_SIZE, 1, 1, 1); 306 PAGE_SIZE, 1, 1, 1);
307 } 307 }
308 else if(pte_newprot(*pte)){ 308 else if(pte_newprot(*pte)){
309 updated = 1; 309 updated = 1;
310 os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); 310 os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
311 } 311 }
312 addr += PAGE_SIZE; 312 addr += PAGE_SIZE;
313 } 313 }
314 return(updated); 314 return(updated);
315} 315}
316 316
317pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) 317pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
318{ 318{
319 return(pgd_offset(mm, address)); 319 return(pgd_offset(mm, address));
320} 320}
321 321
322pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) 322pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
323{ 323{
324 return(pud_offset(pgd, address)); 324 return(pud_offset(pgd, address));
325} 325}
326 326
327pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) 327pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
328{ 328{
329 return(pmd_offset(pud, address)); 329 return(pmd_offset(pud, address));
330} 330}
331 331
332pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) 332pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
333{ 333{
334 return(pte_offset_kernel(pmd, address)); 334 return(pte_offset_kernel(pmd, address));
335} 335}
336 336
337pte_t *addr_pte(struct task_struct *task, unsigned long addr) 337pte_t *addr_pte(struct task_struct *task, unsigned long addr)
338{ 338{
339 pgd_t *pgd = pgd_offset(task->mm, addr); 339 pgd_t *pgd = pgd_offset(task->mm, addr);
340 pud_t *pud = pud_offset(pgd, addr); 340 pud_t *pud = pud_offset(pgd, addr);
341 pmd_t *pmd = pmd_offset(pud, addr); 341 pmd_t *pmd = pmd_offset(pud, addr);
342 342
343 return(pte_offset_map(pmd, addr)); 343 return(pte_offset_map(pmd, addr));
344} 344}
345 345
346void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) 346void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
347{ 347{
348 address &= PAGE_MASK; 348 address &= PAGE_MASK;
349 flush_tlb_range(vma, address, address + PAGE_SIZE); 349 flush_tlb_range(vma, address, address + PAGE_SIZE);
350} 350}
351 351
352void flush_tlb_all(void) 352void flush_tlb_all(void)
353{ 353{
354 flush_tlb_mm(current->mm); 354 flush_tlb_mm(current->mm);
355} 355}
356 356
357void flush_tlb_kernel_range(unsigned long start, unsigned long end) 357void flush_tlb_kernel_range(unsigned long start, unsigned long end)
358{ 358{
359 CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, 359 CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
360 flush_tlb_kernel_range_common, start, end); 360 flush_tlb_kernel_range_common, start, end);
361} 361}
362 362
363void flush_tlb_kernel_vm(void) 363void flush_tlb_kernel_vm(void)
364{ 364{
365 CHOOSE_MODE(flush_tlb_kernel_vm_tt(), 365 CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
366 flush_tlb_kernel_range_common(start_vm, end_vm)); 366 flush_tlb_kernel_range_common(start_vm, end_vm));
367} 367}
368 368
369void __flush_tlb_one(unsigned long addr) 369void __flush_tlb_one(unsigned long addr)
370{ 370{
371 CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); 371 CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
372} 372}
373 373
374void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 374void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
375 unsigned long end) 375 unsigned long end)
376{ 376{
377 CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, 377 CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
378 end); 378 end);
379} 379}
380 380
381void flush_tlb_mm(struct mm_struct *mm) 381void flush_tlb_mm(struct mm_struct *mm)
382{ 382{
383 CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); 383 CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
384} 384}
385 385
386void force_flush_all(void) 386void force_flush_all(void)
387{ 387{
388 CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); 388 CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
389} 389}
390 390
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index ac70fa5a2e2a..e5eeaf2b6af1 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -227,9 +227,16 @@ void bad_segv(struct faultinfo fi, unsigned long ip)
227 227
228void relay_signal(int sig, union uml_pt_regs *regs) 228void relay_signal(int sig, union uml_pt_regs *regs)
229{ 229{
230 if(arch_handle_signal(sig, regs)) return; 230 if(arch_handle_signal(sig, regs))
231 if(!UPT_IS_USER(regs)) 231 return;
232
233 if(!UPT_IS_USER(regs)){
234 if(sig == SIGBUS)
235 printk("Bus error - the /dev/shm or /tmp mount likely "
236 "just ran out of space\n");
232 panic("Kernel mode signal %d", sig); 237 panic("Kernel mode signal %d", sig);
238 }
239
233 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 240 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
234 force_sig(sig, current); 241 force_sig(sig, current);
235} 242}
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6987d1d247a2..cd15b9df5b5c 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -42,7 +42,7 @@ static int helper_child(void *arg)
42 if(data->pre_exec != NULL) 42 if(data->pre_exec != NULL)
43 (*data->pre_exec)(data->pre_data); 43 (*data->pre_exec)(data->pre_data);
44 execvp(argv[0], argv); 44 execvp(argv[0], argv);
45 errval = errno; 45 errval = -errno;
46 printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); 46 printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
47 os_write_file(data->fd, &errval, sizeof(errval)); 47 os_write_file(data->fd, &errval, sizeof(errval));
48 kill(os_getpid(), SIGKILL); 48 kill(os_getpid(), SIGKILL);
@@ -62,7 +62,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
62 stack = *stack_out; 62 stack = *stack_out;
63 else stack = alloc_stack(0, __cant_sleep()); 63 else stack = alloc_stack(0, __cant_sleep());
64 if(stack == 0) 64 if(stack == 0)
65 return(-ENOMEM); 65 return -ENOMEM;
66 66
67 ret = os_pipe(fds, 1, 0); 67 ret = os_pipe(fds, 1, 0);
68 if(ret < 0){ 68 if(ret < 0){
@@ -95,16 +95,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
95 /* Read the errno value from the child, if the exec failed, or get 0 if 95 /* Read the errno value from the child, if the exec failed, or get 0 if
96 * the exec succeeded because the pipe fd was set as close-on-exec. */ 96 * the exec succeeded because the pipe fd was set as close-on-exec. */
97 n = os_read_file(fds[0], &ret, sizeof(ret)); 97 n = os_read_file(fds[0], &ret, sizeof(ret));
98 if (n < 0) { 98 if(n == 0)
99 printk("run_helper : read on pipe failed, ret = %d\n", -n);
100 ret = n;
101 kill(pid, SIGKILL);
102 CATCH_EINTR(waitpid(pid, NULL, 0));
103 } else if(n != 0){
104 CATCH_EINTR(n = waitpid(pid, NULL, 0));
105 ret = -errno;
106 } else {
107 ret = pid; 99 ret = pid;
100 else {
101 if(n < 0){
102 printk("run_helper : read on pipe failed, ret = %d\n",
103 -n);
104 ret = n;
105 kill(pid, SIGKILL);
106 }
107 CATCH_EINTR(waitpid(pid, NULL, 0));
108 } 108 }
109 109
110out_close: 110out_close:
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 7555bf9c33d9..a97206df5b52 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -132,7 +132,7 @@ void os_set_pollfd(int i, int fd)
132 132
133void os_set_ioignore(void) 133void os_set_ioignore(void)
134{ 134{
135 set_handler(SIGIO, SIG_IGN, 0, -1); 135 signal(SIGIO, SIG_IGN);
136} 136}
137 137
138void init_irq_signals(int on_sigstack) 138void init_irq_signals(int on_sigstack)
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 90912aaca7aa..d1c5670787dc 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -67,13 +67,32 @@ static __init void do_uml_initcalls(void)
67 67
68static void last_ditch_exit(int sig) 68static void last_ditch_exit(int sig)
69{ 69{
70 signal(SIGINT, SIG_DFL);
71 signal(SIGTERM, SIG_DFL);
72 signal(SIGHUP, SIG_DFL);
73 uml_cleanup(); 70 uml_cleanup();
74 exit(1); 71 exit(1);
75} 72}
76 73
74static void install_fatal_handler(int sig)
75{
76 struct sigaction action;
77
78 /* All signals are enabled in this handler ... */
79 sigemptyset(&action.sa_mask);
80
81 /* ... including the signal being handled, plus we want the
82 * handler reset to the default behavior, so that if an exit
83 * handler is hanging for some reason, the UML will just die
84 * after this signal is sent a second time.
85 */
86 action.sa_flags = SA_RESETHAND | SA_NODEFER;
87 action.sa_restorer = NULL;
88 action.sa_handler = last_ditch_exit;
89 if(sigaction(sig, &action, NULL) < 0){
90 printf("failed to install handler for signal %d - errno = %d\n",
91 errno);
92 exit(1);
93 }
94}
95
77#define UML_LIB_PATH ":/usr/lib/uml" 96#define UML_LIB_PATH ":/usr/lib/uml"
78 97
79static void setup_env_path(void) 98static void setup_env_path(void)
@@ -158,9 +177,12 @@ int main(int argc, char **argv, char **envp)
158 } 177 }
159 new_argv[argc] = NULL; 178 new_argv[argc] = NULL;
160 179
161 set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); 180 /* Allow these signals to bring down a UML if all other
162 set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); 181 * methods of control fail.
163 set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); 182 */
183 install_fatal_handler(SIGINT);
184 install_fatal_handler(SIGTERM);
185 install_fatal_handler(SIGHUP);
164 186
165 scan_elf_aux( envp); 187 scan_elf_aux( envp);
166 188
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 560c8063c77c..b170b4704dc4 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -114,14 +114,14 @@ static void which_tmpdir(void)
114 } 114 }
115 115
116 while(1){ 116 while(1){
117 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); 117 found = next(fd, buf, ARRAY_SIZE(buf), ' ');
118 if(found != 1) 118 if(found != 1)
119 break; 119 break;
120 120
121 if(!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) 121 if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
122 goto found; 122 goto found;
123 123
124 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n'); 124 found = next(fd, buf, ARRAY_SIZE(buf), '\n');
125 if(found != 1) 125 if(found != 1)
126 break; 126 break;
127 } 127 }
@@ -135,7 +135,7 @@ err:
135 return; 135 return;
136 136
137found: 137found:
138 found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); 138 found = next(fd, buf, ARRAY_SIZE(buf), ' ');
139 if(found != 1) 139 if(found != 1)
140 goto err; 140 goto err;
141 141
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index b98d3ca2cd1b..ff203625a4bd 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,7 +7,6 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <errno.h> 8#include <errno.h>
9#include <signal.h> 9#include <signal.h>
10#include <setjmp.h>
11#include <linux/unistd.h> 10#include <linux/unistd.h>
12#include <sys/mman.h> 11#include <sys/mman.h>
13#include <sys/wait.h> 12#include <sys/wait.h>
@@ -247,7 +246,17 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
247 set_sigstack(sig_stack, pages * page_size()); 246 set_sigstack(sig_stack, pages * page_size());
248 flags = SA_ONSTACK; 247 flags = SA_ONSTACK;
249 } 248 }
250 if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); 249 if(usr1_handler){
250 struct sigaction sa;
251
252 sa.sa_handler = usr1_handler;
253 sigemptyset(&sa.sa_mask);
254 sa.sa_flags = flags;
255 sa.sa_restorer = NULL;
256 if(sigaction(SIGUSR1, &sa, NULL) < 0)
257 panic("init_new_thread_stack - sigaction failed - "
258 "errno = %d\n", errno);
259 }
251} 260}
252 261
253void init_new_thread_signals(void) 262void init_new_thread_signals(void)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 0ecac563c7b3..f6457765b17d 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -43,17 +43,9 @@ struct pollfds {
43/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread 43/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
44 * synchronizes with it. 44 * synchronizes with it.
45 */ 45 */
46static struct pollfds current_poll = { 46static struct pollfds current_poll;
47 .poll = NULL, 47static struct pollfds next_poll;
48 .size = 0, 48static struct pollfds all_sigio_fds;
49 .used = 0
50};
51
52static struct pollfds next_poll = {
53 .poll = NULL,
54 .size = 0,
55 .used = 0
56};
57 49
58static int write_sigio_thread(void *unused) 50static int write_sigio_thread(void *unused)
59{ 51{
@@ -78,7 +70,8 @@ static int write_sigio_thread(void *unused)
78 n = os_read_file(sigio_private[1], &c, sizeof(c)); 70 n = os_read_file(sigio_private[1], &c, sizeof(c));
79 if(n != sizeof(c)) 71 if(n != sizeof(c))
80 printk("write_sigio_thread : " 72 printk("write_sigio_thread : "
81 "read failed, err = %d\n", -n); 73 "read on socket failed, "
74 "err = %d\n", -n);
82 tmp = current_poll; 75 tmp = current_poll;
83 current_poll = next_poll; 76 current_poll = next_poll;
84 next_poll = tmp; 77 next_poll = tmp;
@@ -93,35 +86,36 @@ static int write_sigio_thread(void *unused)
93 86
94 n = os_write_file(respond_fd, &c, sizeof(c)); 87 n = os_write_file(respond_fd, &c, sizeof(c));
95 if(n != sizeof(c)) 88 if(n != sizeof(c))
96 printk("write_sigio_thread : write failed, " 89 printk("write_sigio_thread : write on socket "
97 "err = %d\n", -n); 90 "failed, err = %d\n", -n);
98 } 91 }
99 } 92 }
100 93
101 return 0; 94 return 0;
102} 95}
103 96
104static int need_poll(int n) 97static int need_poll(struct pollfds *polls, int n)
105{ 98{
106 if(n <= next_poll.size){ 99 if(n <= polls->size){
107 next_poll.used = n; 100 polls->used = n;
108 return(0); 101 return 0;
109 } 102 }
110 kfree(next_poll.poll); 103 kfree(polls->poll);
111 next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); 104 polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
112 if(next_poll.poll == NULL){ 105 if(polls->poll == NULL){
113 printk("need_poll : failed to allocate new pollfds\n"); 106 printk("need_poll : failed to allocate new pollfds\n");
114 next_poll.size = 0; 107 polls->size = 0;
115 next_poll.used = 0; 108 polls->used = 0;
116 return(-1); 109 return -ENOMEM;
117 } 110 }
118 next_poll.size = n; 111 polls->size = n;
119 next_poll.used = n; 112 polls->used = n;
120 return(0); 113 return 0;
121} 114}
122 115
123/* Must be called with sigio_lock held, because it's needed by the marked 116/* Must be called with sigio_lock held, because it's needed by the marked
124 * critical section. */ 117 * critical section.
118 */
125static void update_thread(void) 119static void update_thread(void)
126{ 120{
127 unsigned long flags; 121 unsigned long flags;
@@ -156,34 +150,39 @@ static void update_thread(void)
156 set_signals(flags); 150 set_signals(flags);
157} 151}
158 152
159static int add_sigio_fd(int fd, int read) 153int add_sigio_fd(int fd)
160{ 154{
161 int err = 0, i, n, events; 155 struct pollfd *p;
156 int err = 0, i, n;
162 157
163 sigio_lock(); 158 sigio_lock();
159 for(i = 0; i < all_sigio_fds.used; i++){
160 if(all_sigio_fds.poll[i].fd == fd)
161 break;
162 }
163 if(i == all_sigio_fds.used)
164 goto out;
165
166 p = &all_sigio_fds.poll[i];
167
164 for(i = 0; i < current_poll.used; i++){ 168 for(i = 0; i < current_poll.used; i++){
165 if(current_poll.poll[i].fd == fd) 169 if(current_poll.poll[i].fd == fd)
166 goto out; 170 goto out;
167 } 171 }
168 172
169 n = current_poll.used + 1; 173 n = current_poll.used + 1;
170 err = need_poll(n); 174 err = need_poll(&next_poll, n);
171 if(err) 175 if(err)
172 goto out; 176 goto out;
173 177
174 for(i = 0; i < current_poll.used; i++) 178 for(i = 0; i < current_poll.used; i++)
175 next_poll.poll[i] = current_poll.poll[i]; 179 next_poll.poll[i] = current_poll.poll[i];
176 180
177 if(read) events = POLLIN; 181 next_poll.poll[n - 1] = *p;
178 else events = POLLOUT;
179
180 next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
181 .events = events,
182 .revents = 0 });
183 update_thread(); 182 update_thread();
184 out: 183 out:
185 sigio_unlock(); 184 sigio_unlock();
186 return(err); 185 return err;
187} 186}
188 187
189int ignore_sigio_fd(int fd) 188int ignore_sigio_fd(int fd)
@@ -205,18 +204,14 @@ int ignore_sigio_fd(int fd)
205 if(i == current_poll.used) 204 if(i == current_poll.used)
206 goto out; 205 goto out;
207 206
208 err = need_poll(current_poll.used - 1); 207 err = need_poll(&next_poll, current_poll.used - 1);
209 if(err) 208 if(err)
210 goto out; 209 goto out;
211 210
212 for(i = 0; i < current_poll.used; i++){ 211 for(i = 0; i < current_poll.used; i++){
213 p = &current_poll.poll[i]; 212 p = &current_poll.poll[i];
214 if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; 213 if(p->fd != fd)
215 } 214 next_poll.poll[n++] = *p;
216 if(n == i){
217 printk("ignore_sigio_fd : fd %d not found\n", fd);
218 err = -1;
219 goto out;
220 } 215 }
221 216
222 update_thread(); 217 update_thread();
@@ -234,7 +229,7 @@ static struct pollfd *setup_initial_poll(int fd)
234 printk("setup_initial_poll : failed to allocate poll\n"); 229 printk("setup_initial_poll : failed to allocate poll\n");
235 return NULL; 230 return NULL;
236 } 231 }
237 *p = ((struct pollfd) { .fd = fd, 232 *p = ((struct pollfd) { .fd = fd,
238 .events = POLLIN, 233 .events = POLLIN,
239 .revents = 0 }); 234 .revents = 0 });
240 return p; 235 return p;
@@ -323,6 +318,8 @@ out_close1:
323 318
324void maybe_sigio_broken(int fd, int read) 319void maybe_sigio_broken(int fd, int read)
325{ 320{
321 int err;
322
326 if(!isatty(fd)) 323 if(!isatty(fd))
327 return; 324 return;
328 325
@@ -330,7 +327,19 @@ void maybe_sigio_broken(int fd, int read)
330 return; 327 return;
331 328
332 write_sigio_workaround(); 329 write_sigio_workaround();
333 add_sigio_fd(fd, read); 330
331 sigio_lock();
332 err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
333 if(err){
334 printk("maybe_sigio_broken - failed to add pollfd\n");
335 goto out;
336 }
337 all_sigio_fds.poll[all_sigio_fds.used++] =
338 ((struct pollfd) { .fd = fd,
339 .events = read ? POLLIN : POLLOUT,
340 .revents = 0 });
341out:
342 sigio_unlock();
334} 343}
335 344
336static void sigio_cleanup(void) 345static void sigio_cleanup(void)
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 60e4faedf254..6b81739279d1 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,7 +15,6 @@
15#include "user.h" 15#include "user.h"
16#include "signal_kern.h" 16#include "signal_kern.h"
17#include "sysdep/sigcontext.h" 17#include "sysdep/sigcontext.h"
18#include "sysdep/signal.h"
19#include "sigcontext.h" 18#include "sigcontext.h"
20#include "mode.h" 19#include "mode.h"
21#include "os.h" 20#include "os.h"
@@ -38,18 +37,10 @@
38static int signals_enabled = 1; 37static int signals_enabled = 1;
39static int pending = 0; 38static int pending = 0;
40 39
41void sig_handler(ARCH_SIGHDLR_PARAM) 40void sig_handler(int sig, struct sigcontext *sc)
42{ 41{
43 struct sigcontext *sc;
44 int enabled; 42 int enabled;
45 43
46 /* Must be the first thing that this handler does - x86_64 stores
47 * the sigcontext in %rdx, and we need to save it before it has a
48 * chance to get trashed.
49 */
50
51 ARCH_GET_SIGCONTEXT(sc, sig);
52
53 enabled = signals_enabled; 44 enabled = signals_enabled;
54 if(!enabled && (sig == SIGIO)){ 45 if(!enabled && (sig == SIGIO)){
55 pending |= SIGIO_MASK; 46 pending |= SIGIO_MASK;
@@ -64,15 +55,8 @@ void sig_handler(ARCH_SIGHDLR_PARAM)
64 set_signals(enabled); 55 set_signals(enabled);
65} 56}
66 57
67extern int timer_irq_inited;
68
69static void real_alarm_handler(int sig, struct sigcontext *sc) 58static void real_alarm_handler(int sig, struct sigcontext *sc)
70{ 59{
71 if(!timer_irq_inited){
72 signals_enabled = 1;
73 return;
74 }
75
76 if(sig == SIGALRM) 60 if(sig == SIGALRM)
77 switch_timers(0); 61 switch_timers(0);
78 62
@@ -84,13 +68,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc)
84 68
85} 69}
86 70
87void alarm_handler(ARCH_SIGHDLR_PARAM) 71void alarm_handler(int sig, struct sigcontext *sc)
88{ 72{
89 struct sigcontext *sc;
90 int enabled; 73 int enabled;
91 74
92 ARCH_GET_SIGCONTEXT(sc, sig);
93
94 enabled = signals_enabled; 75 enabled = signals_enabled;
95 if(!signals_enabled){ 76 if(!signals_enabled){
96 if(sig == SIGVTALRM) 77 if(sig == SIGVTALRM)
@@ -126,6 +107,10 @@ void remove_sigstack(void)
126 panic("disabling signal stack failed, errno = %d\n", errno); 107 panic("disabling signal stack failed, errno = %d\n", errno);
127} 108}
128 109
110void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
111
112extern void hard_handler(int sig);
113
129void set_handler(int sig, void (*handler)(int), int flags, ...) 114void set_handler(int sig, void (*handler)(int), int flags, ...)
130{ 115{
131 struct sigaction action; 116 struct sigaction action;
@@ -133,13 +118,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
133 sigset_t sig_mask; 118 sigset_t sig_mask;
134 int mask; 119 int mask;
135 120
136 va_start(ap, flags); 121 handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
137 action.sa_handler = handler; 122 action.sa_handler = hard_handler;
123
138 sigemptyset(&action.sa_mask); 124 sigemptyset(&action.sa_mask);
139 while((mask = va_arg(ap, int)) != -1){ 125
126 va_start(ap, flags);
127 while((mask = va_arg(ap, int)) != -1)
140 sigaddset(&action.sa_mask, mask); 128 sigaddset(&action.sa_mask, mask);
141 }
142 va_end(ap); 129 va_end(ap);
130
143 action.sa_flags = flags; 131 action.sa_flags = flags;
144 action.sa_restorer = NULL; 132 action.sa_restorer = NULL;
145 if(sigaction(sig, &action, NULL) < 0) 133 if(sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 7baf90fda58b..42e3d1ed802c 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <errno.h> 9#include <errno.h>
10#include <signal.h> 10#include <signal.h>
11#include <setjmp.h>
12#include <sched.h> 11#include <sched.h>
13#include "ptrace_user.h" 12#include "ptrace_user.h"
14#include <sys/wait.h> 13#include <sys/wait.h>
@@ -156,11 +155,15 @@ extern int __syscall_stub_start;
156static int userspace_tramp(void *stack) 155static int userspace_tramp(void *stack)
157{ 156{
158 void *addr; 157 void *addr;
158 int err;
159 159
160 ptrace(PTRACE_TRACEME, 0, 0, 0); 160 ptrace(PTRACE_TRACEME, 0, 0, 0);
161 161
162 init_new_thread_signals(); 162 init_new_thread_signals();
163 enable_timer(); 163 err = set_interval(1);
164 if(err)
165 panic("userspace_tramp - setting timer failed, errno = %d\n",
166 err);
164 167
165 if(!proc_mm){ 168 if(!proc_mm){
166 /* This has a pte, but it can't be mapped in with the usual 169 /* This has a pte, but it can't be mapped in with the usual
@@ -190,14 +193,25 @@ static int userspace_tramp(void *stack)
190 } 193 }
191 } 194 }
192 if(!ptrace_faultinfo && (stack != NULL)){ 195 if(!ptrace_faultinfo && (stack != NULL)){
196 struct sigaction sa;
197
193 unsigned long v = UML_CONFIG_STUB_CODE + 198 unsigned long v = UML_CONFIG_STUB_CODE +
194 (unsigned long) stub_segv_handler - 199 (unsigned long) stub_segv_handler -
195 (unsigned long) &__syscall_stub_start; 200 (unsigned long) &__syscall_stub_start;
196 201
197 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); 202 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
198 set_handler(SIGSEGV, (void *) v, SA_ONSTACK, 203 sigemptyset(&sa.sa_mask);
199 SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, 204 sigaddset(&sa.sa_mask, SIGIO);
200 SIGUSR1, -1); 205 sigaddset(&sa.sa_mask, SIGWINCH);
206 sigaddset(&sa.sa_mask, SIGALRM);
207 sigaddset(&sa.sa_mask, SIGVTALRM);
208 sigaddset(&sa.sa_mask, SIGUSR1);
209 sa.sa_flags = SA_ONSTACK;
210 sa.sa_handler = (void *) v;
211 sa.sa_restorer = NULL;
212 if(sigaction(SIGSEGV, &sa, NULL) < 0)
213 panic("userspace_tramp - setting SIGSEGV handler "
214 "failed - errno = %d\n", errno);
201 } 215 }
202 216
203 os_stop_process(os_getpid()); 217 os_stop_process(os_getpid());
@@ -470,7 +484,7 @@ void thread_wait(void *sw, void *fb)
470 *switch_buf = &buf; 484 *switch_buf = &buf;
471 fork_buf = fb; 485 fork_buf = fb;
472 if(UML_SETJMP(&buf) == 0) 486 if(UML_SETJMP(&buf) == 0)
473 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); 487 UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
474} 488}
475 489
476void switch_threads(void *me, void *next) 490void switch_threads(void *me, void *next)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 503148504009..7fe92680c7dd 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -14,7 +14,6 @@
14#include <sched.h> 14#include <sched.h>
15#include <fcntl.h> 15#include <fcntl.h>
16#include <errno.h> 16#include <errno.h>
17#include <setjmp.h>
18#include <sys/time.h> 17#include <sys/time.h>
19#include <sys/wait.h> 18#include <sys/wait.h>
20#include <sys/mman.h> 19#include <sys/mman.h>
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index b3213613c41c..37806621b25d 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-$(CONFIG_MODE_SKAS) = registers.o tls.o 6obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
7 7
8USER_OBJS := $(obj-y) 8USER_OBJS := $(obj-y)
9 9
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 516f66dd87e3..7cd0369e02b3 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,12 +5,12 @@
5 5
6#include <errno.h> 6#include <errno.h>
7#include <string.h> 7#include <string.h>
8#include <setjmp.h>
9#include "sysdep/ptrace_user.h" 8#include "sysdep/ptrace_user.h"
10#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
11#include "uml-config.h" 10#include "uml-config.h"
12#include "skas_ptregs.h" 11#include "skas_ptregs.h"
13#include "registers.h" 12#include "registers.h"
13#include "longjmp.h"
14#include "user.h" 14#include "user.h"
15 15
16/* These are set once at boot time and not changed thereafter */ 16/* These are set once at boot time and not changed thereafter */
@@ -130,11 +130,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
130 HOST_FP_SIZE * sizeof(unsigned long)); 130 HOST_FP_SIZE * sizeof(unsigned long));
131} 131}
132 132
133void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) 133unsigned long get_thread_reg(int reg, jmp_buf *buf)
134{ 134{
135 struct __jmp_buf_tag *jmpbuf = buffer; 135 switch(reg){
136 136 case EIP: return buf[0]->__eip;
137 UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); 137 case UESP: return buf[0]->__esp;
138 UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); 138 case EBP: return buf[0]->__ebp;
139 UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); 139 default:
140 printk("get_thread_regs - unknown register %d\n", reg);
141 return 0;
142 }
140} 143}
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
new file mode 100644
index 000000000000..0d3eae518352
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -0,0 +1,15 @@
1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7
8extern void (*handlers[])(int sig, struct sigcontext *sc);
9
10void hard_handler(int sig)
11{
12 struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
13
14 (*handlers[sig])(sig, sc);
15}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index 340ef26f5944..f67842a7735b 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-$(CONFIG_MODE_SKAS) = registers.o 6obj-$(CONFIG_MODE_SKAS) = registers.o signal.o
7 7
8USER_OBJS := $(obj-y) 8USER_OBJS := $(obj-y)
9 9
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index becd898d9398..cb8e8a263280 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -5,11 +5,11 @@
5 5
6#include <errno.h> 6#include <errno.h>
7#include <string.h> 7#include <string.h>
8#include <setjmp.h>
9#include "ptrace_user.h" 8#include "ptrace_user.h"
10#include "uml-config.h" 9#include "uml-config.h"
11#include "skas_ptregs.h" 10#include "skas_ptregs.h"
12#include "registers.h" 11#include "registers.h"
12#include "longjmp.h"
13#include "user.h" 13#include "user.h"
14 14
15/* These are set once at boot time and not changed thereafter */ 15/* These are set once at boot time and not changed thereafter */
@@ -78,11 +78,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
78 HOST_FP_SIZE * sizeof(unsigned long)); 78 HOST_FP_SIZE * sizeof(unsigned long));
79} 79}
80 80
81void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) 81unsigned long get_thread_reg(int reg, jmp_buf *buf)
82{ 82{
83 struct __jmp_buf_tag *jmpbuf = buffer; 83 switch(reg){
84 84 case RIP: return buf[0]->__rip;
85 UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); 85 case RSP: return buf[0]->__rsp;
86 UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); 86 case RBP: return buf[0]->__rbp;
87 UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); 87 default:
88 printk("get_thread_regs - unknown register %d\n", reg);
89 return 0;
90 }
88} 91}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
new file mode 100644
index 000000000000..3f369e5f976b
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -0,0 +1,16 @@
1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7
8extern void (*handlers[])(int sig, struct sigcontext *sc);
9
10void hard_handler(int sig)
11{
12 struct ucontext *uc;
13 asm("movq %%rdx, %0" : "=r" (uc));
14
15 (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
16}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 4ae73c0e5485..38be096e750f 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -17,20 +17,25 @@
17#include "kern_constants.h" 17#include "kern_constants.h"
18#include "os.h" 18#include "os.h"
19 19
20static void set_interval(int timer_type) 20int set_interval(int is_virtual)
21{ 21{
22 int usec = 1000000/hz(); 22 int usec = 1000000/hz();
23 int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
23 struct itimerval interval = ((struct itimerval) { { 0, usec }, 24 struct itimerval interval = ((struct itimerval) { { 0, usec },
24 { 0, usec } }); 25 { 0, usec } });
25 26
26 if(setitimer(timer_type, &interval, NULL) == -1) 27 if(setitimer(timer_type, &interval, NULL) == -1)
27 panic("setitimer failed - errno = %d\n", errno); 28 return -errno;
29
30 return 0;
28} 31}
29 32
33#ifdef CONFIG_MODE_TT
30void enable_timer(void) 34void enable_timer(void)
31{ 35{
32 set_interval(ITIMER_VIRTUAL); 36 set_interval(1);
33} 37}
38#endif
34 39
35void disable_timer(void) 40void disable_timer(void)
36{ 41{
@@ -40,8 +45,8 @@ void disable_timer(void)
40 printk("disnable_timer - setitimer failed, errno = %d\n", 45 printk("disnable_timer - setitimer failed, errno = %d\n",
41 errno); 46 errno);
42 /* If there are signals already queued, after unblocking ignore them */ 47 /* If there are signals already queued, after unblocking ignore them */
43 set_handler(SIGALRM, SIG_IGN, 0, -1); 48 signal(SIGALRM, SIG_IGN);
44 set_handler(SIGVTALRM, SIG_IGN, 0, -1); 49 signal(SIGVTALRM, SIG_IGN);
45} 50}
46 51
47void switch_timers(int to_real) 52void switch_timers(int to_real)
@@ -74,7 +79,7 @@ void uml_idle_timer(void)
74 79
75 set_handler(SIGALRM, (__sighandler_t) alarm_handler, 80 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
76 SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); 81 SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
77 set_interval(ITIMER_REAL); 82 set_interval(0);
78} 83}
79#endif 84#endif
80 85
@@ -94,8 +99,3 @@ void idle_sleep(int secs)
94 ts.tv_nsec = 0; 99 ts.tv_nsec = 0;
95 nanosleep(&ts, NULL); 100 nanosleep(&ts, NULL);
96} 101}
97
98void user_time_init(void)
99{
100 set_interval(ITIMER_VIRTUAL);
101}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 90b29ae9af46..1df231a26244 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -5,7 +5,6 @@
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <signal.h> 7#include <signal.h>
8#include <setjmp.h>
9#include "kern_util.h" 8#include "kern_util.h"
10#include "user_util.h" 9#include "user_util.h"
11#include "os.h" 10#include "os.h"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 865f6a6a2590..bbb73a650370 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -4,8 +4,7 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include <setjmp.h> 7#include <stddef.h>
8#include <string.h>
9#include "longjmp.h" 8#include "longjmp.h"
10 9
11unsigned long __do_user_copy(void *to, const void *from, int n, 10unsigned long __do_user_copy(void *to, const void *from, int n,
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c47a2a7ce70e..3f5b1514e8a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -7,7 +7,6 @@
7#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <limits.h> 9#include <limits.h>
10#include <setjmp.h>
11#include <sys/mman.h> 10#include <sys/mman.h>
12#include <sys/stat.h> 11#include <sys/stat.h>
13#include <sys/utsname.h> 12#include <sys/utsname.h>
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
107 jmp_buf buf; 106 jmp_buf buf;
108 int n; 107 int n;
109 108
110 n = sigsetjmp(buf, 1); 109 n = UML_SETJMP(&buf);
111 if(n == 0){ 110 if(n == 0){
112 va_start(args, proc); 111 va_start(args, proc);
113 (*proc)(&buf, &args); 112 (*proc)(&buf, &args);
114 } 113 }
115 va_end(args); 114 va_end(args);
116 return(n); 115 return n;
117} 116}
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 374d61a19439..59cc70275754 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,5 +1,5 @@
1obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 1obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
2 ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \ 2 ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
3 sys_call_table.o tls.o 3 sys_call_table.o tls.o
4 4
5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o 5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 41b0ab2fe830..f1bcd399ac90 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -13,6 +13,7 @@
13#include "sysdep/ptrace.h" 13#include "sysdep/ptrace.h"
14#include "task.h" 14#include "task.h"
15#include "os.h" 15#include "os.h"
16#include "user_util.h"
16 17
17#define MAXTOKEN 64 18#define MAXTOKEN 64
18 19
@@ -104,17 +105,17 @@ int cpu_feature(char *what, char *buf, int len)
104static int check_cpu_flag(char *feature, int *have_it) 105static int check_cpu_flag(char *feature, int *have_it)
105{ 106{
106 char buf[MAXTOKEN], c; 107 char buf[MAXTOKEN], c;
107 int fd, len = sizeof(buf)/sizeof(buf[0]); 108 int fd, len = ARRAY_SIZE(buf);
108 109
109 printk("Checking for host processor %s support...", feature); 110 printk("Checking for host processor %s support...", feature);
110 fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); 111 fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
111 if(fd < 0){ 112 if(fd < 0){
112 printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); 113 printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
113 return(0); 114 return 0;
114 } 115 }
115 116
116 *have_it = 0; 117 *have_it = 0;
117 if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) 118 if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
118 goto out; 119 goto out;
119 120
120 c = token(fd, buf, len - 1, ' '); 121 c = token(fd, buf, len - 1, ' ');
@@ -138,7 +139,7 @@ static int check_cpu_flag(char *feature, int *have_it)
138 if(*have_it == 0) printk("No\n"); 139 if(*have_it == 0) printk("No\n");
139 else if(*have_it == 1) printk("Yes\n"); 140 else if(*have_it == 1) printk("Yes\n");
140 os_close_file(fd); 141 os_close_file(fd);
141 return(1); 142 return 1;
142} 143}
143 144
144#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems 145#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index fe0877b3509c..69971b78beaf 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -424,9 +424,8 @@ void ldt_get_host_info(void)
424 size++; 424 size++;
425 } 425 }
426 426
427 if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) { 427 if(size < ARRAY_SIZE(dummy_list))
428 host_ldt_entries = dummy_list; 428 host_ldt_entries = dummy_list;
429 }
430 else { 429 else {
431 size = (size + 1) * sizeof(dummy_list[0]); 430 size = (size + 1) * sizeof(dummy_list[0]);
432 host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL); 431 host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 40aa88531446..5f3cc6685820 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -15,6 +15,7 @@
15#include "user.h" 15#include "user.h"
16#include "os.h" 16#include "os.h"
17#include "uml-config.h" 17#include "uml-config.h"
18#include "user_util.h"
18 19
19int ptrace_getregs(long pid, unsigned long *regs_out) 20int ptrace_getregs(long pid, unsigned long *regs_out)
20{ 21{
@@ -51,7 +52,7 @@ static void write_debugregs(int pid, unsigned long *regs)
51 int nregs, i; 52 int nregs, i;
52 53
53 dummy = NULL; 54 dummy = NULL;
54 nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); 55 nregs = ARRAY_SIZE(dummy->u_debugreg);
55 for(i = 0; i < nregs; i++){ 56 for(i = 0; i < nregs; i++){
56 if((i == 4) || (i == 5)) continue; 57 if((i == 4) || (i == 5)) continue;
57 if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], 58 if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
@@ -68,7 +69,7 @@ static void read_debugregs(int pid, unsigned long *regs)
68 int nregs, i; 69 int nregs, i;
69 70
70 dummy = NULL; 71 dummy = NULL;
71 nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); 72 nregs = ARRAY_SIZE(dummy->u_debugreg);
72 for(i = 0; i < nregs; i++){ 73 for(i = 0; i < nregs; i++){
73 regs[i] = ptrace(PTRACE_PEEKUSR, pid, 74 regs[i] = ptrace(PTRACE_PEEKUSR, pid,
74 &dummy->u_debugreg[i], 0); 75 &dummy->u_debugreg[i], 0);
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S
new file mode 100644
index 000000000000..b766792c9933
--- /dev/null
+++ b/arch/um/sys-i386/setjmp.S
@@ -0,0 +1,58 @@
1#
2# arch/i386/setjmp.S
3#
4# setjmp/longjmp for the i386 architecture
5#
6
7#
8# The jmp_buf is assumed to contain the following, in order:
9# %ebx
10# %esp
11# %ebp
12# %esi
13# %edi
14# <return address>
15#
16
17 .text
18 .align 4
19 .globl setjmp
20 .type setjmp, @function
21setjmp:
22#ifdef _REGPARM
23 movl %eax,%edx
24#else
25 movl 4(%esp),%edx
26#endif
27 popl %ecx # Return address, and adjust the stack
28 xorl %eax,%eax # Return value
29 movl %ebx,(%edx)
30 movl %esp,4(%edx) # Post-return %esp!
31 pushl %ecx # Make the call/return stack happy
32 movl %ebp,8(%edx)
33 movl %esi,12(%edx)
34 movl %edi,16(%edx)
35 movl %ecx,20(%edx) # Return address
36 ret
37
38 .size setjmp,.-setjmp
39
40 .text
41 .align 4
42 .globl longjmp
43 .type longjmp, @function
44longjmp:
45#ifdef _REGPARM
46 xchgl %eax,%edx
47#else
48 movl 4(%esp),%edx # jmp_ptr address
49 movl 8(%esp),%eax # Return value
50#endif
51 movl (%edx),%ebx
52 movl 4(%edx),%esp
53 movl 8(%edx),%ebp
54 movl 12(%edx),%esi
55 movl 16(%edx),%edi
56 jmp *20(%edx)
57
58 .size longjmp,.-longjmp
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c19794d435d6..f41768b8e25e 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,8 +5,8 @@
5# 5#
6 6
7obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ 7obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
8 sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \ 8 setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
9 tls.o 9 ksyms.o tls.o
10 10
11obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o 11obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
12obj-$(CONFIG_MODULES) += um_module.o 12obj-$(CONFIG_MODULES) += um_module.o
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S
new file mode 100644
index 000000000000..45f547b4043e
--- /dev/null
+++ b/arch/um/sys-x86_64/setjmp.S
@@ -0,0 +1,54 @@
1#
2# arch/x86_64/setjmp.S
3#
4# setjmp/longjmp for the x86-64 architecture
5#
6
7#
8# The jmp_buf is assumed to contain the following, in order:
9# %rbx
10# %rsp (post-return)
11# %rbp
12# %r12
13# %r13
14# %r14
15# %r15
16# <return address>
17#
18
19 .text
20 .align 4
21 .globl setjmp
22 .type setjmp, @function
23setjmp:
24 pop %rsi # Return address, and adjust the stack
25 xorl %eax,%eax # Return value
26 movq %rbx,(%rdi)
27 movq %rsp,8(%rdi) # Post-return %rsp!
28 push %rsi # Make the call/return stack happy
29 movq %rbp,16(%rdi)
30 movq %r12,24(%rdi)
31 movq %r13,32(%rdi)
32 movq %r14,40(%rdi)
33 movq %r15,48(%rdi)
34 movq %rsi,56(%rdi) # Return address
35 ret
36
37 .size setjmp,.-setjmp
38
39 .text
40 .align 4
41 .globl longjmp
42 .type longjmp, @function
43longjmp:
44 movl %esi,%eax # Return value (int)
45 movq (%rdi),%rbx
46 movq 8(%rdi),%rsp
47 movq 16(%rdi),%rbp
48 movq 24(%rdi),%r12
49 movq 32(%rdi),%r13
50 movq 40(%rdi),%r14
51 movq 48(%rdi),%r15
52 jmp *56(%rdi)
53
54 .size longjmp,.-longjmp
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 6cd4878625f1..581ce9af0ec8 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -24,6 +24,10 @@ config X86
24 bool 24 bool
25 default y 25 default y
26 26
27config ZONE_DMA32
28 bool
29 default y
30
27config LOCKDEP_SUPPORT 31config LOCKDEP_SUPPORT
28 bool 32 bool
29 default y 33 default y
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index d6d7f731f6f0..708a3cd9a27e 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -16,6 +16,7 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/kexec.h> 17#include <linux/kexec.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/mm.h>
19 20
20#include <asm/pgtable.h> 21#include <asm/pgtable.h>
21#include <asm/page.h> 22#include <asm/page.h>
@@ -297,6 +298,53 @@ void __init e820_reserve_resources(void)
297 } 298 }
298} 299}
299 300
301/* Mark pages corresponding to given address range as nosave */
302static void __init
303e820_mark_nosave_range(unsigned long start, unsigned long end)
304{
305 unsigned long pfn, max_pfn;
306
307 if (start >= end)
308 return;
309
310 printk("Nosave address range: %016lx - %016lx\n", start, end);
311 max_pfn = end >> PAGE_SHIFT;
312 for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
313 if (pfn_valid(pfn))
314 SetPageNosave(pfn_to_page(pfn));
315}
316
317/*
318 * Find the ranges of physical addresses that do not correspond to
319 * e820 RAM areas and mark the corresponding pages as nosave for software
320 * suspend and suspend to RAM.
321 *
322 * This function requires the e820 map to be sorted and without any
323 * overlapping entries and assumes the first e820 area to be RAM.
324 */
325void __init e820_mark_nosave_regions(void)
326{
327 int i;
328 unsigned long paddr;
329
330 paddr = round_down(e820.map[0].addr + e820.map[0].size, PAGE_SIZE);
331 for (i = 1; i < e820.nr_map; i++) {
332 struct e820entry *ei = &e820.map[i];
333
334 if (paddr < ei->addr)
335 e820_mark_nosave_range(paddr,
336 round_up(ei->addr, PAGE_SIZE));
337
338 paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
339 if (ei->type != E820_RAM)
340 e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE),
341 paddr);
342
343 if (paddr >= (end_pfn << PAGE_SHIFT))
344 break;
345 }
346}
347
300/* 348/*
301 * Add a memory region to the kernel e820 map. 349 * Add a memory region to the kernel e820 map.
302 */ 350 */
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 34afad704824..4b39f0da17f3 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -689,6 +689,7 @@ void __init setup_arch(char **cmdline_p)
689 */ 689 */
690 probe_roms(); 690 probe_roms();
691 e820_reserve_resources(); 691 e820_reserve_resources();
692 e820_mark_nosave_regions();
692 693
693 request_resource(&iomem_resource, &video_ram_resource); 694 request_resource(&iomem_resource, &video_ram_resource);
694 695
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 975380207b46..3ae9ffddddc0 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -46,9 +46,10 @@
46#include <linux/bootmem.h> 46#include <linux/bootmem.h>
47#include <linux/thread_info.h> 47#include <linux/thread_info.h>
48#include <linux/module.h> 48#include <linux/module.h>
49
50#include <linux/delay.h> 49#include <linux/delay.h>
51#include <linux/mc146818rtc.h> 50#include <linux/mc146818rtc.h>
51#include <linux/smp.h>
52
52#include <asm/mtrr.h> 53#include <asm/mtrr.h>
53#include <asm/pgalloc.h> 54#include <asm/pgalloc.h>
54#include <asm/desc.h> 55#include <asm/desc.h>
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
index 320b6fb00cca..bfbe00763c68 100644
--- a/arch/x86_64/kernel/suspend_asm.S
+++ b/arch/x86_64/kernel/suspend_asm.S
@@ -54,7 +54,7 @@ ENTRY(restore_image)
54 movq %rcx, %cr3; 54 movq %rcx, %cr3;
55 movq %rax, %cr4; # turn PGE back on 55 movq %rax, %cr4; # turn PGE back on
56 56
57 movq pagedir_nosave(%rip), %rdx 57 movq restore_pblist(%rip), %rdx
58loop: 58loop:
59 testq %rdx, %rdx 59 testq %rdx, %rdx
60 jz done 60 jz done
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 7a9b18224182..7700e6cd2bd9 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -1148,23 +1148,25 @@ int hpet_rtc_timer_init(void)
1148 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; 1148 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
1149 1149
1150 local_irq_save(flags); 1150 local_irq_save(flags);
1151
1151 cnt = hpet_readl(HPET_COUNTER); 1152 cnt = hpet_readl(HPET_COUNTER);
1152 cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); 1153 cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
1153 hpet_writel(cnt, HPET_T1_CMP); 1154 hpet_writel(cnt, HPET_T1_CMP);
1154 hpet_t1_cmp = cnt; 1155 hpet_t1_cmp = cnt;
1155 local_irq_restore(flags);
1156 1156
1157 cfg = hpet_readl(HPET_T1_CFG); 1157 cfg = hpet_readl(HPET_T1_CFG);
1158 cfg &= ~HPET_TN_PERIODIC; 1158 cfg &= ~HPET_TN_PERIODIC;
1159 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; 1159 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
1160 hpet_writel(cfg, HPET_T1_CFG); 1160 hpet_writel(cfg, HPET_T1_CFG);
1161 1161
1162 local_irq_restore(flags);
1163
1162 return 1; 1164 return 1;
1163} 1165}
1164 1166
1165static void hpet_rtc_timer_reinit(void) 1167static void hpet_rtc_timer_reinit(void)
1166{ 1168{
1167 unsigned int cfg, cnt; 1169 unsigned int cfg, cnt, ticks_per_int, lost_ints;
1168 1170
1169 if (unlikely(!(PIE_on | AIE_on | UIE_on))) { 1171 if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
1170 cfg = hpet_readl(HPET_T1_CFG); 1172 cfg = hpet_readl(HPET_T1_CFG);
@@ -1179,10 +1181,33 @@ static void hpet_rtc_timer_reinit(void)
1179 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; 1181 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
1180 1182
1181 /* It is more accurate to use the comparator value than current count.*/ 1183 /* It is more accurate to use the comparator value than current count.*/
1182 cnt = hpet_t1_cmp; 1184 ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
1183 cnt += hpet_tick*HZ/hpet_rtc_int_freq; 1185 hpet_t1_cmp += ticks_per_int;
1184 hpet_writel(cnt, HPET_T1_CMP); 1186 hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
1185 hpet_t1_cmp = cnt; 1187
1188 /*
1189 * If the interrupt handler was delayed too long, the write above tries
1190 * to schedule the next interrupt in the past and the hardware would
1191 * not interrupt until the counter had wrapped around.
1192 * So we have to check that the comparator wasn't set to a past time.
1193 */
1194 cnt = hpet_readl(HPET_COUNTER);
1195 if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
1196 lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
1197 /* Make sure that, even with the time needed to execute
1198 * this code, the next scheduled interrupt has been moved
1199 * back to the future: */
1200 lost_ints++;
1201
1202 hpet_t1_cmp += lost_ints * ticks_per_int;
1203 hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
1204
1205 if (PIE_on)
1206 PIE_count += lost_ints;
1207
1208 printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
1209 hpet_rtc_int_freq);
1210 }
1186} 1211}
1187 1212
1188/* 1213/*
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index ac8ea66ccb94..4198798e1469 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -299,7 +299,7 @@ static int vmalloc_fault(unsigned long address)
299 if (pgd_none(*pgd)) 299 if (pgd_none(*pgd))
300 set_pgd(pgd, *pgd_ref); 300 set_pgd(pgd, *pgd_ref);
301 else 301 else
302 BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref)); 302 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
303 303
304 /* Below here mismatches are bugs because these lower tables 304 /* Below here mismatches are bugs because these lower tables
305 are shared */ 305 are shared */
@@ -308,7 +308,7 @@ static int vmalloc_fault(unsigned long address)
308 pud_ref = pud_offset(pgd_ref, address); 308 pud_ref = pud_offset(pgd_ref, address);
309 if (pud_none(*pud_ref)) 309 if (pud_none(*pud_ref))
310 return -1; 310 return -1;
311 if (pud_none(*pud) || pud_page(*pud) != pud_page(*pud_ref)) 311 if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
312 BUG(); 312 BUG();
313 pmd = pmd_offset(pud, address); 313 pmd = pmd_offset(pud, address);
314 pmd_ref = pmd_offset(pud_ref, address); 314 pmd_ref = pmd_offset(pud_ref, address);
@@ -641,7 +641,7 @@ void vmalloc_sync_all(void)
641 if (pgd_none(*pgd)) 641 if (pgd_none(*pgd))
642 set_pgd(pgd, *pgd_ref); 642 set_pgd(pgd, *pgd_ref);
643 else 643 else
644 BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref)); 644 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
645 } 645 }
646 spin_unlock(&pgd_lock); 646 spin_unlock(&pgd_lock);
647 set_bit(pgd_index(address), insync); 647 set_bit(pgd_index(address), insync);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index d14fb2dfbfc4..52fd42c40c86 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -536,7 +536,7 @@ int memory_add_physaddr_to_nid(u64 start)
536int arch_add_memory(int nid, u64 start, u64 size) 536int arch_add_memory(int nid, u64 start, u64 size)
537{ 537{
538 struct pglist_data *pgdat = NODE_DATA(nid); 538 struct pglist_data *pgdat = NODE_DATA(nid);
539 struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; 539 struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
540 unsigned long start_pfn = start >> PAGE_SHIFT; 540 unsigned long start_pfn = start >> PAGE_SHIFT;
541 unsigned long nr_pages = size >> PAGE_SHIFT; 541 unsigned long nr_pages = size >> PAGE_SHIFT;
542 int ret; 542 int ret;