diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2006-09-26 02:32:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:54 -0400 |
commit | 5f97f7f9400de47ae837170bb274e90ad3934386 (patch) | |
tree | 514451e6dc6b46253293a00035d375e77b1c65ed | |
parent | 53e62d3aaa60590d4a69b4e07c29f448b5151047 (diff) |
[PATCH] avr32 architecture
This adds support for the Atmel AVR32 architecture as well as the AT32AP7000
CPU and the AT32STK1000 development board.
AVR32 is a new high-performance 32-bit RISC microprocessor core, designed for
cost-sensitive embedded applications, with particular emphasis on low power
consumption and high code density. The AVR32 architecture is not binary
compatible with earlier 8-bit AVR architectures.
The AVR32 architecture, including the instruction set, is described by the
AVR32 Architecture Manual, available from
http://www.atmel.com/dyn/resources/prod_documents/doc32000.pdf
The Atmel AT32AP7000 is the first CPU implementing the AVR32 architecture. It
features a 7-stage pipeline, 16KB instruction and data caches and a full
Memory Management Unit. It also comes with a large set of integrated
peripherals, many of which are shared with the AT91 ARM-based controllers from
Atmel.
Full data sheet is available from
http://www.atmel.com/dyn/resources/prod_documents/doc32003.pdf
while the CPU core implementation including caches and MMU is documented by
the AVR32 AP Technical Reference, available from
http://www.atmel.com/dyn/resources/prod_documents/doc32001.pdf
Information about the AT32STK1000 development board can be found at
http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3918
including a BSP CD image with an earlier version of this patch, development
tools (binaries and source/patches) and a root filesystem image suitable for
booting from SD card.
Alternatively, there's a preliminary "getting started" guide available at
http://avr32linux.org/twiki/bin/view/Main/GettingStarted which provides links
to the sources and patches you will need in order to set up a cross-compiling
environment for avr32-linux.
This patch, as well as the other patches included with the BSP and the
toolchain patches, is actively supported by Atmel Corporation.
[dmccr@us.ibm.com: Fix more pxx_page macro locations]
[bunk@stusta.de: fix `make defconfig']
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Dave McCracken <dmccr@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
176 files changed, 18124 insertions, 2 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 23348c0d37bc..767a43434ae8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -443,6 +443,23 @@ W: http://people.redhat.com/sgrubb/audit/ | |||
443 | T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git | 443 | T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git |
444 | S: Maintained | 444 | S: Maintained |
445 | 445 | ||
446 | AVR32 ARCHITECTURE | ||
447 | P: Atmel AVR32 Support Team | ||
448 | M: avr32@atmel.com | ||
449 | P: Haavard Skinnemoen | ||
450 | M: hskinnemoen@atmel.com | ||
451 | W: http://www.atmel.com/products/AVR32/ | ||
452 | W: http://avr32linux.org/ | ||
453 | W: http://avrfreaks.net/ | ||
454 | S: Supported | ||
455 | |||
456 | AVR32/AT32AP MACHINE SUPPORT | ||
457 | P: Atmel AVR32 Support Team | ||
458 | M: avr32@atmel.com | ||
459 | P: Haavard Skinnemoen | ||
460 | M: hskinnemoen@atmel.com | ||
461 | S: Supported | ||
462 | |||
446 | AX.25 NETWORK LAYER | 463 | AX.25 NETWORK LAYER |
447 | P: Ralf Baechle | 464 | P: Ralf Baechle |
448 | M: ralf@linux-mips.org | 465 | M: ralf@linux-mips.org |
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 | |||
6 | mainmenu "Linux Kernel Configuration" | ||
7 | |||
8 | config 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 | |||
22 | config UID16 | ||
23 | bool | ||
24 | |||
25 | config GENERIC_HARDIRQS | ||
26 | bool | ||
27 | default y | ||
28 | |||
29 | config HARDIRQS_SW_RESEND | ||
30 | bool | ||
31 | default y | ||
32 | |||
33 | config GENERIC_IRQ_PROBE | ||
34 | bool | ||
35 | default y | ||
36 | |||
37 | config RWSEM_GENERIC_SPINLOCK | ||
38 | bool | ||
39 | default y | ||
40 | |||
41 | config GENERIC_TIME | ||
42 | bool | ||
43 | default y | ||
44 | |||
45 | config RWSEM_XCHGADD_ALGORITHM | ||
46 | bool | ||
47 | |||
48 | config GENERIC_BUST_SPINLOCK | ||
49 | bool | ||
50 | |||
51 | config GENERIC_HWEIGHT | ||
52 | bool | ||
53 | default y | ||
54 | |||
55 | config GENERIC_CALIBRATE_DELAY | ||
56 | bool | ||
57 | default y | ||
58 | |||
59 | source "init/Kconfig" | ||
60 | |||
61 | menu "System Type and features" | ||
62 | |||
63 | config SUBARCH_AVR32B | ||
64 | bool | ||
65 | config MMU | ||
66 | bool | ||
67 | config PERFORMANCE_COUNTERS | ||
68 | bool | ||
69 | |||
70 | config PLATFORM_AT32AP | ||
71 | bool | ||
72 | select SUBARCH_AVR32B | ||
73 | select MMU | ||
74 | select PERFORMANCE_COUNTERS | ||
75 | |||
76 | choice | ||
77 | prompt "AVR32 CPU type" | ||
78 | default CPU_AT32AP7000 | ||
79 | |||
80 | config CPU_AT32AP7000 | ||
81 | bool "AT32AP7000" | ||
82 | select PLATFORM_AT32AP | ||
83 | endchoice | ||
84 | |||
85 | # | ||
86 | # CPU Daughterboards for ATSTK1000 | ||
87 | config BOARD_ATSTK1002 | ||
88 | bool | ||
89 | |||
90 | choice | ||
91 | prompt "AVR32 board type" | ||
92 | default BOARD_ATSTK1000 | ||
93 | |||
94 | config BOARD_ATSTK1000 | ||
95 | bool "ATSTK1000 evaluation board" | ||
96 | select BOARD_ATSTK1002 if CPU_AT32AP7000 | ||
97 | endchoice | ||
98 | |||
99 | choice | ||
100 | prompt "Boot loader type" | ||
101 | default LOADER_U_BOOT | ||
102 | |||
103 | config LOADER_U_BOOT | ||
104 | bool "U-Boot (or similar) bootloader" | ||
105 | endchoice | ||
106 | |||
107 | config LOAD_ADDRESS | ||
108 | hex | ||
109 | default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y | ||
110 | |||
111 | config ENTRY_ADDRESS | ||
112 | hex | ||
113 | default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y | ||
114 | |||
115 | config PHYS_OFFSET | ||
116 | hex | ||
117 | default 0x10000000 if CPU_AT32AP7000=y | ||
118 | |||
119 | source "kernel/Kconfig.preempt" | ||
120 | |||
121 | config HAVE_ARCH_BOOTMEM_NODE | ||
122 | bool | ||
123 | default n | ||
124 | |||
125 | config ARCH_HAVE_MEMORY_PRESENT | ||
126 | bool | ||
127 | default n | ||
128 | |||
129 | config NEED_NODE_MEMMAP_SIZE | ||
130 | bool | ||
131 | default n | ||
132 | |||
133 | config ARCH_FLATMEM_ENABLE | ||
134 | bool | ||
135 | default y | ||
136 | |||
137 | config ARCH_DISCONTIGMEM_ENABLE | ||
138 | bool | ||
139 | default n | ||
140 | |||
141 | config ARCH_SPARSEMEM_ENABLE | ||
142 | bool | ||
143 | default n | ||
144 | |||
145 | source "mm/Kconfig" | ||
146 | |||
147 | config 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 | |||
157 | source "kernel/Kconfig.hz" | ||
158 | |||
159 | config 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 | |||
167 | endmenu | ||
168 | |||
169 | menu "Bus options" | ||
170 | |||
171 | config PCI | ||
172 | bool | ||
173 | |||
174 | source "drivers/pci/Kconfig" | ||
175 | |||
176 | source "drivers/pcmcia/Kconfig" | ||
177 | |||
178 | endmenu | ||
179 | |||
180 | menu "Executable file formats" | ||
181 | source "fs/Kconfig.binfmt" | ||
182 | endmenu | ||
183 | |||
184 | source "net/Kconfig" | ||
185 | |||
186 | source "drivers/Kconfig" | ||
187 | |||
188 | source "fs/Kconfig" | ||
189 | |||
190 | source "arch/avr32/Kconfig.debug" | ||
191 | |||
192 | source "security/Kconfig" | ||
193 | |||
194 | source "crypto/Kconfig" | ||
195 | |||
196 | source "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 @@ | |||
1 | menu "Kernel hacking" | ||
2 | |||
3 | config TRACE_IRQFLAGS_SUPPORT | ||
4 | bool | ||
5 | default y | ||
6 | |||
7 | source "lib/Kconfig.debug" | ||
8 | |||
9 | config 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 | |||
19 | endmenu | ||
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 | ||
10 | all: uImage vmlinux.elf linux.lst | ||
11 | |||
12 | KBUILD_DEFCONFIG := atstk1002_defconfig | ||
13 | |||
14 | CFLAGS += -pipe -fno-builtin -mno-pic | ||
15 | AFLAGS += -mrelax -mno-pic | ||
16 | CFLAGS_MODULE += -mno-relax | ||
17 | LDFLAGS_vmlinux += --relax | ||
18 | |||
19 | cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000 | ||
20 | |||
21 | CFLAGS += $(cpuflags-y) | ||
22 | AFLAGS += $(cpuflags-y) | ||
23 | |||
24 | CHECKFLAGS += -D__avr32__ | ||
25 | |||
26 | LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) | ||
27 | |||
28 | head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o | ||
29 | head-y += arch/avr32/kernel/head.o | ||
30 | core-$(CONFIG_PLATFORM_AT32AP) += arch/avr32/mach-at32ap/ | ||
31 | core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/ | ||
32 | core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/ | ||
33 | core-y += arch/avr32/kernel/ | ||
34 | core-y += arch/avr32/mm/ | ||
35 | libs-y += arch/avr32/lib/ #$(LIBGCC) | ||
36 | |||
37 | archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap | ||
38 | |||
39 | include/asm-avr32/.arch: $(wildcard include/config/platform/*.h) include/config/auto.conf | ||
40 | @echo ' SYMLINK include/asm-avr32/arch -> include/asm-avr32/$(archincdir-y)' | ||
41 | ifneq ($(KBUILD_SRC),) | ||
42 | $(Q)mkdir -p include/asm-avr32 | ||
43 | $(Q)ln -fsn $(srctree)/include/asm-avr32/$(archincdir-y) include/asm-avr32/arch | ||
44 | else | ||
45 | $(Q)ln -fsn $(archincdir-y) include/asm-avr32/arch | ||
46 | endif | ||
47 | @touch $@ | ||
48 | |||
49 | archprepare: include/asm-avr32/.arch | ||
50 | |||
51 | BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec | ||
52 | |||
53 | .PHONY: $(BOOT_TARGETS) install | ||
54 | |||
55 | boot := arch/$(ARCH)/boot/images | ||
56 | |||
57 | KBUILD_IMAGE := $(boot)/uImage | ||
58 | vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf | ||
59 | vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso | ||
60 | uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec | ||
61 | uImage: KBUILD_IMAGE := $(boot)/uImage | ||
62 | |||
63 | quiet_cmd_listing = LST $@ | ||
64 | cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@ | ||
65 | quiet_cmd_disasm = DIS $@ | ||
66 | cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@ | ||
67 | |||
68 | vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux | ||
69 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | ||
70 | |||
71 | install: vmlinux | ||
72 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ | ||
73 | |||
74 | linux.s: vmlinux | ||
75 | $(call if_changed,disasm) | ||
76 | |||
77 | linux.lst: vmlinux | ||
78 | $(call if_changed,listing) | ||
79 | |||
80 | define 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' | ||
84 | endef | ||
diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile new file mode 100644 index 000000000000..c3e36ece8651 --- /dev/null +++ b/arch/avr32/boards/atstk1000/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-y += setup.o spi.o | ||
2 | obj-$(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 | |||
14 | struct 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 | |||
21 | extern struct lcdc_platform_data atstk1000_fb0_data; | ||
22 | |||
23 | static 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, ð0_data); | ||
32 | at32_add_device_spi(0); | ||
33 | at32_add_device_lcdc(0, &atstk1000_fb0_data); | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | postcore_initcall(atstk1002_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. */ | ||
20 | struct tag *bootloader_tags __initdata; | ||
21 | |||
22 | struct lcdc_platform_data __initdata atstk1000_fb0_data; | ||
23 | |||
24 | asmlinkage 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 | |||
33 | void __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 | |||
13 | static 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 | |||
22 | static int board_init_spi(void) | ||
23 | { | ||
24 | spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); | ||
25 | return 0; | ||
26 | } | ||
27 | arch_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 | |||
9 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
10 | |||
11 | extra-y := vmlinux.bin vmlinux.gz | ||
12 | |||
13 | OBJCOPYFLAGS_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 | |||
20 | quiet_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 | |||
25 | targets += uImage uImage.srec | ||
26 | $(obj)/uImage: $(obj)/vmlinux.gz | ||
27 | $(call if_changed,uimage) | ||
28 | @echo ' Image $@ is ready' | ||
29 | |||
30 | OBJCOPYFLAGS_uImage.srec := -I binary -O srec | ||
31 | $(obj)/uImage.srec: $(obj)/uImage | ||
32 | $(call if_changed,objcopy) | ||
33 | |||
34 | OBJCOPYFLAGS_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 | |||
52 | quiet_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 | |||
58 | install: $(BOOTIMAGE) | ||
59 | sh $(srctree)/install-kernel.sh $< | ||
60 | |||
61 | # Generated files to be removed upon make clean | ||
62 | clean-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 @@ | |||
1 | extra-y := head.o | ||
2 | |||
3 | obj-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 | ||
33 | 1: 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 | ||
48 | magic_number: | ||
49 | .long ATAG_MAGIC | ||
50 | tag_table_addr: | ||
51 | .long bootloader_tags | ||
52 | bss_start_addr: | ||
53 | .long __bss_start | ||
54 | end_addr: | ||
55 | .long _end | ||
56 | |||
57 | no_tag_table: | ||
58 | sub r12, pc, (. - 2f) | ||
59 | bral panic | ||
60 | 2: .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 | # | ||
6 | CONFIG_AVR32=y | ||
7 | CONFIG_GENERIC_HARDIRQS=y | ||
8 | CONFIG_HARDIRQS_SW_RESEND=y | ||
9 | CONFIG_GENERIC_IRQ_PROBE=y | ||
10 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
11 | CONFIG_GENERIC_HWEIGHT=y | ||
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
13 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
14 | |||
15 | # | ||
16 | # Code maturity level options | ||
17 | # | ||
18 | CONFIG_EXPERIMENTAL=y | ||
19 | CONFIG_BROKEN_ON_SMP=y | ||
20 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
21 | |||
22 | # | ||
23 | # General setup | ||
24 | # | ||
25 | CONFIG_LOCALVERSION="" | ||
26 | # CONFIG_LOCALVERSION_AUTO is not set | ||
27 | CONFIG_SWAP=y | ||
28 | # CONFIG_SYSVIPC is not set | ||
29 | # CONFIG_POSIX_MQUEUE is not set | ||
30 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
31 | CONFIG_SYSCTL=y | ||
32 | # CONFIG_AUDIT is not set | ||
33 | # CONFIG_IKCONFIG is not set | ||
34 | # CONFIG_RELAY is not set | ||
35 | CONFIG_INITRAMFS_SOURCE="" | ||
36 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
37 | CONFIG_EMBEDDED=y | ||
38 | CONFIG_KALLSYMS=y | ||
39 | # CONFIG_KALLSYMS_ALL is not set | ||
40 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
41 | CONFIG_HOTPLUG=y | ||
42 | CONFIG_PRINTK=y | ||
43 | CONFIG_BUG=y | ||
44 | CONFIG_ELF_CORE=y | ||
45 | # CONFIG_BASE_FULL is not set | ||
46 | # CONFIG_FUTEX is not set | ||
47 | # CONFIG_EPOLL is not set | ||
48 | CONFIG_SHMEM=y | ||
49 | # CONFIG_SLAB is not set | ||
50 | # CONFIG_VM_EVENT_COUNTERS is not set | ||
51 | # CONFIG_TINY_SHMEM is not set | ||
52 | CONFIG_BASE_SMALL=1 | ||
53 | CONFIG_SLOB=y | ||
54 | |||
55 | # | ||
56 | # Loadable module support | ||
57 | # | ||
58 | CONFIG_MODULES=y | ||
59 | CONFIG_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 | # | ||
73 | CONFIG_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 | ||
80 | CONFIG_DEFAULT_NOOP=y | ||
81 | CONFIG_DEFAULT_IOSCHED="noop" | ||
82 | |||
83 | # | ||
84 | # System Type and features | ||
85 | # | ||
86 | CONFIG_SUBARCH_AVR32B=y | ||
87 | CONFIG_MMU=y | ||
88 | CONFIG_PERFORMANCE_COUNTERS=y | ||
89 | CONFIG_PLATFORM_AT32AP=y | ||
90 | CONFIG_CPU_AT32AP7000=y | ||
91 | CONFIG_BOARD_ATSTK1002=y | ||
92 | CONFIG_BOARD_ATSTK1000=y | ||
93 | CONFIG_LOADER_U_BOOT=y | ||
94 | CONFIG_LOAD_ADDRESS=0x10000000 | ||
95 | CONFIG_ENTRY_ADDRESS=0x90000000 | ||
96 | CONFIG_PHYS_OFFSET=0x10000000 | ||
97 | CONFIG_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 | ||
103 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
104 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | ||
105 | # CONFIG_ARCH_SPARSEMEM_ENABLE is not set | ||
106 | CONFIG_SELECT_MEMORY_MODEL=y | ||
107 | CONFIG_FLATMEM_MANUAL=y | ||
108 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
109 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
110 | CONFIG_FLATMEM=y | ||
111 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
112 | # CONFIG_SPARSEMEM_STATIC is not set | ||
113 | CONFIG_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 | ||
117 | CONFIG_HZ_250=y | ||
118 | # CONFIG_HZ_1000 is not set | ||
119 | CONFIG_HZ=250 | ||
120 | CONFIG_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 | # | ||
134 | CONFIG_BINFMT_ELF=y | ||
135 | # CONFIG_BINFMT_MISC is not set | ||
136 | |||
137 | # | ||
138 | # Networking | ||
139 | # | ||
140 | CONFIG_NET=y | ||
141 | |||
142 | # | ||
143 | # Networking options | ||
144 | # | ||
145 | # CONFIG_NETDEBUG is not set | ||
146 | CONFIG_PACKET=y | ||
147 | CONFIG_PACKET_MMAP=y | ||
148 | CONFIG_UNIX=y | ||
149 | # CONFIG_NET_KEY is not set | ||
150 | CONFIG_INET=y | ||
151 | # CONFIG_IP_MULTICAST is not set | ||
152 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
153 | CONFIG_IP_FIB_HASH=y | ||
154 | CONFIG_IP_PNP=y | ||
155 | CONFIG_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 | ||
169 | CONFIG_INET_DIAG=y | ||
170 | CONFIG_INET_TCP_DIAG=y | ||
171 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
172 | CONFIG_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 | # | ||
228 | CONFIG_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 | ||
257 | CONFIG_BLK_DEV_LOOP=m | ||
258 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
259 | CONFIG_BLK_DEV_NBD=m | ||
260 | CONFIG_BLK_DEV_RAM=m | ||
261 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
262 | CONFIG_BLK_DEV_RAM_SIZE=4096 | ||
263 | CONFIG_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 | # | ||
299 | CONFIG_NETDEVICES=y | ||
300 | CONFIG_DUMMY=y | ||
301 | # CONFIG_BONDING is not set | ||
302 | # CONFIG_EQUALIZER is not set | ||
303 | CONFIG_TUN=m | ||
304 | |||
305 | # | ||
306 | # PHY device support | ||
307 | # | ||
308 | # CONFIG_PHYLIB is not set | ||
309 | |||
310 | # | ||
311 | # Ethernet (10 or 100Mbit) | ||
312 | # | ||
313 | CONFIG_NET_ETHERNET=y | ||
314 | CONFIG_MII=y | ||
315 | CONFIG_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 | ||
338 | CONFIG_PPP=m | ||
339 | # CONFIG_PPP_MULTILINK is not set | ||
340 | # CONFIG_PPP_FILTER is not set | ||
341 | CONFIG_PPP_ASYNC=m | ||
342 | # CONFIG_PPP_SYNC_TTY is not set | ||
343 | CONFIG_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 | # | ||
388 | CONFIG_SERIAL_AT91=y | ||
389 | CONFIG_SERIAL_AT91_CONSOLE=y | ||
390 | # CONFIG_SERIAL_AT91_TTYAT is not set | ||
391 | CONFIG_SERIAL_CORE=y | ||
392 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
393 | CONFIG_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 | # | ||
430 | CONFIG_SPI=y | ||
431 | # CONFIG_SPI_DEBUG is not set | ||
432 | CONFIG_SPI_MASTER=y | ||
433 | |||
434 | # | ||
435 | # SPI Master Controller Drivers | ||
436 | # | ||
437 | CONFIG_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 | ||
462 | CONFIG_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 | ||
473 | CONFIG_FB=m | ||
474 | CONFIG_FB_CFB_FILLRECT=m | ||
475 | CONFIG_FB_CFB_COPYAREA=m | ||
476 | CONFIG_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 | ||
481 | CONFIG_FB_SIDSA=m | ||
482 | CONFIG_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 | ||
490 | CONFIG_BACKLIGHT_LCD_SUPPORT=y | ||
491 | # CONFIG_BACKLIGHT_CLASS_DEVICE is not set | ||
492 | CONFIG_LCD_CLASS_DEVICE=m | ||
493 | CONFIG_LCD_DEVICE=y | ||
494 | CONFIG_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 | # | ||
564 | CONFIG_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 | ||
573 | CONFIG_MINIX_FS=m | ||
574 | CONFIG_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 | # | ||
591 | CONFIG_FAT_FS=m | ||
592 | CONFIG_MSDOS_FS=m | ||
593 | CONFIG_VFAT_FS=m | ||
594 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
595 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
596 | # CONFIG_NTFS_FS is not set | ||
597 | |||
598 | # | ||
599 | # Pseudo filesystems | ||
600 | # | ||
601 | CONFIG_PROC_FS=y | ||
602 | CONFIG_PROC_KCORE=y | ||
603 | CONFIG_SYSFS=y | ||
604 | CONFIG_TMPFS=y | ||
605 | # CONFIG_HUGETLB_PAGE is not set | ||
606 | CONFIG_RAMFS=y | ||
607 | CONFIG_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 | # | ||
629 | CONFIG_NFS_FS=y | ||
630 | CONFIG_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 | ||
635 | CONFIG_ROOT_NFS=y | ||
636 | CONFIG_LOCKD=y | ||
637 | CONFIG_LOCKD_V4=y | ||
638 | CONFIG_NFS_COMMON=y | ||
639 | CONFIG_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 | ||
643 | CONFIG_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 | ||
658 | CONFIG_MSDOS_PARTITION=y | ||
659 | |||
660 | # | ||
661 | # Native Language Support | ||
662 | # | ||
663 | CONFIG_NLS=m | ||
664 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
665 | CONFIG_NLS_CODEPAGE_437=m | ||
666 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
667 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
668 | CONFIG_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 | ||
689 | CONFIG_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 | ||
702 | CONFIG_NLS_UTF8=m | ||
703 | |||
704 | # | ||
705 | # Kernel hacking | ||
706 | # | ||
707 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
708 | CONFIG_PRINTK_TIME=y | ||
709 | CONFIG_MAGIC_SYSRQ=y | ||
710 | # CONFIG_UNUSED_SYMBOLS is not set | ||
711 | CONFIG_DEBUG_KERNEL=y | ||
712 | CONFIG_LOG_BUF_SHIFT=14 | ||
713 | CONFIG_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 | ||
721 | CONFIG_DEBUG_BUGVERBOSE=y | ||
722 | # CONFIG_DEBUG_INFO is not set | ||
723 | CONFIG_DEBUG_FS=y | ||
724 | # CONFIG_DEBUG_VM is not set | ||
725 | CONFIG_FRAME_POINTER=y | ||
726 | # CONFIG_UNWIND_INFO is not set | ||
727 | CONFIG_FORCED_INLINING=y | ||
728 | # CONFIG_RCU_TORTURE_TEST is not set | ||
729 | CONFIG_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 | # | ||
749 | CONFIG_CRC_CCITT=m | ||
750 | # CONFIG_CRC16 is not set | ||
751 | CONFIG_CRC32=m | ||
752 | # CONFIG_LIBCRC32C is not set | ||
753 | CONFIG_ZLIB_INFLATE=m | ||
754 | CONFIG_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 | |||
5 | extra-y := head.o vmlinux.lds | ||
6 | |||
7 | obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o | ||
8 | obj-y += syscall_table.o syscall-stubs.o irq.o | ||
9 | obj-y += setup.o traps.o semaphore.o ptrace.o | ||
10 | obj-y += signal.o sys_avr32.o process.o time.o | ||
11 | obj-y += init_task.o switch_to.o cpu.o | ||
12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o | ||
13 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
14 | |||
15 | USE_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 | |||
17 | void 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 | */ | ||
19 | extern unsigned long long __avr32_lsl64(unsigned long long u, unsigned long b); | ||
20 | extern unsigned long long __avr32_lsr64(unsigned long long u, unsigned long b); | ||
21 | extern unsigned long long __avr32_asr64(unsigned long long u, unsigned long b); | ||
22 | EXPORT_SYMBOL(__avr32_lsl64); | ||
23 | EXPORT_SYMBOL(__avr32_lsr64); | ||
24 | EXPORT_SYMBOL(__avr32_asr64); | ||
25 | |||
26 | /* | ||
27 | * String functions | ||
28 | */ | ||
29 | EXPORT_SYMBOL(memset); | ||
30 | EXPORT_SYMBOL(memcpy); | ||
31 | |||
32 | /* | ||
33 | * Userspace access stuff. | ||
34 | */ | ||
35 | EXPORT_SYMBOL(copy_from_user); | ||
36 | EXPORT_SYMBOL(copy_to_user); | ||
37 | EXPORT_SYMBOL(__copy_user); | ||
38 | EXPORT_SYMBOL(strncpy_from_user); | ||
39 | EXPORT_SYMBOL(__strncpy_from_user); | ||
40 | EXPORT_SYMBOL(clear_user); | ||
41 | EXPORT_SYMBOL(__clear_user); | ||
42 | EXPORT_SYMBOL(csum_partial); | ||
43 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
44 | |||
45 | /* Delay loops (lib/delay.S) */ | ||
46 | EXPORT_SYMBOL(__ndelay); | ||
47 | EXPORT_SYMBOL(__udelay); | ||
48 | EXPORT_SYMBOL(__const_udelay); | ||
49 | |||
50 | /* Bit operations (lib/findbit.S) */ | ||
51 | EXPORT_SYMBOL(find_first_zero_bit); | ||
52 | EXPORT_SYMBOL(find_next_zero_bit); | ||
53 | EXPORT_SYMBOL(find_first_bit); | ||
54 | EXPORT_SYMBOL(find_next_bit); | ||
55 | EXPORT_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 | |||
19 | static 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 | */ | ||
27 | static 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 | } | ||
34 | static 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 | } | ||
47 | static 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 | } | ||
54 | static 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 | |||
68 | static 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 | } | ||
75 | static 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 | } | ||
88 | static 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 | } | ||
95 | static 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 | |||
109 | static 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 | } | ||
116 | static 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 | |||
130 | static 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 | } | ||
137 | static 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 | |||
156 | static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event); | ||
157 | static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count); | ||
158 | static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event); | ||
159 | static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count); | ||
160 | static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles); | ||
161 | static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable); | ||
162 | |||
163 | #endif /* CONFIG_PERFORMANCE_COUNTERS */ | ||
164 | |||
165 | static 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 | |||
187 | subsys_initcall(topology_init); | ||
188 | |||
189 | static const char *cpu_names[] = { | ||
190 | "Morgan", | ||
191 | "AP7000", | ||
192 | }; | ||
193 | #define NR_CPU_NAMES ARRAY_SIZE(cpu_names) | ||
194 | |||
195 | static const char *arch_names[] = { | ||
196 | "AVR32A", | ||
197 | "AVR32B", | ||
198 | }; | ||
199 | #define NR_ARCH_NAMES ARRAY_SIZE(arch_names) | ||
200 | |||
201 | static const char *mmu_types[] = { | ||
202 | "No MMU", | ||
203 | "ITLB and DTLB", | ||
204 | "Shared TLB", | ||
205 | "MPU" | ||
206 | }; | ||
207 | |||
208 | void __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 | ||
265 | static 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 | |||
305 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
306 | { | ||
307 | return *pos < 1 ? (void *)1 : NULL; | ||
308 | } | ||
309 | |||
310 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
311 | { | ||
312 | ++*pos; | ||
313 | return NULL; | ||
314 | } | ||
315 | |||
316 | static void c_stop(struct seq_file *m, void *v) | ||
317 | { | ||
318 | |||
319 | } | ||
320 | |||
321 | struct 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 | ||
40 | exception_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 | ||
88 | itlb_miss: | ||
89 | tlbmiss_save | ||
90 | rjmp tlb_miss_common | ||
91 | |||
92 | .section .tlbr.ex.text,"ax",@progbits | ||
93 | dtlb_miss_read: | ||
94 | tlbmiss_save | ||
95 | rjmp tlb_miss_common | ||
96 | |||
97 | .section .tlbw.ex.text,"ax",@progbits | ||
98 | dtlb_miss_write: | ||
99 | tlbmiss_save | ||
100 | |||
101 | .global tlb_miss_common | ||
102 | tlb_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 */ | ||
111 | pgtbl_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 */ | ||
146 | 1: 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 | |||
157 | handle_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 | ||
167 | system_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 | |||
181 | syscall_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 | ||
191 | syscall_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 | |||
204 | syscall_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 | ||
213 | syscall_table_addr: | ||
214 | .long sys_call_table | ||
215 | |||
216 | syscall_badsys: | ||
217 | mov r12, -ENOSYS | ||
218 | rjmp syscall_return | ||
219 | |||
220 | .global ret_from_fork | ||
221 | ret_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 | |||
231 | syscall_trace_enter: | ||
232 | pushm r8-r12 | ||
233 | rcall syscall_trace | ||
234 | popm r8-r12 | ||
235 | rjmp syscall_trace_cont | ||
236 | |||
237 | syscall_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 | |||
245 | 1: 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 | |||
253 | 2: 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 | |||
264 | 3: 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 */ | ||
278 | page_table_not_present: | ||
279 | page_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 */ | ||
290 | save_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 | |||
297 | 1: pushm r11, r12 /* PC and SR */ | ||
298 | unmask_exceptions | ||
299 | ret r12 | ||
300 | |||
301 | 2: 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 */ | ||
306 | handle_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... */ | ||
315 | bad_return: | ||
316 | sub r12, pc, (. - 1f) | ||
317 | bral panic | ||
318 | .align 2 | ||
319 | 1: .asciz "Return from critical exception!" | ||
320 | |||
321 | .align 1 | ||
322 | do_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 | |||
329 | do_bus_error_read: | ||
330 | sub sp, 4 | ||
331 | stmts --sp, r0-lr | ||
332 | rcall save_full_context_ex | ||
333 | mov r11, 0 | ||
334 | 1: mfsr r12, SYSREG_BEAR | ||
335 | mov r10, sp | ||
336 | rcall do_bus_error | ||
337 | rjmp ret_from_exception | ||
338 | |||
339 | .align 1 | ||
340 | do_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 | |||
350 | handle_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 | |||
359 | handle_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 | ||
369 | do_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 | |||
378 | do_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 | |||
406 | do_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 | |||
416 | ret_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 | |||
427 | fault_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 | |||
436 | fault_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 | ||
449 | 1: | ||
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 | |||
463 | irq_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 | |||
473 | fault_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 | |||
482 | 1: 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 | |||
493 | 2: 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 */ | ||
506 | handle_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 | */ | ||
549 | handle_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 | |||
566 | debug_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 | |||
575 | debug_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 | |||
583 | 1: 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 | |||
591 | 2: 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 | |||
602 | 3: 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 | ||
620 | irq_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 | |||
645 | 1: 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 | ||
653 | 2: | ||
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 | ||
18 | kernel_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 | ||
40 | init_sr: | ||
41 | .long 0x007f0000 /* Supervisor mode, everything masked */ | ||
42 | stack_addr: | ||
43 | .long init_thread_union | ||
44 | kernel_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 | |||
16 | static struct fs_struct init_fs = INIT_FS; | ||
17 | static struct files_struct init_files = INIT_FILES; | ||
18 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
19 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
20 | struct mm_struct init_mm = INIT_MM(init_mm); | ||
21 | |||
22 | EXPORT_SYMBOL(init_mm); | ||
23 | |||
24 | /* | ||
25 | * Initial thread structure. Must be aligned on an 8192-byte boundary. | ||
26 | */ | ||
27 | union 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 | */ | ||
36 | struct task_struct init_task = INIT_TASK(init_task); | ||
37 | |||
38 | EXPORT_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 | */ | ||
32 | void ack_bad_irq(unsigned int irq) | ||
33 | { | ||
34 | printk("unexpected IRQ %u\n", irq); | ||
35 | } | ||
36 | |||
37 | #ifdef CONFIG_PROC_FS | ||
38 | int 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 | |||
21 | DEFINE_PER_CPU(struct kprobe *, current_kprobe); | ||
22 | static unsigned long kprobe_status; | ||
23 | static struct pt_regs jprobe_saved_regs; | ||
24 | |||
25 | int __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 | |||
46 | void __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 | |||
54 | void __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 | |||
62 | static 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 | |||
86 | static 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 | |||
101 | static void __kprobes set_current_kprobe(struct kprobe *p) | ||
102 | { | ||
103 | __get_cpu_var(current_kprobe) = p; | ||
104 | } | ||
105 | |||
106 | static 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 | |||
151 | ss_probe: | ||
152 | prepare_singlestep(p, regs); | ||
153 | kprobe_status = KPROBE_HIT_SS; | ||
154 | return 1; | ||
155 | |||
156 | no_kprobe: | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static 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 | |||
181 | static 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 | */ | ||
200 | int __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 | |||
230 | int __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 | |||
247 | void __kprobes jprobe_return(void) | ||
248 | { | ||
249 | asm volatile("breakpoint" ::: "memory"); | ||
250 | } | ||
251 | |||
252 | int __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 | |||
263 | int __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 | |||
21 | void *module_alloc(unsigned long size) | ||
22 | { | ||
23 | if (size == 0) | ||
24 | return NULL; | ||
25 | return vmalloc(size); | ||
26 | } | ||
27 | |||
28 | void 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 | |||
38 | static 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 | |||
70 | int 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 | |||
137 | out_free_syminfo: | ||
138 | vfree(module->arch.syminfo); | ||
139 | module->arch.syminfo = NULL; | ||
140 | |||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | static 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 | |||
155 | int 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 | |||
303 | int 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 | |||
312 | int 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 | |||
321 | void 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 | |||
19 | void (*pm_power_off)(void) = NULL; | ||
20 | EXPORT_SYMBOL(pm_power_off); | ||
21 | |||
22 | /* | ||
23 | * This file handles the architecture-dependent parts of process handling.. | ||
24 | */ | ||
25 | |||
26 | void 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 | |||
39 | void machine_halt(void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | void machine_power_off(void) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | void 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 | */ | ||
66 | asmlinkage 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 | |||
74 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
75 | { | ||
76 | struct pt_regs regs; | ||
77 | |||
78 | memset(®s, 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, ®s, 0, NULL, NULL); | ||
89 | } | ||
90 | EXPORT_SYMBOL(kernel_thread); | ||
91 | |||
92 | /* | ||
93 | * Free current thread data structures etc | ||
94 | */ | ||
95 | void exit_thread(void) | ||
96 | { | ||
97 | /* nothing to do */ | ||
98 | } | ||
99 | |||
100 | void flush_thread(void) | ||
101 | { | ||
102 | /* nothing to do */ | ||
103 | } | ||
104 | |||
105 | void release_thread(struct task_struct *dead_task) | ||
106 | { | ||
107 | /* do nothing */ | ||
108 | } | ||
109 | |||
110 | static const char *cpu_modes[] = { | ||
111 | "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1", | ||
112 | "Interrupt level 2", "Interrupt level 3", "Exception", "NMI" | ||
113 | }; | ||
114 | |||
115 | void 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 | } | ||
156 | EXPORT_SYMBOL(show_regs); | ||
157 | |||
158 | /* Fill in the fpu structure for a core dump. This is easy -- we don't have any */ | ||
159 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | ||
160 | { | ||
161 | /* Not valid */ | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | asmlinkage void ret_from_fork(void); | ||
166 | |||
167 | int 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 */ | ||
191 | asmlinkage int sys_fork(struct pt_regs *regs) | ||
192 | { | ||
193 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
194 | } | ||
195 | |||
196 | asmlinkage 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 | |||
207 | asmlinkage 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 | |||
213 | asmlinkage 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 | |||
229 | out: | ||
230 | return error; | ||
231 | } | ||
232 | |||
233 | |||
234 | /* | ||
235 | * This function is supposed to answer the question "who called | ||
236 | * schedule()?" | ||
237 | */ | ||
238 | unsigned 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 | |||
26 | static 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 | |||
32 | static 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 | */ | ||
56 | void 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 | */ | ||
64 | static 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 | */ | ||
82 | static 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 | */ | ||
110 | static 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 | |||
129 | static 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 | |||
136 | static 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 | |||
155 | long 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 | |||
262 | asmlinkage 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 | |||
289 | asmlinkage 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 | */ | ||
343 | asmlinkage 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 | |||
52 | void __up(struct semaphore *sem) | ||
53 | { | ||
54 | wake_up(&sem->wait); | ||
55 | } | ||
56 | EXPORT_SYMBOL(__up); | ||
57 | |||
58 | void __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 | } | ||
94 | EXPORT_SYMBOL(__down); | ||
95 | |||
96 | int __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 | } | ||
148 | EXPORT_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 | |||
29 | extern int root_mountflags; | ||
30 | |||
31 | /* | ||
32 | * Bootloader-provided information about physical memory | ||
33 | */ | ||
34 | struct tag_mem_range *mem_phys; | ||
35 | struct tag_mem_range *mem_reserved; | ||
36 | struct 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 | */ | ||
42 | struct avr32_cpuinfo boot_cpu_data = { | ||
43 | .loops_per_jiffy = 5000000 | ||
44 | }; | ||
45 | EXPORT_SYMBOL(boot_cpu_data); | ||
46 | |||
47 | static 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 | */ | ||
53 | static struct tag_mem_range __initdata mem_range_cache[32]; | ||
54 | static unsigned mem_range_next_free; | ||
55 | |||
56 | /* | ||
57 | * Standard memory resources | ||
58 | */ | ||
59 | static 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 | */ | ||
90 | static unsigned long __initdata fbmem_start; | ||
91 | static 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 | */ | ||
103 | static 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 | } | ||
110 | early_param("fbmem", early_parse_fbmem); | ||
111 | |||
112 | static 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 | |||
148 | static 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 | |||
159 | static 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 | |||
197 | static 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 | |||
203 | static 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 | |||
210 | static 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 | |||
216 | static 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 | |||
226 | static 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 | |||
232 | static 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 | */ | ||
261 | static 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 | */ | ||
278 | static 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 | |||
287 | void __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 | |||
25 | asmlinkage 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 | |||
31 | struct rt_sigframe | ||
32 | { | ||
33 | struct siginfo info; | ||
34 | struct ucontext uc; | ||
35 | unsigned long retcode; | ||
36 | }; | ||
37 | |||
38 | static int | ||
39 | restore_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 | |||
73 | asmlinkage 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(¤t->sighand->siglock); | ||
89 | current->blocked = set; | ||
90 | recalc_sigpending(); | ||
91 | spin_unlock_irq(¤t->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 | |||
101 | badframe: | ||
102 | force_sig(SIGSEGV, current); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int | ||
107 | setup_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 | |||
134 | static inline void __user * | ||
135 | get_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 | |||
145 | static int | ||
146 | setup_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 | |||
207 | out: | ||
208 | return err; | ||
209 | } | ||
210 | |||
211 | static 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 | |||
220 | static inline void | ||
221 | handle_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(¤t->sighand->siglock); | ||
241 | sigorsets(¤t->blocked, ¤t->blocked, | ||
242 | &ka->sa.sa_mask); | ||
243 | sigaddset(¤t->blocked, sig); | ||
244 | recalc_sigpending(); | ||
245 | spin_unlock_irq(¤t->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 | */ | ||
259 | int 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 = ¤t->saved_sigmask; | ||
281 | else if (!oldset) | ||
282 | oldset = ¤t->blocked; | ||
283 | |||
284 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
285 | no_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, ¤t->saved_sigmask, NULL); | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | handle_signal(signr, &ka, &info, oldset, regs, syscall); | ||
316 | return 1; | ||
317 | } | ||
318 | |||
319 | asmlinkage 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, ¤t->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 | |||
17 | asmlinkage 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 | |||
30 | asmlinkage 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(¤t->mm->mmap_sem); | ||
45 | error = do_mmap_pgoff(file, addr, len, prot, flags, offset); | ||
46 | up_write(¤t->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 | ||
23 | sys_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 | |||
29 | static cycle_t read_cycle_count(void) | ||
30 | { | ||
31 | return (cycle_t)sysreg_read(COUNT); | ||
32 | } | ||
33 | |||
34 | static 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 | */ | ||
46 | static unsigned long null_rtc_get_time(void) | ||
47 | { | ||
48 | return mktime(2004, 1, 1, 0, 0, 0); | ||
49 | } | ||
50 | |||
51 | static int null_rtc_set_time(unsigned long sec) | ||
52 | { | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static unsigned long (*rtc_get_time)(void) = null_rtc_get_time; | ||
57 | static int (*rtc_set_time)(unsigned long) = null_rtc_set_time; | ||
58 | |||
59 | /* how many counter cycles in a jiffy? */ | ||
60 | static unsigned long cycles_per_jiffy; | ||
61 | |||
62 | /* cycle counter value at the previous timer interrupt */ | ||
63 | static unsigned int timerhi, timerlo; | ||
64 | |||
65 | /* the count value for the next timer interrupt */ | ||
66 | static unsigned int expirelo; | ||
67 | |||
68 | static 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 | |||
89 | static 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 | */ | ||
103 | static 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 | */ | ||
115 | unsigned 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 | */ | ||
127 | static 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 | |||
134 | static irqreturn_t | ||
135 | timer_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 | |||
165 | static struct irqaction timer_irqaction = { | ||
166 | .handler = timer_interrupt, | ||
167 | .flags = IRQF_DISABLED, | ||
168 | .name = "timer", | ||
169 | }; | ||
170 | |||
171 | void __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 | |||
221 | static struct sysdev_class timer_class = { | ||
222 | set_kset_name("timer"), | ||
223 | }; | ||
224 | |||
225 | static struct sys_device timer_device = { | ||
226 | .id = 0, | ||
227 | .cls = &timer_class, | ||
228 | }; | ||
229 | |||
230 | static 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 | |||
238 | device_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 | |||
22 | static 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 | |||
48 | out: | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | #ifdef CONFIG_FRAME_POINTER | ||
53 | static 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 | ||
89 | static 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 | |||
104 | void 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 | |||
121 | void 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 | |||
142 | void dump_stack(void) | ||
143 | { | ||
144 | show_stack(NULL, NULL); | ||
145 | } | ||
146 | EXPORT_SYMBOL(dump_stack); | ||
147 | |||
148 | ATOMIC_NOTIFIER_HEAD(avr32_die_chain); | ||
149 | |||
150 | int 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 | } | ||
156 | EXPORT_SYMBOL(register_die_notifier); | ||
157 | |||
158 | int unregister_die_notifier(struct notifier_block *nb) | ||
159 | { | ||
160 | return atomic_notifier_chain_unregister(&avr32_die_chain, nb); | ||
161 | } | ||
162 | EXPORT_SYMBOL(unregister_die_notifier); | ||
163 | |||
164 | static DEFINE_SPINLOCK(die_lock); | ||
165 | |||
166 | void __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 | |||
195 | void __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 | |||
202 | asmlinkage 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 | |||
217 | asmlinkage 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 | |||
225 | asmlinkage 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 */ | ||
256 | static LIST_HEAD(undef_hook); | ||
257 | static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; | ||
258 | |||
259 | void 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 | |||
266 | void 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 | |||
273 | static 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 | ||
299 | static 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 | ||
315 | static inline void do_bug_verbose(struct pt_regs *regs, u32 insn) | ||
316 | { | ||
317 | |||
318 | } | ||
319 | #endif | ||
320 | #endif | ||
321 | |||
322 | asmlinkage 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 | |||
354 | invalid_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 | |||
391 | kernel_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 | |||
406 | asmlinkage 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 | |||
422 | void __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 | |||
13 | OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32") | ||
14 | OUTPUT_ARCH(avr32) | ||
15 | ENTRY(_start) | ||
16 | |||
17 | /* Big endian */ | ||
18 | jiffies = jiffies_64 + 4; | ||
19 | |||
20 | SECTIONS | ||
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 | |||
5 | lib-y := copy_user.o clear_user.o | ||
6 | lib-y += strncpy_from_user.o strnlen_user.o | ||
7 | lib-y += delay.o memset.o memcpy.o findbit.o | ||
8 | lib-y += csum_partial.o csum_partial_copy_generic.o | ||
9 | lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o | ||
10 | lib-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 | |||
28 | 1: 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 | |||
28 | 1: 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 | |||
28 | 1: 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" | ||
16 | clear_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 | |||
28 | 1: sub r11, 4 | ||
29 | brlt 2f | ||
30 | |||
31 | 10: st.w r12++, r8 | ||
32 | sub r11, 4 | ||
33 | brge 10b | ||
34 | |||
35 | 2: sub r11, -4 | ||
36 | reteq 0 | ||
37 | |||
38 | /* Unaligned count or address */ | ||
39 | bld r11, 1 | ||
40 | brcc 12f | ||
41 | 11: st.h r12++, r8 | ||
42 | sub r11, 2 | ||
43 | reteq 0 | ||
44 | 12: st.b r12++, r8 | ||
45 | retal 0 | ||
46 | |||
47 | /* Unaligned address */ | ||
48 | 5: cp.w r11, 4 | ||
49 | brlt 2b | ||
50 | |||
51 | lsl r9, 2 | ||
52 | add pc, pc, r9 | ||
53 | 13: st.b r12++, r8 | ||
54 | sub r11, 1 | ||
55 | 14: st.b r12++, r8 | ||
56 | sub r11, 1 | ||
57 | 15: 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 | ||
66 | 18: sub r11, -4 | ||
67 | 19: 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 | ||
28 | copy_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 | ||
36 | copy_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 */ | ||
49 | 1: sub r10, 4 | ||
50 | brlt 3f | ||
51 | |||
52 | 2: | ||
53 | 10: ld.w r8, r11++ | ||
54 | 11: st.w r12++, r8 | ||
55 | sub r10, 4 | ||
56 | brge 2b | ||
57 | |||
58 | 3: 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 | */ | ||
65 | 4: | ||
66 | 20: ld.ub r8, r11++ | ||
67 | 21: st.b r12++, r8 | ||
68 | sub r10, 1 | ||
69 | reteq 0 | ||
70 | 22: ld.ub r8, r11++ | ||
71 | 23: st.b r12++, r8 | ||
72 | sub r10, 1 | ||
73 | reteq 0 | ||
74 | 24: ld.ub r8, r11++ | ||
75 | 25: st.b r12++, r8 | ||
76 | retal 0 | ||
77 | |||
78 | /* Handle unaligned from-pointer */ | ||
79 | 6: cp.w r10, 4 | ||
80 | brlt 4b | ||
81 | rsub r9, r9, 4 | ||
82 | |||
83 | 30: ld.ub r8, r11++ | ||
84 | 31: st.b r12++, r8 | ||
85 | sub r10, 1 | ||
86 | sub r9, 1 | ||
87 | breq 1b | ||
88 | 32: ld.ub r8, r11++ | ||
89 | 33: st.b r12++, r8 | ||
90 | sub r10, 1 | ||
91 | sub r9, 1 | ||
92 | breq 1b | ||
93 | 34: ld.ub r8, r11++ | ||
94 | 35: 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 | ||
101 | 19: sub r10, -4 | ||
102 | 29: 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 | ||
17 | csum_partial: | ||
18 | /* checksum complete words, aligned or not */ | ||
19 | 3: sub r11, 4 | ||
20 | brlt 5f | ||
21 | 4: 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 */ | ||
28 | 5: 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 | ||
40 | 6: ld.ub r8, r12++ | ||
41 | lsl r8, 8 | ||
42 | 7: 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 | ||
20 | 9999: 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 | ||
27 | 9999: 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 | ||
37 | csum_partial_copy_generic: | ||
38 | pushm r4-r7,lr | ||
39 | |||
40 | /* The inner loop */ | ||
41 | 1: sub r10, 4 | ||
42 | brlt 5f | ||
43 | 2: 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 */ | ||
51 | 5: sub r10, -4 | ||
52 | brne 7f | ||
53 | |||
54 | 6: mov r12, r9 | ||
55 | popm r4-r7,pc | ||
56 | |||
57 | /* handle additional bytes at the tail */ | ||
58 | 7: mov r5, 0 | ||
59 | mov r4, 32 | ||
60 | 8: 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 | ||
76 | fixup_ld_src: | ||
77 | mov r9, -EFAULT | ||
78 | cp.w r8, 0 | ||
79 | breq 1f | ||
80 | st.w r8[0], r9 | ||
81 | |||
82 | 1: /* | ||
83 | * TODO: zero the complete destination - computing the rest | ||
84 | * is too much work | ||
85 | */ | ||
86 | |||
87 | mov r9, 0 | ||
88 | rjmp 6b | ||
89 | |||
90 | fixup_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 | ||
96 | 1: 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 | |||
21 | int read_current_timer(unsigned long *timer_value) | ||
22 | { | ||
23 | *timer_value = sysreg_read(COUNT); | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | void __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 | |||
37 | inline 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 | |||
47 | void __udelay(unsigned long usecs) | ||
48 | { | ||
49 | __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ | ||
50 | } | ||
51 | |||
52 | void __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 | */ | ||
15 | ENTRY(find_first_zero_bit) | ||
16 | cp.w r11, 0 | ||
17 | reteq r11 | ||
18 | mov r9, r11 | ||
19 | 1: 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 | */ | ||
32 | ENTRY(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 */ | ||
55 | 1: 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 | */ | ||
79 | ENTRY(find_first_bit) | ||
80 | cp.w r11, 0 | ||
81 | reteq r11 | ||
82 | mov r9, r11 | ||
83 | 1: 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 | */ | ||
96 | ENTRY(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 */ | ||
118 | 1: 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 | |||
126 | ENTRY(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 */ | ||
148 | 1: 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 | */ | ||
19 | 1: 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 | |||
32 | 1: 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 | |||
38 | 2: 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 | |||
15 | 1: 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 | |||
26 | 1: 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 | |||
33 | 2: 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 | |||
5 | typedef int QItype __attribute__ ((mode (QI))); | ||
6 | typedef unsigned int UQItype __attribute__ ((mode (QI))); | ||
7 | typedef int HItype __attribute__ ((mode (HI))); | ||
8 | typedef unsigned int UHItype __attribute__ ((mode (HI))); | ||
9 | typedef int SItype __attribute__ ((mode (SI))); | ||
10 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
11 | typedef int DItype __attribute__ ((mode (DI))); | ||
12 | typedef unsigned int UDItype __attribute__ ((mode (DI))); | ||
13 | typedef float SFtype __attribute__ ((mode (SF))); | ||
14 | typedef float DFtype __attribute__ ((mode (DF))); | ||
15 | typedef 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 | |||
27 | struct DWstruct {Wtype high, low;}; | ||
28 | |||
29 | typedef 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 | ||
21 | memcpy: | ||
22 | mov r9, r11 | ||
23 | andl r9, 3, COH | ||
24 | brne 1f | ||
25 | |||
26 | /* At this point, "from" is word-aligned */ | ||
27 | 2: sub r10, 4 | ||
28 | mov r9, r12 | ||
29 | brlt 4f | ||
30 | |||
31 | 3: ld.w r8, r11++ | ||
32 | sub r10, 4 | ||
33 | st.w r12++, r8 | ||
34 | brge 3b | ||
35 | |||
36 | 4: 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 */ | ||
51 | 1: 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 | ||
26 | memset: | ||
27 | mov r9, r12 | ||
28 | mov r8, r12 | ||
29 | or r11, r11, r11 << 8 | ||
30 | andl r9, 3, COH | ||
31 | brne 1f | ||
32 | |||
33 | 2: or r11, r11, r11 << 16 | ||
34 | sub r10, 4 | ||
35 | brlt 5f | ||
36 | |||
37 | /* Let's do some real work */ | ||
38 | 4: 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 | */ | ||
46 | 5: 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 | ||
58 | 6: st.b r8++, r11 | ||
59 | retal r12 | ||
60 | |||
61 | /* Handle unaligned pointer */ | ||
62 | 1: 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" | ||
30 | strncpy_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 | |||
43 | 1: 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 | |||
50 | 2: sub r10, r9 | ||
51 | retal r10 | ||
52 | |||
53 | .section .fixup, "ax" | ||
54 | .align 1 | ||
55 | 3: 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" | ||
19 | strnlen_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 | |||
31 | 10: ld.ub r8, r12++ | ||
32 | cp.w r8, 0 | ||
33 | breq 2f | ||
34 | sub r11, 1 | ||
35 | brne 10b | ||
36 | |||
37 | sub r12, -1 | ||
38 | 2: sub r12, r10 | ||
39 | retal r12 | ||
40 | |||
41 | |||
42 | .type adjust_length, "function" | ||
43 | adjust_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 | ||
55 | 1: popm pc, r12=0 | ||
56 | |||
57 | .align 2 | ||
58 | _task_size: | ||
59 | .long TASK_SIZE | ||
60 | |||
61 | .section .fixup, "ax" | ||
62 | .align 1 | ||
63 | 19: 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..4b10853eb614 --- /dev/null +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-y += at32ap.o clock.o pio.o intc.o extint.o | ||
2 | obj-$(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 | |||
19 | struct at32_sm system_manager; | ||
20 | |||
21 | static 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 | |||
41 | fail: | ||
42 | printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | void __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 | |||
56 | static 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 | |||
79 | static struct platform_driver pdc_driver = { | ||
80 | .probe = pdc_probe, | ||
81 | .driver = { | ||
82 | .name = "pdc", | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static int __init pdc_init(void) | ||
87 | { | ||
88 | return platform_driver_register(&pdc_driver); | ||
89 | } | ||
90 | arch_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..e8c6893a1c23 --- /dev/null +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -0,0 +1,866 @@ | |||
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) \ | ||
43 | static 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) \ | ||
50 | static 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) \ | ||
61 | static 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 | |||
70 | enum { | ||
71 | PIOA, | ||
72 | PIOB, | ||
73 | PIOC, | ||
74 | PIOD, | ||
75 | }; | ||
76 | |||
77 | enum { | ||
78 | FUNC_A, | ||
79 | FUNC_B, | ||
80 | }; | ||
81 | |||
82 | unsigned long at32ap7000_osc_rates[3] = { | ||
83 | [0] = 32768, | ||
84 | /* FIXME: these are ATSTK1002-specific */ | ||
85 | [1] = 20000000, | ||
86 | [2] = 12000000, | ||
87 | }; | ||
88 | |||
89 | static unsigned long osc_get_rate(struct clk *clk) | ||
90 | { | ||
91 | return at32ap7000_osc_rates[clk->index]; | ||
92 | } | ||
93 | |||
94 | static 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 | |||
111 | static 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 | |||
120 | static 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 | */ | ||
133 | static struct clk osc32k = { | ||
134 | .name = "osc32k", | ||
135 | .get_rate = osc_get_rate, | ||
136 | .users = 1, | ||
137 | .index = 0, | ||
138 | }; | ||
139 | static struct clk osc0 = { | ||
140 | .name = "osc0", | ||
141 | .get_rate = osc_get_rate, | ||
142 | .users = 1, | ||
143 | .index = 1, | ||
144 | }; | ||
145 | static struct clk osc1 = { | ||
146 | .name = "osc1", | ||
147 | .get_rate = osc_get_rate, | ||
148 | .index = 2, | ||
149 | }; | ||
150 | static struct clk pll0 = { | ||
151 | .name = "pll0", | ||
152 | .get_rate = pll0_get_rate, | ||
153 | .parent = &osc0, | ||
154 | }; | ||
155 | static 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 | */ | ||
166 | static 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 | */ | ||
174 | static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) | ||
175 | { | ||
176 | return main_clock->get_rate(main_clock) >> shift; | ||
177 | }; | ||
178 | |||
179 | static 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 | |||
195 | static 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 | |||
206 | static 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 | |||
222 | static 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 | |||
233 | static 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 | |||
249 | static 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 | |||
260 | static 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 | |||
276 | static 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 | |||
287 | static struct clk cpu_clk = { | ||
288 | .name = "cpu", | ||
289 | .get_rate = cpu_clk_get_rate, | ||
290 | .users = 1, | ||
291 | }; | ||
292 | static struct clk hsb_clk = { | ||
293 | .name = "hsb", | ||
294 | .parent = &cpu_clk, | ||
295 | .get_rate = hsb_clk_get_rate, | ||
296 | }; | ||
297 | static 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 | }; | ||
304 | static 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 | |||
317 | static 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 | |||
331 | static 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 | |||
348 | static 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 | |||
380 | int 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 | * -------------------------------------------------------------------- */ | ||
413 | static struct resource sm_resource[] = { | ||
414 | PBMEM(0xfff00000), | ||
415 | NAMED_IRQ(19, "eim"), | ||
416 | NAMED_IRQ(20, "pm"), | ||
417 | NAMED_IRQ(21, "rtc"), | ||
418 | }; | ||
419 | struct platform_device at32_sm_device = { | ||
420 | .name = "sm", | ||
421 | .id = 0, | ||
422 | .resource = sm_resource, | ||
423 | .num_resources = ARRAY_SIZE(sm_resource), | ||
424 | }; | ||
425 | DEV_CLK(pclk, at32_sm, pbb, 0); | ||
426 | |||
427 | static struct resource intc0_resource[] = { | ||
428 | PBMEM(0xfff00400), | ||
429 | }; | ||
430 | struct platform_device at32_intc0_device = { | ||
431 | .name = "intc", | ||
432 | .id = 0, | ||
433 | .resource = intc0_resource, | ||
434 | .num_resources = ARRAY_SIZE(intc0_resource), | ||
435 | }; | ||
436 | DEV_CLK(pclk, at32_intc0, pbb, 1); | ||
437 | |||
438 | static 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 | }; | ||
445 | static 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 | |||
453 | static struct platform_device pdc_device = { | ||
454 | .name = "pdc", | ||
455 | .id = 0, | ||
456 | }; | ||
457 | DEV_CLK(hclk, pdc, hsb, 4); | ||
458 | DEV_CLK(pclk, pdc, pba, 16); | ||
459 | |||
460 | static struct clk pico_clk = { | ||
461 | .name = "pico", | ||
462 | .parent = &cpu_clk, | ||
463 | .mode = cpu_clk_mode, | ||
464 | .get_rate = cpu_clk_get_rate, | ||
465 | .users = 1, | ||
466 | }; | ||
467 | |||
468 | /* -------------------------------------------------------------------- | ||
469 | * PIO | ||
470 | * -------------------------------------------------------------------- */ | ||
471 | |||
472 | static struct resource pio0_resource[] = { | ||
473 | PBMEM(0xffe02800), | ||
474 | IRQ(13), | ||
475 | }; | ||
476 | DEFINE_DEV(pio, 0); | ||
477 | DEV_CLK(mck, pio0, pba, 10); | ||
478 | |||
479 | static struct resource pio1_resource[] = { | ||
480 | PBMEM(0xffe02c00), | ||
481 | IRQ(14), | ||
482 | }; | ||
483 | DEFINE_DEV(pio, 1); | ||
484 | DEV_CLK(mck, pio1, pba, 11); | ||
485 | |||
486 | static struct resource pio2_resource[] = { | ||
487 | PBMEM(0xffe03000), | ||
488 | IRQ(15), | ||
489 | }; | ||
490 | DEFINE_DEV(pio, 2); | ||
491 | DEV_CLK(mck, pio2, pba, 12); | ||
492 | |||
493 | static struct resource pio3_resource[] = { | ||
494 | PBMEM(0xffe03400), | ||
495 | IRQ(16), | ||
496 | }; | ||
497 | DEFINE_DEV(pio, 3); | ||
498 | DEV_CLK(mck, pio3, pba, 13); | ||
499 | |||
500 | void __init at32_add_system_devices(void) | ||
501 | { | ||
502 | system_manager.eim_first_irq = NR_INTERNAL_IRQS; | ||
503 | |||
504 | platform_device_register(&at32_sm_device); | ||
505 | platform_device_register(&at32_intc0_device); | ||
506 | platform_device_register(&pdc_device); | ||
507 | |||
508 | platform_device_register(&pio0_device); | ||
509 | platform_device_register(&pio1_device); | ||
510 | platform_device_register(&pio2_device); | ||
511 | platform_device_register(&pio3_device); | ||
512 | } | ||
513 | |||
514 | /* -------------------------------------------------------------------- | ||
515 | * USART | ||
516 | * -------------------------------------------------------------------- */ | ||
517 | |||
518 | static struct resource usart0_resource[] = { | ||
519 | PBMEM(0xffe00c00), | ||
520 | IRQ(7), | ||
521 | }; | ||
522 | DEFINE_DEV(usart, 0); | ||
523 | DEV_CLK(usart, usart0, pba, 4); | ||
524 | |||
525 | static struct resource usart1_resource[] = { | ||
526 | PBMEM(0xffe01000), | ||
527 | IRQ(7), | ||
528 | }; | ||
529 | DEFINE_DEV(usart, 1); | ||
530 | DEV_CLK(usart, usart1, pba, 4); | ||
531 | |||
532 | static struct resource usart2_resource[] = { | ||
533 | PBMEM(0xffe01400), | ||
534 | IRQ(8), | ||
535 | }; | ||
536 | DEFINE_DEV(usart, 2); | ||
537 | DEV_CLK(usart, usart2, pba, 5); | ||
538 | |||
539 | static struct resource usart3_resource[] = { | ||
540 | PBMEM(0xffe01800), | ||
541 | IRQ(9), | ||
542 | }; | ||
543 | DEFINE_DEV(usart, 3); | ||
544 | DEV_CLK(usart, usart3, pba, 6); | ||
545 | |||
546 | static inline void configure_usart0_pins(void) | ||
547 | { | ||
548 | portmux_set_func(PIOA, 8, FUNC_B); /* RXD */ | ||
549 | portmux_set_func(PIOA, 9, FUNC_B); /* TXD */ | ||
550 | } | ||
551 | |||
552 | static inline void configure_usart1_pins(void) | ||
553 | { | ||
554 | portmux_set_func(PIOA, 17, FUNC_A); /* RXD */ | ||
555 | portmux_set_func(PIOA, 18, FUNC_A); /* TXD */ | ||
556 | } | ||
557 | |||
558 | static inline void configure_usart2_pins(void) | ||
559 | { | ||
560 | portmux_set_func(PIOB, 26, FUNC_B); /* RXD */ | ||
561 | portmux_set_func(PIOB, 27, FUNC_B); /* TXD */ | ||
562 | } | ||
563 | |||
564 | static inline void configure_usart3_pins(void) | ||
565 | { | ||
566 | portmux_set_func(PIOB, 18, FUNC_B); /* RXD */ | ||
567 | portmux_set_func(PIOB, 17, FUNC_B); /* TXD */ | ||
568 | } | ||
569 | |||
570 | static struct platform_device *setup_usart(unsigned int id) | ||
571 | { | ||
572 | struct platform_device *pdev; | ||
573 | |||
574 | switch (id) { | ||
575 | case 0: | ||
576 | pdev = &usart0_device; | ||
577 | configure_usart0_pins(); | ||
578 | break; | ||
579 | case 1: | ||
580 | pdev = &usart1_device; | ||
581 | configure_usart1_pins(); | ||
582 | break; | ||
583 | case 2: | ||
584 | pdev = &usart2_device; | ||
585 | configure_usart2_pins(); | ||
586 | break; | ||
587 | case 3: | ||
588 | pdev = &usart3_device; | ||
589 | configure_usart3_pins(); | ||
590 | break; | ||
591 | default: | ||
592 | pdev = NULL; | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | return pdev; | ||
597 | } | ||
598 | |||
599 | struct platform_device *__init at32_add_device_usart(unsigned int id) | ||
600 | { | ||
601 | struct platform_device *pdev; | ||
602 | |||
603 | pdev = setup_usart(id); | ||
604 | if (pdev) | ||
605 | platform_device_register(pdev); | ||
606 | |||
607 | return pdev; | ||
608 | } | ||
609 | |||
610 | struct platform_device *at91_default_console_device; | ||
611 | |||
612 | void __init at32_setup_serial_console(unsigned int usart_id) | ||
613 | { | ||
614 | at91_default_console_device = setup_usart(usart_id); | ||
615 | } | ||
616 | |||
617 | /* -------------------------------------------------------------------- | ||
618 | * Ethernet | ||
619 | * -------------------------------------------------------------------- */ | ||
620 | |||
621 | static struct eth_platform_data macb0_data; | ||
622 | static struct resource macb0_resource[] = { | ||
623 | PBMEM(0xfff01800), | ||
624 | IRQ(25), | ||
625 | }; | ||
626 | DEFINE_DEV_DATA(macb, 0); | ||
627 | DEV_CLK(hclk, macb0, hsb, 8); | ||
628 | DEV_CLK(pclk, macb0, pbb, 6); | ||
629 | |||
630 | struct platform_device *__init | ||
631 | at32_add_device_eth(unsigned int id, struct eth_platform_data *data) | ||
632 | { | ||
633 | struct platform_device *pdev; | ||
634 | |||
635 | switch (id) { | ||
636 | case 0: | ||
637 | pdev = &macb0_device; | ||
638 | |||
639 | portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */ | ||
640 | portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */ | ||
641 | portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */ | ||
642 | portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */ | ||
643 | portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */ | ||
644 | portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */ | ||
645 | portmux_set_func(PIOC, 13, FUNC_A); /* RXER */ | ||
646 | portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */ | ||
647 | portmux_set_func(PIOC, 16, FUNC_A); /* MDC */ | ||
648 | portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */ | ||
649 | |||
650 | if (!data->is_rmii) { | ||
651 | portmux_set_func(PIOC, 0, FUNC_A); /* COL */ | ||
652 | portmux_set_func(PIOC, 1, FUNC_A); /* CRS */ | ||
653 | portmux_set_func(PIOC, 2, FUNC_A); /* TXER */ | ||
654 | portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */ | ||
655 | portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */ | ||
656 | portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */ | ||
657 | portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */ | ||
658 | portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */ | ||
659 | portmux_set_func(PIOC, 18, FUNC_A); /* SPD */ | ||
660 | } | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | return NULL; | ||
665 | } | ||
666 | |||
667 | memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data)); | ||
668 | platform_device_register(pdev); | ||
669 | |||
670 | return pdev; | ||
671 | } | ||
672 | |||
673 | /* -------------------------------------------------------------------- | ||
674 | * SPI | ||
675 | * -------------------------------------------------------------------- */ | ||
676 | static struct resource spi0_resource[] = { | ||
677 | PBMEM(0xffe00000), | ||
678 | IRQ(3), | ||
679 | }; | ||
680 | DEFINE_DEV(spi, 0); | ||
681 | DEV_CLK(mck, spi0, pba, 0); | ||
682 | |||
683 | struct platform_device *__init at32_add_device_spi(unsigned int id) | ||
684 | { | ||
685 | struct platform_device *pdev; | ||
686 | |||
687 | switch (id) { | ||
688 | case 0: | ||
689 | pdev = &spi0_device; | ||
690 | portmux_set_func(PIOA, 0, FUNC_A); /* MISO */ | ||
691 | portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */ | ||
692 | portmux_set_func(PIOA, 2, FUNC_A); /* SCK */ | ||
693 | portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */ | ||
694 | portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */ | ||
695 | portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */ | ||
696 | break; | ||
697 | |||
698 | default: | ||
699 | return NULL; | ||
700 | } | ||
701 | |||
702 | platform_device_register(pdev); | ||
703 | return pdev; | ||
704 | } | ||
705 | |||
706 | /* -------------------------------------------------------------------- | ||
707 | * LCDC | ||
708 | * -------------------------------------------------------------------- */ | ||
709 | static struct lcdc_platform_data lcdc0_data; | ||
710 | static struct resource lcdc0_resource[] = { | ||
711 | { | ||
712 | .start = 0xff000000, | ||
713 | .end = 0xff000fff, | ||
714 | .flags = IORESOURCE_MEM, | ||
715 | }, | ||
716 | IRQ(1), | ||
717 | }; | ||
718 | DEFINE_DEV_DATA(lcdc, 0); | ||
719 | DEV_CLK(hclk, lcdc0, hsb, 7); | ||
720 | static struct clk lcdc0_pixclk = { | ||
721 | .name = "pixclk", | ||
722 | .dev = &lcdc0_device.dev, | ||
723 | .mode = genclk_mode, | ||
724 | .get_rate = genclk_get_rate, | ||
725 | .set_rate = genclk_set_rate, | ||
726 | .set_parent = genclk_set_parent, | ||
727 | .index = 7, | ||
728 | }; | ||
729 | |||
730 | struct platform_device *__init | ||
731 | at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data) | ||
732 | { | ||
733 | struct platform_device *pdev; | ||
734 | |||
735 | switch (id) { | ||
736 | case 0: | ||
737 | pdev = &lcdc0_device; | ||
738 | portmux_set_func(PIOC, 19, FUNC_A); /* CC */ | ||
739 | portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */ | ||
740 | portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */ | ||
741 | portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */ | ||
742 | portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */ | ||
743 | portmux_set_func(PIOC, 24, FUNC_A); /* MODE */ | ||
744 | portmux_set_func(PIOC, 25, FUNC_A); /* PWR */ | ||
745 | portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */ | ||
746 | portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */ | ||
747 | portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */ | ||
748 | portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */ | ||
749 | portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */ | ||
750 | portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */ | ||
751 | portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */ | ||
752 | portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */ | ||
753 | portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */ | ||
754 | portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */ | ||
755 | portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */ | ||
756 | portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */ | ||
757 | portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */ | ||
758 | portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */ | ||
759 | portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */ | ||
760 | portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */ | ||
761 | portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */ | ||
762 | portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */ | ||
763 | portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */ | ||
764 | portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */ | ||
765 | portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */ | ||
766 | portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */ | ||
767 | portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */ | ||
768 | portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */ | ||
769 | |||
770 | clk_set_parent(&lcdc0_pixclk, &pll0); | ||
771 | clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); | ||
772 | break; | ||
773 | |||
774 | default: | ||
775 | return NULL; | ||
776 | } | ||
777 | |||
778 | memcpy(pdev->dev.platform_data, data, | ||
779 | sizeof(struct lcdc_platform_data)); | ||
780 | |||
781 | platform_device_register(pdev); | ||
782 | return pdev; | ||
783 | } | ||
784 | |||
785 | struct clk *at32_clock_list[] = { | ||
786 | &osc32k, | ||
787 | &osc0, | ||
788 | &osc1, | ||
789 | &pll0, | ||
790 | &pll1, | ||
791 | &cpu_clk, | ||
792 | &hsb_clk, | ||
793 | &pba_clk, | ||
794 | &pbb_clk, | ||
795 | &at32_sm_pclk, | ||
796 | &at32_intc0_pclk, | ||
797 | &ebi_clk, | ||
798 | &hramc_clk, | ||
799 | &pdc_hclk, | ||
800 | &pdc_pclk, | ||
801 | &pico_clk, | ||
802 | &pio0_mck, | ||
803 | &pio1_mck, | ||
804 | &pio2_mck, | ||
805 | &pio3_mck, | ||
806 | &usart0_usart, | ||
807 | &usart1_usart, | ||
808 | &usart2_usart, | ||
809 | &usart3_usart, | ||
810 | &macb0_hclk, | ||
811 | &macb0_pclk, | ||
812 | &spi0_mck, | ||
813 | &lcdc0_hclk, | ||
814 | &lcdc0_pixclk, | ||
815 | }; | ||
816 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); | ||
817 | |||
818 | void __init at32_portmux_init(void) | ||
819 | { | ||
820 | at32_init_pio(&pio0_device); | ||
821 | at32_init_pio(&pio1_device); | ||
822 | at32_init_pio(&pio2_device); | ||
823 | at32_init_pio(&pio3_device); | ||
824 | } | ||
825 | |||
826 | void __init at32_clock_init(void) | ||
827 | { | ||
828 | struct at32_sm *sm = &system_manager; | ||
829 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; | ||
830 | int i; | ||
831 | |||
832 | if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL)) | ||
833 | main_clock = &pll0; | ||
834 | else | ||
835 | main_clock = &osc0; | ||
836 | |||
837 | if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC)) | ||
838 | pll0.parent = &osc1; | ||
839 | if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) | ||
840 | pll1.parent = &osc1; | ||
841 | |||
842 | /* | ||
843 | * Turn on all clocks that have at least one user already, and | ||
844 | * turn off everything else. We only do this for module | ||
845 | * clocks, and even though it isn't particularly pretty to | ||
846 | * check the address of the mode function, it should do the | ||
847 | * trick... | ||
848 | */ | ||
849 | for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { | ||
850 | struct clk *clk = at32_clock_list[i]; | ||
851 | |||
852 | if (clk->mode == &cpu_clk_mode) | ||
853 | cpu_mask |= 1 << clk->index; | ||
854 | else if (clk->mode == &hsb_clk_mode) | ||
855 | hsb_mask |= 1 << clk->index; | ||
856 | else if (clk->mode == &pba_clk_mode) | ||
857 | pba_mask |= 1 << clk->index; | ||
858 | else if (clk->mode == &pbb_clk_mode) | ||
859 | pbb_mask |= 1 << clk->index; | ||
860 | } | ||
861 | |||
862 | sm_writel(sm, PM_CPU_MASK, cpu_mask); | ||
863 | sm_writel(sm, PM_HSB_MASK, hsb_mask); | ||
864 | sm_writel(sm, PM_PBA_MASK, pba_mask); | ||
865 | sm_writel(sm, PM_PBB_MASK, pbb_mask); | ||
866 | } | ||
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 | |||
21 | static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED; | ||
22 | |||
23 | struct 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 | } | ||
36 | EXPORT_SYMBOL(clk_get); | ||
37 | |||
38 | void clk_put(struct clk *clk) | ||
39 | { | ||
40 | /* clocks are static for now, we can't free them */ | ||
41 | } | ||
42 | EXPORT_SYMBOL(clk_put); | ||
43 | |||
44 | static 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 | |||
52 | int 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 | } | ||
62 | EXPORT_SYMBOL(clk_enable); | ||
63 | |||
64 | static 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 | |||
74 | void 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 | } | ||
82 | EXPORT_SYMBOL(clk_disable); | ||
83 | |||
84 | unsigned 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 | } | ||
95 | EXPORT_SYMBOL(clk_get_rate); | ||
96 | |||
97 | long 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 | } | ||
110 | EXPORT_SYMBOL(clk_round_rate); | ||
111 | |||
112 | int 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 | } | ||
126 | EXPORT_SYMBOL(clk_set_rate); | ||
127 | |||
128 | int 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 | } | ||
142 | EXPORT_SYMBOL(clk_set_parent); | ||
143 | |||
144 | struct clk *clk_get_parent(struct clk *clk) | ||
145 | { | ||
146 | return clk->parent; | ||
147 | } | ||
148 | EXPORT_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 | |||
16 | struct 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 | |||
29 | extern struct clk *at32_clock_list[]; | ||
30 | extern 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 | |||
24 | static 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 | |||
30 | static 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 | |||
36 | static 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 | |||
43 | static 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 | |||
49 | static 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 | |||
96 | struct 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 | |||
105 | static 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 | |||
130 | static 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 | } | ||
171 | arch_initcall(eim_init); | ||
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 | |||
20 | struct intc { | ||
21 | void __iomem *regs; | ||
22 | struct irq_chip chip; | ||
23 | }; | ||
24 | |||
25 | extern 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 | */ | ||
31 | static void intc_mask_irq(unsigned int irq) | ||
32 | { | ||
33 | |||
34 | } | ||
35 | |||
36 | static void intc_unmask_irq(unsigned int irq) | ||
37 | { | ||
38 | |||
39 | } | ||
40 | |||
41 | static 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 | */ | ||
52 | asmlinkage 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 | |||
80 | void __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 | |||
130 | fail: | ||
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 | |||
24 | struct 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 | |||
32 | static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; | ||
33 | |||
34 | void 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 | |||
51 | static 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 | |||
69 | static struct platform_driver pio_driver = { | ||
70 | .probe = pio_probe, | ||
71 | .driver = { | ||
72 | .name = "pio", | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static int __init pio_init(void) | ||
77 | { | ||
78 | return platform_driver_register(&pio_driver); | ||
79 | } | ||
80 | subsys_initcall(pio_init); | ||
81 | |||
82 | void __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 | |||
176 | void 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 | |||
33 | struct at32_sm system_manager; | ||
34 | |||
35 | int __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 | |||
55 | fail: | ||
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 | |||
70 | static 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 | |||
78 | static struct irqaction eim_spurious_action = { | ||
79 | .handler = spurious_eim_interrupt, | ||
80 | }; | ||
81 | |||
82 | static 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 | |||
125 | unlock: | ||
126 | spin_unlock(&sm->lock); | ||
127 | return IRQ_HANDLED; | ||
128 | } | ||
129 | |||
130 | static 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 | |||
139 | static 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 | |||
148 | static 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 | |||
159 | static 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 | |||
167 | static 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 | |||
202 | static 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 | |||
228 | static 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 | |||
239 | static 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 | |||
284 | out_free_actions: | ||
285 | kfree(sm->action); | ||
286 | out: | ||
287 | return ret; | ||
288 | } | ||
289 | arch_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 | |||
5 | obj-y += init.o clear_page.o copy_page.o dma-coherent.o | ||
6 | obj-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 | |||
23 | void 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 | |||
39 | void 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 | |||
52 | void 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 | |||
65 | void 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 | |||
77 | static 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 | */ | ||
93 | void 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 | */ | ||
105 | void 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 | */ | ||
117 | void 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 | |||
124 | asmlinkage 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 | |||
148 | out: | ||
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 | ||
18 | clear_page: | ||
19 | sub r9, r12, -PAGE_SIZE | ||
20 | mov r10, 0 | ||
21 | mov r11, 0 | ||
22 | 0: 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 | ||
20 | copy_page: | ||
21 | sub r10, r11, -(1 << PAGE_SHIFT) | ||
22 | /* pref r11[0] */ | ||
23 | 1: /* 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 | |||
14 | void 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 | } | ||
36 | EXPORT_SYMBOL(dma_cache_sync); | ||
37 | |||
38 | static 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 | |||
78 | static 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 | |||
87 | void *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 | } | ||
99 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
100 | |||
101 | void 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 | } | ||
113 | EXPORT_SYMBOL(dma_free_coherent); | ||
114 | |||
115 | #if 0 | ||
116 | void *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 | } | ||
126 | EXPORT_SYMBOL(dma_alloc_writecombine); | ||
127 | |||
128 | void 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 | } | ||
138 | EXPORT_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 | ||
23 | static 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 | ||
41 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
42 | |||
43 | /* Hook to register for page fault notifications */ | ||
44 | int register_page_fault_notifier(struct notifier_block *nb) | ||
45 | { | ||
46 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
47 | } | ||
48 | |||
49 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
50 | { | ||
51 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
52 | } | ||
53 | |||
54 | static 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(¬ify_page_fault_chain, val, &args); | ||
62 | } | ||
63 | #else | ||
64 | static 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 | */ | ||
83 | asmlinkage 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 | */ | ||
127 | good_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 | */ | ||
155 | survive: | ||
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 | */ | ||
178 | bad_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 | |||
211 | no_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 | */ | ||
254 | out_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 | |||
267 | do_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 | |||
287 | asmlinkage 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 | ||
310 | void kernel_map_pages(struct page *page, int numpages, int enable) | ||
311 | { | ||
312 | |||
313 | } | ||
314 | EXPORT_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 | |||
28 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
29 | |||
30 | pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
31 | |||
32 | struct page *empty_zero_page; | ||
33 | |||
34 | /* | ||
35 | * Cache of MMU context last used. | ||
36 | */ | ||
37 | unsigned 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 | |||
42 | void 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 | |||
81 | static 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 | */ | ||
101 | static 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 | */ | ||
131 | static unsigned long __init | ||
132 | find_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 | |||
189 | void __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 | */ | ||
323 | void __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 | |||
392 | void __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 | |||
440 | static 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 | |||
457 | void 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 | |||
465 | static int keep_initrd; | ||
466 | |||
467 | void free_initrd_mem(unsigned long start, unsigned long end) | ||
468 | { | ||
469 | if (!keep_initrd) | ||
470 | free_area(start, end, "initrd"); | ||
471 | } | ||
472 | |||
473 | static 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 | |||
17 | static 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 | |||
36 | static 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 | |||
60 | static 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 | |||
84 | static 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 | */ | ||
128 | void __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 | } | ||
180 | EXPORT_SYMBOL(__ioremap); | ||
181 | |||
182 | void __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 | } | ||
197 | EXPORT_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 | |||
16 | void 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 | |||
51 | void 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 | |||
60 | static unsigned long last_mmucr; | ||
61 | |||
62 | static 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 | |||
95 | static 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 | |||
112 | void 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 | |||
126 | void __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 | |||
158 | void 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 | |||
181 | void 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 | */ | ||
223 | void 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 | |||
249 | void 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 | |||
263 | void 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 | |||
278 | static 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 | |||
289 | static 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 | |||
301 | static void tlb_stop(struct seq_file *tlb, void *v) | ||
302 | { | ||
303 | |||
304 | } | ||
305 | |||
306 | static 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 | |||
349 | static struct seq_operations tlb_ops = { | ||
350 | .start = tlb_start, | ||
351 | .next = tlb_next, | ||
352 | .stop = tlb_stop, | ||
353 | .show = tlb_show, | ||
354 | }; | ||
355 | |||
356 | static int tlb_open(struct inode *inode, struct file *file) | ||
357 | { | ||
358 | return seq_open(file, &tlb_ops); | ||
359 | } | ||
360 | |||
361 | static struct file_operations proc_tlb_operations = { | ||
362 | .open = tlb_open, | ||
363 | .read = seq_read, | ||
364 | .llseek = seq_lseek, | ||
365 | .release = seq_release, | ||
366 | }; | ||
367 | |||
368 | static 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 | } | ||
377 | late_initcall(proctlb_init); | ||
378 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/include/asm-avr32/Kbuild b/include/asm-avr32/Kbuild new file mode 100644 index 000000000000..8770e73ce938 --- /dev/null +++ b/include/asm-avr32/Kbuild | |||
@@ -0,0 +1,3 @@ | |||
1 | include include/asm-generic/Kbuild.asm | ||
2 | |||
3 | headers-y += cachectl.h | ||
diff --git a/include/asm-avr32/a.out.h b/include/asm-avr32/a.out.h new file mode 100644 index 000000000000..50bf6e31a143 --- /dev/null +++ b/include/asm-avr32/a.out.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef __ASM_AVR32_A_OUT_H | ||
2 | #define __ASM_AVR32_A_OUT_H | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #ifdef __KERNEL__ | ||
21 | |||
22 | #define STACK_TOP TASK_SIZE | ||
23 | |||
24 | #endif | ||
25 | |||
26 | #endif /* __ASM_AVR32_A_OUT_H */ | ||
diff --git a/include/asm-avr32/addrspace.h b/include/asm-avr32/addrspace.h new file mode 100644 index 000000000000..366794858ec7 --- /dev/null +++ b/include/asm-avr32/addrspace.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Defitions for the address spaces of the AVR32 CPUs. Heavily based on | ||
3 | * include/asm-sh/addrspace.h | ||
4 | * | ||
5 | * Copyright (C) 2004-2006 Atmel Corporation | ||
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 | #ifndef __ASM_AVR32_ADDRSPACE_H | ||
12 | #define __ASM_AVR32_ADDRSPACE_H | ||
13 | |||
14 | #ifdef CONFIG_MMU | ||
15 | |||
16 | /* Memory segments when segmentation is enabled */ | ||
17 | #define P0SEG 0x00000000 | ||
18 | #define P1SEG 0x80000000 | ||
19 | #define P2SEG 0xa0000000 | ||
20 | #define P3SEG 0xc0000000 | ||
21 | #define P4SEG 0xe0000000 | ||
22 | |||
23 | /* Returns the privileged segment base of a given address */ | ||
24 | #define PXSEG(a) (((unsigned long)(a)) & 0xe0000000) | ||
25 | |||
26 | /* Returns the physical address of a PnSEG (n=1,2) address */ | ||
27 | #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) | ||
28 | |||
29 | /* | ||
30 | * Map an address to a certain privileged segment | ||
31 | */ | ||
32 | #define P1SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ | ||
33 | | P1SEG)) | ||
34 | #define P2SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ | ||
35 | | P2SEG)) | ||
36 | #define P3SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ | ||
37 | | P3SEG)) | ||
38 | #define P4SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) \ | ||
39 | | P4SEG)) | ||
40 | |||
41 | #endif /* CONFIG_MMU */ | ||
42 | |||
43 | #endif /* __ASM_AVR32_ADDRSPACE_H */ | ||
diff --git a/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h b/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h new file mode 100644 index 000000000000..ce1150d4438d --- /dev/null +++ b/include/asm-avr32/arch-at32ap/at91rm9200_pdc.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h | ||
3 | * | ||
4 | * Copyright (C) 2005 Ivan Kokshaysky | ||
5 | * Copyright (C) SAN People | ||
6 | * | ||
7 | * Peripheral Data Controller (PDC) registers. | ||
8 | * Based on AT91RM9200 datasheet revision E. | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef AT91RM9200_PDC_H | ||
17 | #define AT91RM9200_PDC_H | ||
18 | |||
19 | #define AT91_PDC_RPR 0x100 /* Receive Pointer Register */ | ||
20 | #define AT91_PDC_RCR 0x104 /* Receive Counter Register */ | ||
21 | #define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */ | ||
22 | #define AT91_PDC_TCR 0x10c /* Transmit Counter Register */ | ||
23 | #define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */ | ||
24 | #define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */ | ||
25 | #define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */ | ||
26 | #define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */ | ||
27 | |||
28 | #define AT91_PDC_PTCR 0x120 /* Transfer Control Register */ | ||
29 | #define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */ | ||
30 | #define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */ | ||
31 | #define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */ | ||
32 | #define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */ | ||
33 | |||
34 | #define AT91_PDC_PTSR 0x124 /* Transfer Status Register */ | ||
35 | |||
36 | #endif | ||
diff --git a/include/asm-avr32/arch-at32ap/at91rm9200_usart.h b/include/asm-avr32/arch-at32ap/at91rm9200_usart.h new file mode 100644 index 000000000000..79f851e31b9c --- /dev/null +++ b/include/asm-avr32/arch-at32ap/at91rm9200_usart.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * include/asm-arm/arch-at91rm9200/at91rm9200_usart.h | ||
3 | * | ||
4 | * Copyright (C) 2005 Ivan Kokshaysky | ||
5 | * Copyright (C) SAN People | ||
6 | * | ||
7 | * USART registers. | ||
8 | * Based on AT91RM9200 datasheet revision E. | ||
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 as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifndef AT91RM9200_USART_H | ||
17 | #define AT91RM9200_USART_H | ||
18 | |||
19 | #define AT91_US_CR 0x00 /* Control Register */ | ||
20 | #define AT91_US_RSTRX (1 << 2) /* Reset Receiver */ | ||
21 | #define AT91_US_RSTTX (1 << 3) /* Reset Transmitter */ | ||
22 | #define AT91_US_RXEN (1 << 4) /* Receiver Enable */ | ||
23 | #define AT91_US_RXDIS (1 << 5) /* Receiver Disable */ | ||
24 | #define AT91_US_TXEN (1 << 6) /* Transmitter Enable */ | ||
25 | #define AT91_US_TXDIS (1 << 7) /* Transmitter Disable */ | ||
26 | #define AT91_US_RSTSTA (1 << 8) /* Reset Status Bits */ | ||
27 | #define AT91_US_STTBRK (1 << 9) /* Start Break */ | ||
28 | #define AT91_US_STPBRK (1 << 10) /* Stop Break */ | ||
29 | #define AT91_US_STTTO (1 << 11) /* Start Time-out */ | ||
30 | #define AT91_US_SENDA (1 << 12) /* Send Address */ | ||
31 | #define AT91_US_RSTIT (1 << 13) /* Reset Iterations */ | ||
32 | #define AT91_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ | ||
33 | #define AT91_US_RETTO (1 << 15) /* Rearm Time-out */ | ||
34 | #define AT91_US_DTREN (1 << 16) /* Data Terminal Ready Enable */ | ||
35 | #define AT91_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */ | ||
36 | #define AT91_US_RTSEN (1 << 18) /* Request To Send Enable */ | ||
37 | #define AT91_US_RTSDIS (1 << 19) /* Request To Send Disable */ | ||
38 | |||
39 | #define AT91_US_MR 0x04 /* Mode Register */ | ||
40 | #define AT91_US_USMODE (0xf << 0) /* Mode of the USART */ | ||
41 | #define AT91_US_USMODE_NORMAL 0 | ||
42 | #define AT91_US_USMODE_RS485 1 | ||
43 | #define AT91_US_USMODE_HWHS 2 | ||
44 | #define AT91_US_USMODE_MODEM 3 | ||
45 | #define AT91_US_USMODE_ISO7816_T0 4 | ||
46 | #define AT91_US_USMODE_ISO7816_T1 6 | ||
47 | #define AT91_US_USMODE_IRDA 8 | ||
48 | #define AT91_US_USCLKS (3 << 4) /* Clock Selection */ | ||
49 | #define AT91_US_CHRL (3 << 6) /* Character Length */ | ||
50 | #define AT91_US_CHRL_5 (0 << 6) | ||
51 | #define AT91_US_CHRL_6 (1 << 6) | ||
52 | #define AT91_US_CHRL_7 (2 << 6) | ||
53 | #define AT91_US_CHRL_8 (3 << 6) | ||
54 | #define AT91_US_SYNC (1 << 8) /* Synchronous Mode Select */ | ||
55 | #define AT91_US_PAR (7 << 9) /* Parity Type */ | ||
56 | #define AT91_US_PAR_EVEN (0 << 9) | ||
57 | #define AT91_US_PAR_ODD (1 << 9) | ||
58 | #define AT91_US_PAR_SPACE (2 << 9) | ||
59 | #define AT91_US_PAR_MARK (3 << 9) | ||
60 | #define AT91_US_PAR_NONE (4 << 9) | ||
61 | #define AT91_US_PAR_MULTI_DROP (6 << 9) | ||
62 | #define AT91_US_NBSTOP (3 << 12) /* Number of Stop Bits */ | ||
63 | #define AT91_US_NBSTOP_1 (0 << 12) | ||
64 | #define AT91_US_NBSTOP_1_5 (1 << 12) | ||
65 | #define AT91_US_NBSTOP_2 (2 << 12) | ||
66 | #define AT91_US_CHMODE (3 << 14) /* Channel Mode */ | ||
67 | #define AT91_US_CHMODE_NORMAL (0 << 14) | ||
68 | #define AT91_US_CHMODE_ECHO (1 << 14) | ||
69 | #define AT91_US_CHMODE_LOC_LOOP (2 << 14) | ||
70 | #define AT91_US_CHMODE_REM_LOOP (3 << 14) | ||
71 | #define AT91_US_MSBF (1 << 16) /* Bit Order */ | ||
72 | #define AT91_US_MODE9 (1 << 17) /* 9-bit Character Length */ | ||
73 | #define AT91_US_CLKO (1 << 18) /* Clock Output Select */ | ||
74 | #define AT91_US_OVER (1 << 19) /* Oversampling Mode */ | ||
75 | #define AT91_US_INACK (1 << 20) /* Inhibit Non Acknowledge */ | ||
76 | #define AT91_US_DSNACK (1 << 21) /* Disable Successive NACK */ | ||
77 | #define AT91_US_MAX_ITER (7 << 24) /* Max Iterations */ | ||
78 | #define AT91_US_FILTER (1 << 28) /* Infrared Receive Line Filter */ | ||
79 | |||
80 | #define AT91_US_IER 0x08 /* Interrupt Enable Register */ | ||
81 | #define AT91_US_RXRDY (1 << 0) /* Receiver Ready */ | ||
82 | #define AT91_US_TXRDY (1 << 1) /* Transmitter Ready */ | ||
83 | #define AT91_US_RXBRK (1 << 2) /* Break Received / End of Break */ | ||
84 | #define AT91_US_ENDRX (1 << 3) /* End of Receiver Transfer */ | ||
85 | #define AT91_US_ENDTX (1 << 4) /* End of Transmitter Transfer */ | ||
86 | #define AT91_US_OVRE (1 << 5) /* Overrun Error */ | ||
87 | #define AT91_US_FRAME (1 << 6) /* Framing Error */ | ||
88 | #define AT91_US_PARE (1 << 7) /* Parity Error */ | ||
89 | #define AT91_US_TIMEOUT (1 << 8) /* Receiver Time-out */ | ||
90 | #define AT91_US_TXEMPTY (1 << 9) /* Transmitter Empty */ | ||
91 | #define AT91_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */ | ||
92 | #define AT91_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ | ||
93 | #define AT91_US_RXBUFF (1 << 12) /* Reception Buffer Full */ | ||
94 | #define AT91_US_NACK (1 << 13) /* Non Acknowledge */ | ||
95 | #define AT91_US_RIIC (1 << 16) /* Ring Indicator Input Change */ | ||
96 | #define AT91_US_DSRIC (1 << 17) /* Data Set Ready Input Change */ | ||
97 | #define AT91_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */ | ||
98 | #define AT91_US_CTSIC (1 << 19) /* Clear to Send Input Change */ | ||
99 | #define AT91_US_RI (1 << 20) /* RI */ | ||
100 | #define AT91_US_DSR (1 << 21) /* DSR */ | ||
101 | #define AT91_US_DCD (1 << 22) /* DCD */ | ||
102 | #define AT91_US_CTS (1 << 23) /* CTS */ | ||
103 | |||
104 | #define AT91_US_IDR 0x0c /* Interrupt Disable Register */ | ||
105 | #define AT91_US_IMR 0x10 /* Interrupt Mask Register */ | ||
106 | #define AT91_US_CSR 0x14 /* Channel Status Register */ | ||
107 | #define AT91_US_RHR 0x18 /* Receiver Holding Register */ | ||
108 | #define AT91_US_THR 0x1c /* Transmitter Holding Register */ | ||
109 | |||
110 | #define AT91_US_BRGR 0x20 /* Baud Rate Generator Register */ | ||
111 | #define AT91_US_CD (0xffff << 0) /* Clock Divider */ | ||
112 | |||
113 | #define AT91_US_RTOR 0x24 /* Receiver Time-out Register */ | ||
114 | #define AT91_US_TO (0xffff << 0) /* Time-out Value */ | ||
115 | |||
116 | #define AT91_US_TTGR 0x28 /* Transmitter Timeguard Register */ | ||
117 | #define AT91_US_TG (0xff << 0) /* Timeguard Value */ | ||
118 | |||
119 | #define AT91_US_FIDI 0x40 /* FI DI Ratio Register */ | ||
120 | #define AT91_US_NER 0x44 /* Number of Errors Register */ | ||
121 | #define AT91_US_IF 0x4c /* IrDA Filter Register */ | ||
122 | |||
123 | #endif | ||
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h new file mode 100644 index 000000000000..39368e18ab20 --- /dev/null +++ b/include/asm-avr32/arch-at32ap/board.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Platform data definitions. | ||
3 | */ | ||
4 | #ifndef __ASM_ARCH_BOARD_H | ||
5 | #define __ASM_ARCH_BOARD_H | ||
6 | |||
7 | #include <linux/types.h> | ||
8 | |||
9 | /* Add basic devices: system manager, interrupt controller, portmuxes, etc. */ | ||
10 | void at32_add_system_devices(void); | ||
11 | |||
12 | #define AT91_NR_UART 4 | ||
13 | extern struct platform_device *at91_default_console_device; | ||
14 | |||
15 | struct platform_device *at32_add_device_usart(unsigned int id); | ||
16 | |||
17 | struct eth_platform_data { | ||
18 | u8 valid; | ||
19 | u8 mii_phy_addr; | ||
20 | u8 is_rmii; | ||
21 | u8 hw_addr[6]; | ||
22 | }; | ||
23 | struct platform_device * | ||
24 | at32_add_device_eth(unsigned int id, struct eth_platform_data *data); | ||
25 | |||
26 | struct platform_device *at32_add_device_spi(unsigned int id); | ||
27 | |||
28 | struct lcdc_platform_data { | ||
29 | unsigned long fbmem_start; | ||
30 | unsigned long fbmem_size; | ||
31 | }; | ||
32 | struct platform_device * | ||
33 | at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data); | ||
34 | |||
35 | #endif /* __ASM_ARCH_BOARD_H */ | ||
diff --git a/include/asm-avr32/arch-at32ap/init.h b/include/asm-avr32/arch-at32ap/init.h new file mode 100644 index 000000000000..43722634e069 --- /dev/null +++ b/include/asm-avr32/arch-at32ap/init.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * AT32AP platform initialization calls. | ||
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_AT32AP_INIT_H__ | ||
11 | #define __ASM_AVR32_AT32AP_INIT_H__ | ||
12 | |||
13 | void setup_platform(void); | ||
14 | |||
15 | /* Called by setup_platform */ | ||
16 | void at32_clock_init(void); | ||
17 | void at32_portmux_init(void); | ||
18 | |||
19 | void at32_setup_serial_console(unsigned int usart_id); | ||
20 | |||
21 | #endif /* __ASM_AVR32_AT32AP_INIT_H__ */ | ||
diff --git a/include/asm-avr32/arch-at32ap/portmux.h b/include/asm-avr32/arch-at32ap/portmux.h new file mode 100644 index 000000000000..4d50421262a1 --- /dev/null +++ b/include/asm-avr32/arch-at32ap/portmux.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * AT32 portmux interface. | ||
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_AT32_PORTMUX_H__ | ||
11 | #define __ASM_AVR32_AT32_PORTMUX_H__ | ||
12 | |||
13 | void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, | ||
14 | unsigned int function_id); | ||
15 | |||
16 | #endif /* __ASM_AVR32_AT32_PORTMUX_H__ */ | ||
diff --git a/include/asm-avr32/arch-at32ap/sm.h b/include/asm-avr32/arch-at32ap/sm.h new file mode 100644 index 000000000000..265a9ead20bf --- /dev/null +++ b/include/asm-avr32/arch-at32ap/sm.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * AT32 System Manager interface. | ||
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_AT32_SM_H__ | ||
11 | #define __ASM_AVR32_AT32_SM_H__ | ||
12 | |||
13 | struct irq_chip; | ||
14 | struct platform_device; | ||
15 | |||
16 | struct at32_sm { | ||
17 | spinlock_t lock; | ||
18 | void __iomem *regs; | ||
19 | struct irq_chip *eim_chip; | ||
20 | unsigned int eim_first_irq; | ||
21 | struct platform_device *pdev; | ||
22 | }; | ||
23 | |||
24 | extern struct platform_device at32_sm_device; | ||
25 | extern struct at32_sm system_manager; | ||
26 | |||
27 | #endif /* __ASM_AVR32_AT32_SM_H__ */ | ||
diff --git a/include/asm-avr32/asm.h b/include/asm-avr32/asm.h new file mode 100644 index 000000000000..515c7618952b --- /dev/null +++ b/include/asm-avr32/asm.h | |||
@@ -0,0 +1,102 @@ | |||
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 | #ifndef __ASM_AVR32_ASM_H__ | ||
9 | #define __ASM_AVR32_ASM_H__ | ||
10 | |||
11 | #include <asm/sysreg.h> | ||
12 | #include <asm/asm-offsets.h> | ||
13 | #include <asm/thread_info.h> | ||
14 | |||
15 | #define mask_interrupts ssrf SR_GM_BIT | ||
16 | #define mask_exceptions ssrf SR_EM_BIT | ||
17 | #define unmask_interrupts csrf SR_GM_BIT | ||
18 | #define unmask_exceptions csrf SR_EM_BIT | ||
19 | |||
20 | #ifdef CONFIG_FRAME_POINTER | ||
21 | .macro save_fp | ||
22 | st.w --sp, r7 | ||
23 | .endm | ||
24 | .macro restore_fp | ||
25 | ld.w r7, sp++ | ||
26 | .endm | ||
27 | .macro zero_fp | ||
28 | mov r7, 0 | ||
29 | .endm | ||
30 | #else | ||
31 | .macro save_fp | ||
32 | .endm | ||
33 | .macro restore_fp | ||
34 | .endm | ||
35 | .macro zero_fp | ||
36 | .endm | ||
37 | #endif | ||
38 | .macro get_thread_info reg | ||
39 | mov \reg, sp | ||
40 | andl \reg, ~(THREAD_SIZE - 1) & 0xffff | ||
41 | .endm | ||
42 | |||
43 | /* Save and restore registers */ | ||
44 | .macro save_min sr, tmp=lr | ||
45 | pushm lr | ||
46 | mfsr \tmp, \sr | ||
47 | zero_fp | ||
48 | st.w --sp, \tmp | ||
49 | .endm | ||
50 | |||
51 | .macro restore_min sr, tmp=lr | ||
52 | ld.w \tmp, sp++ | ||
53 | mtsr \sr, \tmp | ||
54 | popm lr | ||
55 | .endm | ||
56 | |||
57 | .macro save_half sr, tmp=lr | ||
58 | save_fp | ||
59 | pushm r8-r9,r10,r11,r12,lr | ||
60 | zero_fp | ||
61 | mfsr \tmp, \sr | ||
62 | st.w --sp, \tmp | ||
63 | .endm | ||
64 | |||
65 | .macro restore_half sr, tmp=lr | ||
66 | ld.w \tmp, sp++ | ||
67 | mtsr \sr, \tmp | ||
68 | popm r8-r9,r10,r11,r12,lr | ||
69 | restore_fp | ||
70 | .endm | ||
71 | |||
72 | .macro save_full_user sr, tmp=lr | ||
73 | stmts --sp, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,sp,lr | ||
74 | st.w --sp, lr | ||
75 | zero_fp | ||
76 | mfsr \tmp, \sr | ||
77 | st.w --sp, \tmp | ||
78 | .endm | ||
79 | |||
80 | .macro restore_full_user sr, tmp=lr | ||
81 | ld.w \tmp, sp++ | ||
82 | mtsr \sr, \tmp | ||
83 | ld.w lr, sp++ | ||
84 | ldmts sp++, r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,sp,lr | ||
85 | .endm | ||
86 | |||
87 | /* uaccess macros */ | ||
88 | .macro branch_if_kernel scratch, label | ||
89 | get_thread_info \scratch | ||
90 | ld.w \scratch, \scratch[TI_flags] | ||
91 | bld \scratch, TIF_USERSPACE | ||
92 | brcc \label | ||
93 | .endm | ||
94 | |||
95 | .macro ret_if_privileged scratch, addr, size, ret | ||
96 | sub \scratch, \size, 1 | ||
97 | add \scratch, \addr | ||
98 | retcs \ret | ||
99 | retmi \ret | ||
100 | .endm | ||
101 | |||
102 | #endif /* __ASM_AVR32_ASM_H__ */ | ||
diff --git a/include/asm-avr32/atomic.h b/include/asm-avr32/atomic.h new file mode 100644 index 000000000000..e0b9c44c126c --- /dev/null +++ b/include/asm-avr32/atomic.h | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Atomic operations that C can't guarantee us. Useful for | ||
3 | * resource counting etc. | ||
4 | * | ||
5 | * But use these as seldom as possible since they are slower than | ||
6 | * regular operations. | ||
7 | * | ||
8 | * Copyright (C) 2004-2006 Atmel 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 | #ifndef __ASM_AVR32_ATOMIC_H | ||
15 | #define __ASM_AVR32_ATOMIC_H | ||
16 | |||
17 | #include <asm/system.h> | ||
18 | |||
19 | typedef struct { volatile int counter; } atomic_t; | ||
20 | #define ATOMIC_INIT(i) { (i) } | ||
21 | |||
22 | #define atomic_read(v) ((v)->counter) | ||
23 | #define atomic_set(v, i) (((v)->counter) = i) | ||
24 | |||
25 | /* | ||
26 | * atomic_sub_return - subtract the atomic variable | ||
27 | * @i: integer value to subtract | ||
28 | * @v: pointer of type atomic_t | ||
29 | * | ||
30 | * Atomically subtracts @i from @v. Returns the resulting value. | ||
31 | */ | ||
32 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
33 | { | ||
34 | int result; | ||
35 | |||
36 | asm volatile( | ||
37 | "/* atomic_sub_return */\n" | ||
38 | "1: ssrf 5\n" | ||
39 | " ld.w %0, %2\n" | ||
40 | " sub %0, %3\n" | ||
41 | " stcond %1, %0\n" | ||
42 | " brne 1b" | ||
43 | : "=&r"(result), "=o"(v->counter) | ||
44 | : "m"(v->counter), "ir"(i) | ||
45 | : "cc"); | ||
46 | |||
47 | return result; | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * atomic_add_return - add integer to atomic variable | ||
52 | * @i: integer value to add | ||
53 | * @v: pointer of type atomic_t | ||
54 | * | ||
55 | * Atomically adds @i to @v. Returns the resulting value. | ||
56 | */ | ||
57 | static inline int atomic_add_return(int i, atomic_t *v) | ||
58 | { | ||
59 | int result; | ||
60 | |||
61 | if (__builtin_constant_p(i)) | ||
62 | result = atomic_sub_return(-i, v); | ||
63 | else | ||
64 | asm volatile( | ||
65 | "/* atomic_add_return */\n" | ||
66 | "1: ssrf 5\n" | ||
67 | " ld.w %0, %1\n" | ||
68 | " add %0, %3\n" | ||
69 | " stcond %2, %0\n" | ||
70 | " brne 1b" | ||
71 | : "=&r"(result), "=o"(v->counter) | ||
72 | : "m"(v->counter), "r"(i) | ||
73 | : "cc", "memory"); | ||
74 | |||
75 | return result; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * atomic_sub_unless - sub unless the number is a given value | ||
80 | * @v: pointer of type atomic_t | ||
81 | * @a: the amount to add to v... | ||
82 | * @u: ...unless v is equal to u. | ||
83 | * | ||
84 | * If the atomic value v is not equal to u, this function subtracts a | ||
85 | * from v, and returns non zero. If v is equal to u then it returns | ||
86 | * zero. This is done as an atomic operation. | ||
87 | */ | ||
88 | static inline int atomic_sub_unless(atomic_t *v, int a, int u) | ||
89 | { | ||
90 | int tmp, result = 0; | ||
91 | |||
92 | asm volatile( | ||
93 | "/* atomic_sub_unless */\n" | ||
94 | "1: ssrf 5\n" | ||
95 | " ld.w %0, %3\n" | ||
96 | " cp.w %0, %5\n" | ||
97 | " breq 1f\n" | ||
98 | " sub %0, %4\n" | ||
99 | " stcond %2, %0\n" | ||
100 | " brne 1b\n" | ||
101 | " mov %1, 1\n" | ||
102 | "1:" | ||
103 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) | ||
104 | : "m"(v->counter), "ir"(a), "ir"(u) | ||
105 | : "cc", "memory"); | ||
106 | |||
107 | return result; | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * atomic_add_unless - add unless the number is a given value | ||
112 | * @v: pointer of type atomic_t | ||
113 | * @a: the amount to add to v... | ||
114 | * @u: ...unless v is equal to u. | ||
115 | * | ||
116 | * If the atomic value v is not equal to u, this function adds a to v, | ||
117 | * and returns non zero. If v is equal to u then it returns zero. This | ||
118 | * is done as an atomic operation. | ||
119 | */ | ||
120 | static inline int atomic_add_unless(atomic_t *v, int a, int u) | ||
121 | { | ||
122 | int tmp, result; | ||
123 | |||
124 | if (__builtin_constant_p(a)) | ||
125 | result = atomic_sub_unless(v, -a, u); | ||
126 | else { | ||
127 | result = 0; | ||
128 | asm volatile( | ||
129 | "/* atomic_add_unless */\n" | ||
130 | "1: ssrf 5\n" | ||
131 | " ld.w %0, %3\n" | ||
132 | " cp.w %0, %5\n" | ||
133 | " breq 1f\n" | ||
134 | " add %0, %4\n" | ||
135 | " stcond %2, %0\n" | ||
136 | " brne 1b\n" | ||
137 | " mov %1, 1\n" | ||
138 | "1:" | ||
139 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) | ||
140 | : "m"(v->counter), "r"(a), "ir"(u) | ||
141 | : "cc", "memory"); | ||
142 | } | ||
143 | |||
144 | return result; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * atomic_sub_if_positive - conditionally subtract integer from atomic variable | ||
149 | * @i: integer value to subtract | ||
150 | * @v: pointer of type atomic_t | ||
151 | * | ||
152 | * Atomically test @v and subtract @i if @v is greater or equal than @i. | ||
153 | * The function returns the old value of @v minus @i. | ||
154 | */ | ||
155 | static inline int atomic_sub_if_positive(int i, atomic_t *v) | ||
156 | { | ||
157 | int result; | ||
158 | |||
159 | asm volatile( | ||
160 | "/* atomic_sub_if_positive */\n" | ||
161 | "1: ssrf 5\n" | ||
162 | " ld.w %0, %2\n" | ||
163 | " sub %0, %3\n" | ||
164 | " brlt 1f\n" | ||
165 | " stcond %1, %0\n" | ||
166 | " brne 1b\n" | ||
167 | "1:" | ||
168 | : "=&r"(result), "=o"(v->counter) | ||
169 | : "m"(v->counter), "ir"(i) | ||
170 | : "cc", "memory"); | ||
171 | |||
172 | return result; | ||
173 | } | ||
174 | |||
175 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
176 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
177 | |||
178 | #define atomic_sub(i, v) (void)atomic_sub_return(i, v) | ||
179 | #define atomic_add(i, v) (void)atomic_add_return(i, v) | ||
180 | #define atomic_dec(v) atomic_sub(1, (v)) | ||
181 | #define atomic_inc(v) atomic_add(1, (v)) | ||
182 | |||
183 | #define atomic_dec_return(v) atomic_sub_return(1, v) | ||
184 | #define atomic_inc_return(v) atomic_add_return(1, v) | ||
185 | |||
186 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) | ||
187 | #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) | ||
188 | #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) | ||
189 | #define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0) | ||
190 | |||
191 | #define atomic_inc_not_zero(v) atomic_add_unless(v, 1, 0) | ||
192 | #define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v) | ||
193 | |||
194 | #define smp_mb__before_atomic_dec() barrier() | ||
195 | #define smp_mb__after_atomic_dec() barrier() | ||
196 | #define smp_mb__before_atomic_inc() barrier() | ||
197 | #define smp_mb__after_atomic_inc() barrier() | ||
198 | |||
199 | #include <asm-generic/atomic.h> | ||
200 | |||
201 | #endif /* __ASM_AVR32_ATOMIC_H */ | ||
diff --git a/include/asm-avr32/auxvec.h b/include/asm-avr32/auxvec.h new file mode 100644 index 000000000000..d5dd435bf8f4 --- /dev/null +++ b/include/asm-avr32/auxvec.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef __ASM_AVR32_AUXVEC_H | ||
2 | #define __ASM_AVR32_AUXVEC_H | ||
3 | |||
4 | #endif /* __ASM_AVR32_AUXVEC_H */ | ||
diff --git a/include/asm-avr32/bitops.h b/include/asm-avr32/bitops.h new file mode 100644 index 000000000000..5299f8c8e11d --- /dev/null +++ b/include/asm-avr32/bitops.h | |||
@@ -0,0 +1,296 @@ | |||
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 | #ifndef __ASM_AVR32_BITOPS_H | ||
9 | #define __ASM_AVR32_BITOPS_H | ||
10 | |||
11 | #include <asm/byteorder.h> | ||
12 | #include <asm/system.h> | ||
13 | |||
14 | /* | ||
15 | * clear_bit() doesn't provide any barrier for the compiler | ||
16 | */ | ||
17 | #define smp_mb__before_clear_bit() barrier() | ||
18 | #define smp_mb__after_clear_bit() barrier() | ||
19 | |||
20 | /* | ||
21 | * set_bit - Atomically set a bit in memory | ||
22 | * @nr: the bit to set | ||
23 | * @addr: the address to start counting from | ||
24 | * | ||
25 | * This function is atomic and may not be reordered. See __set_bit() | ||
26 | * if you do not require the atomic guarantees. | ||
27 | * | ||
28 | * Note that @nr may be almost arbitrarily large; this function is not | ||
29 | * restricted to acting on a single-word quantity. | ||
30 | */ | ||
31 | static inline void set_bit(int nr, volatile void * addr) | ||
32 | { | ||
33 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
34 | unsigned long tmp; | ||
35 | |||
36 | if (__builtin_constant_p(nr)) { | ||
37 | asm volatile( | ||
38 | "1: ssrf 5\n" | ||
39 | " ld.w %0, %2\n" | ||
40 | " sbr %0, %3\n" | ||
41 | " stcond %1, %0\n" | ||
42 | " brne 1b" | ||
43 | : "=&r"(tmp), "=o"(*p) | ||
44 | : "m"(*p), "i"(nr) | ||
45 | : "cc"); | ||
46 | } else { | ||
47 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
48 | asm volatile( | ||
49 | "1: ssrf 5\n" | ||
50 | " ld.w %0, %2\n" | ||
51 | " or %0, %3\n" | ||
52 | " stcond %1, %0\n" | ||
53 | " brne 1b" | ||
54 | : "=&r"(tmp), "=o"(*p) | ||
55 | : "m"(*p), "r"(mask) | ||
56 | : "cc"); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * clear_bit - Clears a bit in memory | ||
62 | * @nr: Bit to clear | ||
63 | * @addr: Address to start counting from | ||
64 | * | ||
65 | * clear_bit() is atomic and may not be reordered. However, it does | ||
66 | * not contain a memory barrier, so if it is used for locking purposes, | ||
67 | * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() | ||
68 | * in order to ensure changes are visible on other processors. | ||
69 | */ | ||
70 | static inline void clear_bit(int nr, volatile void * addr) | ||
71 | { | ||
72 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
73 | unsigned long tmp; | ||
74 | |||
75 | if (__builtin_constant_p(nr)) { | ||
76 | asm volatile( | ||
77 | "1: ssrf 5\n" | ||
78 | " ld.w %0, %2\n" | ||
79 | " cbr %0, %3\n" | ||
80 | " stcond %1, %0\n" | ||
81 | " brne 1b" | ||
82 | : "=&r"(tmp), "=o"(*p) | ||
83 | : "m"(*p), "i"(nr) | ||
84 | : "cc"); | ||
85 | } else { | ||
86 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
87 | asm volatile( | ||
88 | "1: ssrf 5\n" | ||
89 | " ld.w %0, %2\n" | ||
90 | " andn %0, %3\n" | ||
91 | " stcond %1, %0\n" | ||
92 | " brne 1b" | ||
93 | : "=&r"(tmp), "=o"(*p) | ||
94 | : "m"(*p), "r"(mask) | ||
95 | : "cc"); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * change_bit - Toggle a bit in memory | ||
101 | * @nr: Bit to change | ||
102 | * @addr: Address to start counting from | ||
103 | * | ||
104 | * change_bit() is atomic and may not be reordered. | ||
105 | * Note that @nr may be almost arbitrarily large; this function is not | ||
106 | * restricted to acting on a single-word quantity. | ||
107 | */ | ||
108 | static inline void change_bit(int nr, volatile void * addr) | ||
109 | { | ||
110 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
111 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
112 | unsigned long tmp; | ||
113 | |||
114 | asm volatile( | ||
115 | "1: ssrf 5\n" | ||
116 | " ld.w %0, %2\n" | ||
117 | " eor %0, %3\n" | ||
118 | " stcond %1, %0\n" | ||
119 | " brne 1b" | ||
120 | : "=&r"(tmp), "=o"(*p) | ||
121 | : "m"(*p), "r"(mask) | ||
122 | : "cc"); | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * test_and_set_bit - Set a bit and return its old value | ||
127 | * @nr: Bit to set | ||
128 | * @addr: Address to count from | ||
129 | * | ||
130 | * This operation is atomic and cannot be reordered. | ||
131 | * It also implies a memory barrier. | ||
132 | */ | ||
133 | static inline int test_and_set_bit(int nr, volatile void * addr) | ||
134 | { | ||
135 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
136 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
137 | unsigned long tmp, old; | ||
138 | |||
139 | if (__builtin_constant_p(nr)) { | ||
140 | asm volatile( | ||
141 | "1: ssrf 5\n" | ||
142 | " ld.w %0, %3\n" | ||
143 | " mov %2, %0\n" | ||
144 | " sbr %0, %4\n" | ||
145 | " stcond %1, %0\n" | ||
146 | " brne 1b" | ||
147 | : "=&r"(tmp), "=o"(*p), "=&r"(old) | ||
148 | : "m"(*p), "i"(nr) | ||
149 | : "memory", "cc"); | ||
150 | } else { | ||
151 | asm volatile( | ||
152 | "1: ssrf 5\n" | ||
153 | " ld.w %2, %3\n" | ||
154 | " or %0, %2, %4\n" | ||
155 | " stcond %1, %0\n" | ||
156 | " brne 1b" | ||
157 | : "=&r"(tmp), "=o"(*p), "=&r"(old) | ||
158 | : "m"(*p), "r"(mask) | ||
159 | : "memory", "cc"); | ||
160 | } | ||
161 | |||
162 | return (old & mask) != 0; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * test_and_clear_bit - Clear a bit and return its old value | ||
167 | * @nr: Bit to clear | ||
168 | * @addr: Address to count from | ||
169 | * | ||
170 | * This operation is atomic and cannot be reordered. | ||
171 | * It also implies a memory barrier. | ||
172 | */ | ||
173 | static inline int test_and_clear_bit(int nr, volatile void * addr) | ||
174 | { | ||
175 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
176 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
177 | unsigned long tmp, old; | ||
178 | |||
179 | if (__builtin_constant_p(nr)) { | ||
180 | asm volatile( | ||
181 | "1: ssrf 5\n" | ||
182 | " ld.w %0, %3\n" | ||
183 | " mov %2, %0\n" | ||
184 | " cbr %0, %4\n" | ||
185 | " stcond %1, %0\n" | ||
186 | " brne 1b" | ||
187 | : "=&r"(tmp), "=o"(*p), "=&r"(old) | ||
188 | : "m"(*p), "i"(nr) | ||
189 | : "memory", "cc"); | ||
190 | } else { | ||
191 | asm volatile( | ||
192 | "1: ssrf 5\n" | ||
193 | " ld.w %0, %3\n" | ||
194 | " mov %2, %0\n" | ||
195 | " andn %0, %4\n" | ||
196 | " stcond %1, %0\n" | ||
197 | " brne 1b" | ||
198 | : "=&r"(tmp), "=o"(*p), "=&r"(old) | ||
199 | : "m"(*p), "r"(mask) | ||
200 | : "memory", "cc"); | ||
201 | } | ||
202 | |||
203 | return (old & mask) != 0; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * test_and_change_bit - Change a bit and return its old value | ||
208 | * @nr: Bit to change | ||
209 | * @addr: Address to count from | ||
210 | * | ||
211 | * This operation is atomic and cannot be reordered. | ||
212 | * It also implies a memory barrier. | ||
213 | */ | ||
214 | static inline int test_and_change_bit(int nr, volatile void * addr) | ||
215 | { | ||
216 | unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG; | ||
217 | unsigned long mask = 1UL << (nr % BITS_PER_LONG); | ||
218 | unsigned long tmp, old; | ||
219 | |||
220 | asm volatile( | ||
221 | "1: ssrf 5\n" | ||
222 | " ld.w %2, %3\n" | ||
223 | " eor %0, %2, %4\n" | ||
224 | " stcond %1, %0\n" | ||
225 | " brne 1b" | ||
226 | : "=&r"(tmp), "=o"(*p), "=&r"(old) | ||
227 | : "m"(*p), "r"(mask) | ||
228 | : "memory", "cc"); | ||
229 | |||
230 | return (old & mask) != 0; | ||
231 | } | ||
232 | |||
233 | #include <asm-generic/bitops/non-atomic.h> | ||
234 | |||
235 | /* Find First bit Set */ | ||
236 | static inline unsigned long __ffs(unsigned long word) | ||
237 | { | ||
238 | unsigned long result; | ||
239 | |||
240 | asm("brev %1\n\t" | ||
241 | "clz %0,%1" | ||
242 | : "=r"(result), "=&r"(word) | ||
243 | : "1"(word)); | ||
244 | return result; | ||
245 | } | ||
246 | |||
247 | /* Find First Zero */ | ||
248 | static inline unsigned long ffz(unsigned long word) | ||
249 | { | ||
250 | return __ffs(~word); | ||
251 | } | ||
252 | |||
253 | /* Find Last bit Set */ | ||
254 | static inline int fls(unsigned long word) | ||
255 | { | ||
256 | unsigned long result; | ||
257 | |||
258 | asm("clz %0,%1" : "=r"(result) : "r"(word)); | ||
259 | return 32 - result; | ||
260 | } | ||
261 | |||
262 | unsigned long find_first_zero_bit(const unsigned long *addr, | ||
263 | unsigned long size); | ||
264 | unsigned long find_next_zero_bit(const unsigned long *addr, | ||
265 | unsigned long size, | ||
266 | unsigned long offset); | ||
267 | unsigned long find_first_bit(const unsigned long *addr, | ||
268 | unsigned long size); | ||
269 | unsigned long find_next_bit(const unsigned long *addr, | ||
270 | unsigned long size, | ||
271 | unsigned long offset); | ||
272 | |||
273 | /* | ||
274 | * ffs: find first bit set. This is defined the same way as | ||
275 | * the libc and compiler builtin ffs routines, therefore | ||
276 | * differs in spirit from the above ffz (man ffs). | ||
277 | * | ||
278 | * The difference is that bit numbering starts at 1, and if no bit is set, | ||
279 | * the function returns 0. | ||
280 | */ | ||
281 | static inline int ffs(unsigned long word) | ||
282 | { | ||
283 | if(word == 0) | ||
284 | return 0; | ||
285 | return __ffs(word) + 1; | ||
286 | } | ||
287 | |||
288 | #include <asm-generic/bitops/fls64.h> | ||
289 | #include <asm-generic/bitops/sched.h> | ||
290 | #include <asm-generic/bitops/hweight.h> | ||
291 | |||
292 | #include <asm-generic/bitops/ext2-non-atomic.h> | ||
293 | #include <asm-generic/bitops/ext2-atomic.h> | ||
294 | #include <asm-generic/bitops/minix-le.h> | ||
295 | |||
296 | #endif /* __ASM_AVR32_BITOPS_H */ | ||
diff --git a/include/asm-avr32/bug.h b/include/asm-avr32/bug.h new file mode 100644 index 000000000000..521766bc9366 --- /dev/null +++ b/include/asm-avr32/bug.h | |||
@@ -0,0 +1,47 @@ | |||
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 | #ifndef __ASM_AVR32_BUG_H | ||
9 | #define __ASM_AVR32_BUG_H | ||
10 | |||
11 | #ifdef CONFIG_BUG | ||
12 | |||
13 | /* | ||
14 | * According to our Chief Architect, this compact opcode is very | ||
15 | * unlikely to ever be implemented. | ||
16 | */ | ||
17 | #define AVR32_BUG_OPCODE 0x5df0 | ||
18 | |||
19 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
20 | |||
21 | #define BUG() \ | ||
22 | do { \ | ||
23 | asm volatile(".hword %0\n\t" \ | ||
24 | ".hword %1\n\t" \ | ||
25 | ".long %2" \ | ||
26 | : \ | ||
27 | : "n"(AVR32_BUG_OPCODE), \ | ||
28 | "i"(__LINE__), "X"(__FILE__)); \ | ||
29 | } while (0) | ||
30 | |||
31 | #else | ||
32 | |||
33 | #define BUG() \ | ||
34 | do { \ | ||
35 | asm volatile(".hword %0\n\t" \ | ||
36 | : : "n"(AVR32_BUG_OPCODE)); \ | ||
37 | } while (0) | ||
38 | |||
39 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ | ||
40 | |||
41 | #define HAVE_ARCH_BUG | ||
42 | |||
43 | #endif /* CONFIG_BUG */ | ||
44 | |||
45 | #include <asm-generic/bug.h> | ||
46 | |||
47 | #endif /* __ASM_AVR32_BUG_H */ | ||
diff --git a/include/asm-avr32/bugs.h b/include/asm-avr32/bugs.h new file mode 100644 index 000000000000..7635e770622e --- /dev/null +++ b/include/asm-avr32/bugs.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * This is included by init/main.c to check for architecture-dependent bugs. | ||
3 | * | ||
4 | * Needs: | ||
5 | * void check_bugs(void); | ||
6 | */ | ||
7 | #ifndef __ASM_AVR32_BUGS_H | ||
8 | #define __ASM_AVR32_BUGS_H | ||
9 | |||
10 | static void __init check_bugs(void) | ||
11 | { | ||
12 | cpu_data->loops_per_jiffy = loops_per_jiffy; | ||
13 | } | ||
14 | |||
15 | #endif /* __ASM_AVR32_BUGS_H */ | ||
diff --git a/include/asm-avr32/byteorder.h b/include/asm-avr32/byteorder.h new file mode 100644 index 000000000000..402ff4125cdc --- /dev/null +++ b/include/asm-avr32/byteorder.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * AVR32 endian-conversion functions. | ||
3 | */ | ||
4 | #ifndef __ASM_AVR32_BYTEORDER_H | ||
5 | #define __ASM_AVR32_BYTEORDER_H | ||
6 | |||
7 | #include <asm/types.h> | ||
8 | #include <linux/compiler.h> | ||
9 | |||
10 | #ifdef __CHECKER__ | ||
11 | extern unsigned long __builtin_bswap_32(unsigned long x); | ||
12 | extern unsigned short __builtin_bswap_16(unsigned short x); | ||
13 | #endif | ||
14 | |||
15 | #define __arch__swab32(x) __builtin_bswap_32(x) | ||
16 | #define __arch__swab16(x) __builtin_bswap_16(x) | ||
17 | |||
18 | #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) | ||
19 | # define __BYTEORDER_HAS_U64__ | ||
20 | # define __SWAB_64_THRU_32__ | ||
21 | #endif | ||
22 | |||
23 | #include <linux/byteorder/big_endian.h> | ||
24 | |||
25 | #endif /* __ASM_AVR32_BYTEORDER_H */ | ||
diff --git a/include/asm-avr32/cache.h b/include/asm-avr32/cache.h new file mode 100644 index 000000000000..dabb955f3c00 --- /dev/null +++ b/include/asm-avr32/cache.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ASM_AVR32_CACHE_H | ||
2 | #define __ASM_AVR32_CACHE_H | ||
3 | |||
4 | #define L1_CACHE_SHIFT 5 | ||
5 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
6 | |||
7 | #ifndef __ASSEMBLER__ | ||
8 | struct cache_info { | ||
9 | unsigned int ways; | ||
10 | unsigned int sets; | ||
11 | unsigned int linesz; | ||
12 | }; | ||
13 | #endif /* __ASSEMBLER */ | ||
14 | |||
15 | /* Cache operation constants */ | ||
16 | #define ICACHE_FLUSH 0x00 | ||
17 | #define ICACHE_INVALIDATE 0x01 | ||
18 | #define ICACHE_LOCK 0x02 | ||
19 | #define ICACHE_UNLOCK 0x03 | ||
20 | #define ICACHE_PREFETCH 0x04 | ||
21 | |||
22 | #define DCACHE_FLUSH 0x08 | ||
23 | #define DCACHE_LOCK 0x09 | ||
24 | #define DCACHE_UNLOCK 0x0a | ||
25 | #define DCACHE_INVALIDATE 0x0b | ||
26 | #define DCACHE_CLEAN 0x0c | ||
27 | #define DCACHE_CLEAN_INVAL 0x0d | ||
28 | |||
29 | #endif /* __ASM_AVR32_CACHE_H */ | ||
diff --git a/include/asm-avr32/cachectl.h b/include/asm-avr32/cachectl.h new file mode 100644 index 000000000000..4faf1ce60061 --- /dev/null +++ b/include/asm-avr32/cachectl.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef __ASM_AVR32_CACHECTL_H | ||
2 | #define __ASM_AVR32_CACHECTL_H | ||
3 | |||
4 | /* | ||
5 | * Operations that can be performed through the cacheflush system call | ||
6 | */ | ||
7 | |||
8 | /* Clean the data cache, then invalidate the icache */ | ||
9 | #define CACHE_IFLUSH 0 | ||
10 | |||
11 | #endif /* __ASM_AVR32_CACHECTL_H */ | ||
diff --git a/include/asm-avr32/cacheflush.h b/include/asm-avr32/cacheflush.h new file mode 100644 index 000000000000..f1bf1708980e --- /dev/null +++ b/include/asm-avr32/cacheflush.h | |||
@@ -0,0 +1,129 @@ | |||
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 | #ifndef __ASM_AVR32_CACHEFLUSH_H | ||
9 | #define __ASM_AVR32_CACHEFLUSH_H | ||
10 | |||
11 | /* Keep includes the same across arches. */ | ||
12 | #include <linux/mm.h> | ||
13 | |||
14 | #define CACHE_OP_ICACHE_INVALIDATE 0x01 | ||
15 | #define CACHE_OP_DCACHE_INVALIDATE 0x0b | ||
16 | #define CACHE_OP_DCACHE_CLEAN 0x0c | ||
17 | #define CACHE_OP_DCACHE_CLEAN_INVAL 0x0d | ||
18 | |||
19 | /* | ||
20 | * Invalidate any cacheline containing virtual address vaddr without | ||
21 | * writing anything back to memory. | ||
22 | * | ||
23 | * Note that this function may corrupt unrelated data structures when | ||
24 | * applied on buffers that are not cacheline aligned in both ends. | ||
25 | */ | ||
26 | static inline void invalidate_dcache_line(void *vaddr) | ||
27 | { | ||
28 | asm volatile("cache %0[0], %1" | ||
29 | : | ||
30 | : "r"(vaddr), "n"(CACHE_OP_DCACHE_INVALIDATE) | ||
31 | : "memory"); | ||
32 | } | ||
33 | |||
34 | /* | ||
35 | * Make sure any cacheline containing virtual address vaddr is written | ||
36 | * to memory. | ||
37 | */ | ||
38 | static inline void clean_dcache_line(void *vaddr) | ||
39 | { | ||
40 | asm volatile("cache %0[0], %1" | ||
41 | : | ||
42 | : "r"(vaddr), "n"(CACHE_OP_DCACHE_CLEAN) | ||
43 | : "memory"); | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * Make sure any cacheline containing virtual address vaddr is written | ||
48 | * to memory and then invalidate it. | ||
49 | */ | ||
50 | static inline void flush_dcache_line(void *vaddr) | ||
51 | { | ||
52 | asm volatile("cache %0[0], %1" | ||
53 | : | ||
54 | : "r"(vaddr), "n"(CACHE_OP_DCACHE_CLEAN_INVAL) | ||
55 | : "memory"); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Invalidate any instruction cacheline containing virtual address | ||
60 | * vaddr. | ||
61 | */ | ||
62 | static inline void invalidate_icache_line(void *vaddr) | ||
63 | { | ||
64 | asm volatile("cache %0[0], %1" | ||
65 | : | ||
66 | : "r"(vaddr), "n"(CACHE_OP_ICACHE_INVALIDATE) | ||
67 | : "memory"); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Applies the above functions on all lines that are touched by the | ||
72 | * specified virtual address range. | ||
73 | */ | ||
74 | void invalidate_dcache_region(void *start, size_t len); | ||
75 | void clean_dcache_region(void *start, size_t len); | ||
76 | void flush_dcache_region(void *start, size_t len); | ||
77 | void invalidate_icache_region(void *start, size_t len); | ||
78 | |||
79 | /* | ||
80 | * Make sure any pending writes are completed before continuing. | ||
81 | */ | ||
82 | #define flush_write_buffer() asm volatile("sync 0" : : : "memory") | ||
83 | |||
84 | /* | ||
85 | * The following functions are called when a virtual mapping changes. | ||
86 | * We do not need to flush anything in this case. | ||
87 | */ | ||
88 | #define flush_cache_all() do { } while (0) | ||
89 | #define flush_cache_mm(mm) do { } while (0) | ||
90 | #define flush_cache_range(vma, start, end) do { } while (0) | ||
91 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | ||
92 | #define flush_cache_vmap(start, end) do { } while (0) | ||
93 | #define flush_cache_vunmap(start, end) do { } while (0) | ||
94 | |||
95 | /* | ||
96 | * I think we need to implement this one to be able to reliably | ||
97 | * execute pages from RAMDISK. However, if we implement the | ||
98 | * flush_dcache_*() functions, it might not be needed anymore. | ||
99 | * | ||
100 | * #define flush_icache_page(vma, page) do { } while (0) | ||
101 | */ | ||
102 | extern void flush_icache_page(struct vm_area_struct *vma, struct page *page); | ||
103 | |||
104 | /* | ||
105 | * These are (I think) related to D-cache aliasing. We might need to | ||
106 | * do something here, but only for certain configurations. No such | ||
107 | * configurations exist at this time. | ||
108 | */ | ||
109 | #define flush_dcache_page(page) do { } while (0) | ||
110 | #define flush_dcache_mmap_lock(page) do { } while (0) | ||
111 | #define flush_dcache_mmap_unlock(page) do { } while (0) | ||
112 | |||
113 | /* | ||
114 | * These are for I/D cache coherency. In this case, we do need to | ||
115 | * flush with all configurations. | ||
116 | */ | ||
117 | extern void flush_icache_range(unsigned long start, unsigned long end); | ||
118 | extern void flush_icache_user_range(struct vm_area_struct *vma, | ||
119 | struct page *page, | ||
120 | unsigned long addr, int len); | ||
121 | |||
122 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) do { \ | ||
123 | memcpy(dst, src, len); \ | ||
124 | flush_icache_user_range(vma, page, vaddr, len); \ | ||
125 | } while(0) | ||
126 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
127 | memcpy(dst, src, len) | ||
128 | |||
129 | #endif /* __ASM_AVR32_CACHEFLUSH_H */ | ||
diff --git a/include/asm-avr32/checksum.h b/include/asm-avr32/checksum.h new file mode 100644 index 000000000000..41b7af09edc4 --- /dev/null +++ b/include/asm-avr32/checksum.h | |||
@@ -0,0 +1,156 @@ | |||
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 | #ifndef __ASM_AVR32_CHECKSUM_H | ||
9 | #define __ASM_AVR32_CHECKSUM_H | ||
10 | |||
11 | /* | ||
12 | * computes the checksum of a memory block at buff, length len, | ||
13 | * and adds in "sum" (32-bit) | ||
14 | * | ||
15 | * returns a 32-bit number suitable for feeding into itself | ||
16 | * or csum_tcpudp_magic | ||
17 | * | ||
18 | * this function must be called with even lengths, except | ||
19 | * for the last fragment, which may be odd | ||
20 | * | ||
21 | * it's best to have buff aligned on a 32-bit boundary | ||
22 | */ | ||
23 | unsigned int csum_partial(const unsigned char * buff, int len, | ||
24 | unsigned int sum); | ||
25 | |||
26 | /* | ||
27 | * the same as csum_partial, but copies from src while it | ||
28 | * checksums, and handles user-space pointer exceptions correctly, when needed. | ||
29 | * | ||
30 | * here even more important to align src and dst on a 32-bit (or even | ||
31 | * better 64-bit) boundary | ||
32 | */ | ||
33 | unsigned int csum_partial_copy_generic(const char *src, char *dst, int len, | ||
34 | int sum, int *src_err_ptr, | ||
35 | int *dst_err_ptr); | ||
36 | |||
37 | /* | ||
38 | * Note: when you get a NULL pointer exception here this means someone | ||
39 | * passed in an incorrect kernel address to one of these functions. | ||
40 | * | ||
41 | * If you use these functions directly please don't forget the | ||
42 | * verify_area(). | ||
43 | */ | ||
44 | static inline | ||
45 | unsigned int csum_partial_copy_nocheck(const char *src, char *dst, | ||
46 | int len, int sum) | ||
47 | { | ||
48 | return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); | ||
49 | } | ||
50 | |||
51 | static inline | ||
52 | unsigned int csum_partial_copy_from_user (const char __user *src, char *dst, | ||
53 | int len, int sum, int *err_ptr) | ||
54 | { | ||
55 | return csum_partial_copy_generic((const char __force *)src, dst, len, | ||
56 | sum, err_ptr, NULL); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * This is a version of ip_compute_csum() optimized for IP headers, | ||
61 | * which always checksum on 4 octet boundaries. | ||
62 | */ | ||
63 | static inline unsigned short ip_fast_csum(unsigned char *iph, | ||
64 | unsigned int ihl) | ||
65 | { | ||
66 | unsigned int sum, tmp; | ||
67 | |||
68 | __asm__ __volatile__( | ||
69 | " ld.w %0, %1++\n" | ||
70 | " ld.w %3, %1++\n" | ||
71 | " sub %2, 4\n" | ||
72 | " add %0, %3\n" | ||
73 | " ld.w %3, %1++\n" | ||
74 | " adc %0, %0, %3\n" | ||
75 | " ld.w %3, %1++\n" | ||
76 | " adc %0, %0, %3\n" | ||
77 | " acr %0\n" | ||
78 | "1: ld.w %3, %1++\n" | ||
79 | " add %0, %3\n" | ||
80 | " acr %0\n" | ||
81 | " sub %2, 1\n" | ||
82 | " brne 1b\n" | ||
83 | " lsl %3, %0, 16\n" | ||
84 | " andl %0, 0\n" | ||
85 | " mov %2, 0xffff\n" | ||
86 | " add %0, %3\n" | ||
87 | " adc %0, %0, %2\n" | ||
88 | " com %0\n" | ||
89 | " lsr %0, 16\n" | ||
90 | : "=r"(sum), "=r"(iph), "=r"(ihl), "=r"(tmp) | ||
91 | : "1"(iph), "2"(ihl) | ||
92 | : "memory", "cc"); | ||
93 | return sum; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Fold a partial checksum | ||
98 | */ | ||
99 | |||
100 | static inline unsigned int csum_fold(unsigned int sum) | ||
101 | { | ||
102 | unsigned int tmp; | ||
103 | |||
104 | asm(" bfextu %1, %0, 0, 16\n" | ||
105 | " lsr %0, 16\n" | ||
106 | " add %0, %1\n" | ||
107 | " bfextu %1, %0, 16, 16\n" | ||
108 | " add %0, %1" | ||
109 | : "=&r"(sum), "=&r"(tmp) | ||
110 | : "0"(sum)); | ||
111 | |||
112 | return ~sum; | ||
113 | } | ||
114 | |||
115 | static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, | ||
116 | unsigned long daddr, | ||
117 | unsigned short len, | ||
118 | unsigned short proto, | ||
119 | unsigned int sum) | ||
120 | { | ||
121 | asm(" add %0, %1\n" | ||
122 | " adc %0, %0, %2\n" | ||
123 | " adc %0, %0, %3\n" | ||
124 | " acr %0" | ||
125 | : "=r"(sum) | ||
126 | : "r"(daddr), "r"(saddr), "r"(ntohs(len) | (proto << 16)), | ||
127 | "0"(sum) | ||
128 | : "cc"); | ||
129 | |||
130 | return sum; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * computes the checksum of the TCP/UDP pseudo-header | ||
135 | * returns a 16-bit checksum, already complemented | ||
136 | */ | ||
137 | static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, | ||
138 | unsigned long daddr, | ||
139 | unsigned short len, | ||
140 | unsigned short proto, | ||
141 | unsigned int sum) | ||
142 | { | ||
143 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * this routine is used for miscellaneous IP-like checksums, mainly | ||
148 | * in icmp.c | ||
149 | */ | ||
150 | |||
151 | static inline unsigned short ip_compute_csum(unsigned char * buff, int len) | ||
152 | { | ||
153 | return csum_fold(csum_partial(buff, len, 0)); | ||
154 | } | ||
155 | |||
156 | #endif /* __ASM_AVR32_CHECKSUM_H */ | ||
diff --git a/include/asm-avr32/cputime.h b/include/asm-avr32/cputime.h new file mode 100644 index 000000000000..e87e0f81cbeb --- /dev/null +++ b/include/asm-avr32/cputime.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_CPUTIME_H | ||
2 | #define __ASM_AVR32_CPUTIME_H | ||
3 | |||
4 | #include <asm-generic/cputime.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_CPUTIME_H */ | ||
diff --git a/include/asm-avr32/current.h b/include/asm-avr32/current.h new file mode 100644 index 000000000000..c7b0549eab8a --- /dev/null +++ b/include/asm-avr32/current.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef __ASM_AVR32_CURRENT_H | ||
2 | #define __ASM_AVR32_CURRENT_H | ||
3 | |||
4 | #include <linux/thread_info.h> | ||
5 | |||
6 | struct task_struct; | ||
7 | |||
8 | inline static struct task_struct * get_current(void) | ||
9 | { | ||
10 | return current_thread_info()->task; | ||
11 | } | ||
12 | |||
13 | #define current get_current() | ||
14 | |||
15 | #endif /* __ASM_AVR32_CURRENT_H */ | ||
diff --git a/include/asm-avr32/delay.h b/include/asm-avr32/delay.h new file mode 100644 index 000000000000..cc3b2e3343b3 --- /dev/null +++ b/include/asm-avr32/delay.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef __ASM_AVR32_DELAY_H | ||
2 | #define __ASM_AVR32_DELAY_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 1993 Linus Torvalds | ||
6 | * | ||
7 | * Delay routines calling functions in arch/avr32/lib/delay.c | ||
8 | */ | ||
9 | |||
10 | extern void __bad_udelay(void); | ||
11 | extern void __bad_ndelay(void); | ||
12 | |||
13 | extern void __udelay(unsigned long usecs); | ||
14 | extern void __ndelay(unsigned long nsecs); | ||
15 | extern void __const_udelay(unsigned long usecs); | ||
16 | extern void __delay(unsigned long loops); | ||
17 | |||
18 | #define udelay(n) (__builtin_constant_p(n) ? \ | ||
19 | ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \ | ||
20 | __udelay(n)) | ||
21 | |||
22 | #define ndelay(n) (__builtin_constant_p(n) ? \ | ||
23 | ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ | ||
24 | __ndelay(n)) | ||
25 | |||
26 | #endif /* __ASM_AVR32_DELAY_H */ | ||
diff --git a/include/asm-avr32/div64.h b/include/asm-avr32/div64.h new file mode 100644 index 000000000000..d7ddd4fdeca6 --- /dev/null +++ b/include/asm-avr32/div64.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_DIV64_H | ||
2 | #define __ASM_AVR32_DIV64_H | ||
3 | |||
4 | #include <asm-generic/div64.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_DIV64_H */ | ||
diff --git a/include/asm-avr32/dma-mapping.h b/include/asm-avr32/dma-mapping.h new file mode 100644 index 000000000000..4c40cb41cdf8 --- /dev/null +++ b/include/asm-avr32/dma-mapping.h | |||
@@ -0,0 +1,320 @@ | |||
1 | #ifndef __ASM_AVR32_DMA_MAPPING_H | ||
2 | #define __ASM_AVR32_DMA_MAPPING_H | ||
3 | |||
4 | #include <linux/mm.h> | ||
5 | #include <linux/device.h> | ||
6 | #include <asm/scatterlist.h> | ||
7 | #include <asm/processor.h> | ||
8 | #include <asm/cacheflush.h> | ||
9 | #include <asm/io.h> | ||
10 | |||
11 | extern void dma_cache_sync(void *vaddr, size_t size, int direction); | ||
12 | |||
13 | /* | ||
14 | * Return whether the given device DMA address mask can be supported | ||
15 | * properly. For example, if your device can only drive the low 24-bits | ||
16 | * during bus mastering, then you would pass 0x00ffffff as the mask | ||
17 | * to this function. | ||
18 | */ | ||
19 | static inline int dma_supported(struct device *dev, u64 mask) | ||
20 | { | ||
21 | /* Fix when needed. I really don't know of any limitations */ | ||
22 | return 1; | ||
23 | } | ||
24 | |||
25 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | ||
26 | { | ||
27 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
28 | return -EIO; | ||
29 | |||
30 | *dev->dma_mask = dma_mask; | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * dma_alloc_coherent - allocate consistent memory for DMA | ||
36 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
37 | * @size: required memory size | ||
38 | * @handle: bus-specific DMA address | ||
39 | * | ||
40 | * Allocate some uncached, unbuffered memory for a device for | ||
41 | * performing DMA. This function allocates pages, and will | ||
42 | * return the CPU-viewed address, and sets @handle to be the | ||
43 | * device-viewed address. | ||
44 | */ | ||
45 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | ||
46 | dma_addr_t *handle, gfp_t gfp); | ||
47 | |||
48 | /** | ||
49 | * dma_free_coherent - free memory allocated by dma_alloc_coherent | ||
50 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
51 | * @size: size of memory originally requested in dma_alloc_coherent | ||
52 | * @cpu_addr: CPU-view address returned from dma_alloc_coherent | ||
53 | * @handle: device-view address returned from dma_alloc_coherent | ||
54 | * | ||
55 | * Free (and unmap) a DMA buffer previously allocated by | ||
56 | * dma_alloc_coherent(). | ||
57 | * | ||
58 | * References to memory and mappings associated with cpu_addr/handle | ||
59 | * during and after this call executing are illegal. | ||
60 | */ | ||
61 | extern void dma_free_coherent(struct device *dev, size_t size, | ||
62 | void *cpu_addr, dma_addr_t handle); | ||
63 | |||
64 | /** | ||
65 | * dma_alloc_writecombine - allocate write-combining memory for DMA | ||
66 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
67 | * @size: required memory size | ||
68 | * @handle: bus-specific DMA address | ||
69 | * | ||
70 | * Allocate some uncached, buffered memory for a device for | ||
71 | * performing DMA. This function allocates pages, and will | ||
72 | * return the CPU-viewed address, and sets @handle to be the | ||
73 | * device-viewed address. | ||
74 | */ | ||
75 | extern void *dma_alloc_writecombine(struct device *dev, size_t size, | ||
76 | dma_addr_t *handle, gfp_t gfp); | ||
77 | |||
78 | /** | ||
79 | * dma_free_coherent - free memory allocated by dma_alloc_writecombine | ||
80 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
81 | * @size: size of memory originally requested in dma_alloc_writecombine | ||
82 | * @cpu_addr: CPU-view address returned from dma_alloc_writecombine | ||
83 | * @handle: device-view address returned from dma_alloc_writecombine | ||
84 | * | ||
85 | * Free (and unmap) a DMA buffer previously allocated by | ||
86 | * dma_alloc_writecombine(). | ||
87 | * | ||
88 | * References to memory and mappings associated with cpu_addr/handle | ||
89 | * during and after this call executing are illegal. | ||
90 | */ | ||
91 | extern void dma_free_writecombine(struct device *dev, size_t size, | ||
92 | void *cpu_addr, dma_addr_t handle); | ||
93 | |||
94 | /** | ||
95 | * dma_map_single - map a single buffer for streaming DMA | ||
96 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
97 | * @cpu_addr: CPU direct mapped address of buffer | ||
98 | * @size: size of buffer to map | ||
99 | * @dir: DMA transfer direction | ||
100 | * | ||
101 | * Ensure that any data held in the cache is appropriately discarded | ||
102 | * or written back. | ||
103 | * | ||
104 | * The device owns this memory once this call has completed. The CPU | ||
105 | * can regain ownership by calling dma_unmap_single() or dma_sync_single(). | ||
106 | */ | ||
107 | static inline dma_addr_t | ||
108 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
109 | enum dma_data_direction direction) | ||
110 | { | ||
111 | dma_cache_sync(cpu_addr, size, direction); | ||
112 | return virt_to_bus(cpu_addr); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * dma_unmap_single - unmap a single buffer previously mapped | ||
117 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
118 | * @handle: DMA address of buffer | ||
119 | * @size: size of buffer to map | ||
120 | * @dir: DMA transfer direction | ||
121 | * | ||
122 | * Unmap a single streaming mode DMA translation. The handle and size | ||
123 | * must match what was provided in the previous dma_map_single() call. | ||
124 | * All other usages are undefined. | ||
125 | * | ||
126 | * After this call, reads by the CPU to the buffer are guaranteed to see | ||
127 | * whatever the device wrote there. | ||
128 | */ | ||
129 | static inline void | ||
130 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
131 | enum dma_data_direction direction) | ||
132 | { | ||
133 | |||
134 | } | ||
135 | |||
136 | /** | ||
137 | * dma_map_page - map a portion of a page for streaming DMA | ||
138 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
139 | * @page: page that buffer resides in | ||
140 | * @offset: offset into page for start of buffer | ||
141 | * @size: size of buffer to map | ||
142 | * @dir: DMA transfer direction | ||
143 | * | ||
144 | * Ensure that any data held in the cache is appropriately discarded | ||
145 | * or written back. | ||
146 | * | ||
147 | * The device owns this memory once this call has completed. The CPU | ||
148 | * can regain ownership by calling dma_unmap_page() or dma_sync_single(). | ||
149 | */ | ||
150 | static inline dma_addr_t | ||
151 | dma_map_page(struct device *dev, struct page *page, | ||
152 | unsigned long offset, size_t size, | ||
153 | enum dma_data_direction direction) | ||
154 | { | ||
155 | return dma_map_single(dev, page_address(page) + offset, | ||
156 | size, direction); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() | ||
161 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
162 | * @handle: DMA address of buffer | ||
163 | * @size: size of buffer to map | ||
164 | * @dir: DMA transfer direction | ||
165 | * | ||
166 | * Unmap a single streaming mode DMA translation. The handle and size | ||
167 | * must match what was provided in the previous dma_map_single() call. | ||
168 | * All other usages are undefined. | ||
169 | * | ||
170 | * After this call, reads by the CPU to the buffer are guaranteed to see | ||
171 | * whatever the device wrote there. | ||
172 | */ | ||
173 | static inline void | ||
174 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
175 | enum dma_data_direction direction) | ||
176 | { | ||
177 | dma_unmap_single(dev, dma_address, size, direction); | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * dma_map_sg - map a set of SG buffers for streaming mode DMA | ||
182 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
183 | * @sg: list of buffers | ||
184 | * @nents: number of buffers to map | ||
185 | * @dir: DMA transfer direction | ||
186 | * | ||
187 | * Map a set of buffers described by scatterlist in streaming | ||
188 | * mode for DMA. This is the scatter-gather version of the | ||
189 | * above pci_map_single interface. Here the scatter gather list | ||
190 | * elements are each tagged with the appropriate dma address | ||
191 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
192 | * | ||
193 | * NOTE: An implementation may be able to use a smaller number of | ||
194 | * DMA address/length pairs than there are SG table elements. | ||
195 | * (for example via virtual mapping capabilities) | ||
196 | * The routine returns the number of addr/length pairs actually | ||
197 | * used, at most nents. | ||
198 | * | ||
199 | * Device ownership issues as mentioned above for pci_map_single are | ||
200 | * the same here. | ||
201 | */ | ||
202 | static inline int | ||
203 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
204 | enum dma_data_direction direction) | ||
205 | { | ||
206 | int i; | ||
207 | |||
208 | for (i = 0; i < nents; i++) { | ||
209 | char *virt; | ||
210 | |||
211 | sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset; | ||
212 | virt = page_address(sg[i].page) + sg[i].offset; | ||
213 | dma_cache_sync(virt, sg[i].length, direction); | ||
214 | } | ||
215 | |||
216 | return nents; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg | ||
221 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
222 | * @sg: list of buffers | ||
223 | * @nents: number of buffers to map | ||
224 | * @dir: DMA transfer direction | ||
225 | * | ||
226 | * Unmap a set of streaming mode DMA translations. | ||
227 | * Again, CPU read rules concerning calls here are the same as for | ||
228 | * pci_unmap_single() above. | ||
229 | */ | ||
230 | static inline void | ||
231 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
232 | enum dma_data_direction direction) | ||
233 | { | ||
234 | |||
235 | } | ||
236 | |||
237 | /** | ||
238 | * dma_sync_single_for_cpu | ||
239 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
240 | * @handle: DMA address of buffer | ||
241 | * @size: size of buffer to map | ||
242 | * @dir: DMA transfer direction | ||
243 | * | ||
244 | * Make physical memory consistent for a single streaming mode DMA | ||
245 | * translation after a transfer. | ||
246 | * | ||
247 | * If you perform a dma_map_single() but wish to interrogate the | ||
248 | * buffer using the cpu, yet do not wish to teardown the DMA mapping, | ||
249 | * you must call this function before doing so. At the next point you | ||
250 | * give the DMA address back to the card, you must first perform a | ||
251 | * dma_sync_single_for_device, and then the device again owns the | ||
252 | * buffer. | ||
253 | */ | ||
254 | static inline void | ||
255 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
256 | size_t size, enum dma_data_direction direction) | ||
257 | { | ||
258 | dma_cache_sync(bus_to_virt(dma_handle), size, direction); | ||
259 | } | ||
260 | |||
261 | static inline void | ||
262 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
263 | size_t size, enum dma_data_direction direction) | ||
264 | { | ||
265 | dma_cache_sync(bus_to_virt(dma_handle), size, direction); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * dma_sync_sg_for_cpu | ||
270 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
271 | * @sg: list of buffers | ||
272 | * @nents: number of buffers to map | ||
273 | * @dir: DMA transfer direction | ||
274 | * | ||
275 | * Make physical memory consistent for a set of streaming | ||
276 | * mode DMA translations after a transfer. | ||
277 | * | ||
278 | * The same as dma_sync_single_for_* but for a scatter-gather list, | ||
279 | * same rules and usage. | ||
280 | */ | ||
281 | static inline void | ||
282 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
283 | int nents, enum dma_data_direction direction) | ||
284 | { | ||
285 | int i; | ||
286 | |||
287 | for (i = 0; i < nents; i++) { | ||
288 | dma_cache_sync(page_address(sg[i].page) + sg[i].offset, | ||
289 | sg[i].length, direction); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | static inline void | ||
294 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | ||
295 | int nents, enum dma_data_direction direction) | ||
296 | { | ||
297 | int i; | ||
298 | |||
299 | for (i = 0; i < nents; i++) { | ||
300 | dma_cache_sync(page_address(sg[i].page) + sg[i].offset, | ||
301 | sg[i].length, direction); | ||
302 | } | ||
303 | } | ||
304 | |||
305 | /* Now for the API extensions over the pci_ one */ | ||
306 | |||
307 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | ||
308 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | ||
309 | |||
310 | static inline int dma_is_consistent(dma_addr_t dma_addr) | ||
311 | { | ||
312 | return 1; | ||
313 | } | ||
314 | |||
315 | static inline int dma_get_cache_alignment(void) | ||
316 | { | ||
317 | return boot_cpu_data.dcache.linesz; | ||
318 | } | ||
319 | |||
320 | #endif /* __ASM_AVR32_DMA_MAPPING_H */ | ||
diff --git a/include/asm-avr32/dma.h b/include/asm-avr32/dma.h new file mode 100644 index 000000000000..9e91205590ac --- /dev/null +++ b/include/asm-avr32/dma.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __ASM_AVR32_DMA_H | ||
2 | #define __ASM_AVR32_DMA_H | ||
3 | |||
4 | /* The maximum address that we can perform a DMA transfer to on this platform. | ||
5 | * Not really applicable to AVR32, but some functions need it. */ | ||
6 | #define MAX_DMA_ADDRESS 0xffffffff | ||
7 | |||
8 | #endif /* __ASM_AVR32_DMA_H */ | ||
diff --git a/include/asm-avr32/elf.h b/include/asm-avr32/elf.h new file mode 100644 index 000000000000..d334b4994d2d --- /dev/null +++ b/include/asm-avr32/elf.h | |||
@@ -0,0 +1,110 @@ | |||
1 | #ifndef __ASM_AVR32_ELF_H | ||
2 | #define __ASM_AVR32_ELF_H | ||
3 | |||
4 | /* AVR32 relocation numbers */ | ||
5 | #define R_AVR32_NONE 0 | ||
6 | #define R_AVR32_32 1 | ||
7 | #define R_AVR32_16 2 | ||
8 | #define R_AVR32_8 3 | ||
9 | #define R_AVR32_32_PCREL 4 | ||
10 | #define R_AVR32_16_PCREL 5 | ||
11 | #define R_AVR32_8_PCREL 6 | ||
12 | #define R_AVR32_DIFF32 7 | ||
13 | #define R_AVR32_DIFF16 8 | ||
14 | #define R_AVR32_DIFF8 9 | ||
15 | #define R_AVR32_GOT32 10 | ||
16 | #define R_AVR32_GOT16 11 | ||
17 | #define R_AVR32_GOT8 12 | ||
18 | #define R_AVR32_21S 13 | ||
19 | #define R_AVR32_16U 14 | ||
20 | #define R_AVR32_16S 15 | ||
21 | #define R_AVR32_8S 16 | ||
22 | #define R_AVR32_8S_EXT 17 | ||
23 | #define R_AVR32_22H_PCREL 18 | ||
24 | #define R_AVR32_18W_PCREL 19 | ||
25 | #define R_AVR32_16B_PCREL 20 | ||
26 | #define R_AVR32_16N_PCREL 21 | ||
27 | #define R_AVR32_14UW_PCREL 22 | ||
28 | #define R_AVR32_11H_PCREL 23 | ||
29 | #define R_AVR32_10UW_PCREL 24 | ||
30 | #define R_AVR32_9H_PCREL 25 | ||
31 | #define R_AVR32_9UW_PCREL 26 | ||
32 | #define R_AVR32_HI16 27 | ||
33 | #define R_AVR32_LO16 28 | ||
34 | #define R_AVR32_GOTPC 29 | ||
35 | #define R_AVR32_GOTCALL 30 | ||
36 | #define R_AVR32_LDA_GOT 31 | ||
37 | #define R_AVR32_GOT21S 32 | ||
38 | #define R_AVR32_GOT18SW 33 | ||
39 | #define R_AVR32_GOT16S 34 | ||
40 | #define R_AVR32_GOT7UW 35 | ||
41 | #define R_AVR32_32_CPENT 36 | ||
42 | #define R_AVR32_CPCALL 37 | ||
43 | #define R_AVR32_16_CP 38 | ||
44 | #define R_AVR32_9W_CP 39 | ||
45 | #define R_AVR32_RELATIVE 40 | ||
46 | #define R_AVR32_GLOB_DAT 41 | ||
47 | #define R_AVR32_JMP_SLOT 42 | ||
48 | #define R_AVR32_ALIGN 43 | ||
49 | |||
50 | /* | ||
51 | * ELF register definitions.. | ||
52 | */ | ||
53 | |||
54 | #include <asm/ptrace.h> | ||
55 | #include <asm/user.h> | ||
56 | |||
57 | typedef unsigned long elf_greg_t; | ||
58 | |||
59 | #define ELF_NGREG (sizeof (struct pt_regs) / sizeof (elf_greg_t)) | ||
60 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | ||
61 | |||
62 | typedef struct user_fpu_struct elf_fpregset_t; | ||
63 | |||
64 | /* | ||
65 | * This is used to ensure we don't load something for the wrong architecture. | ||
66 | */ | ||
67 | #define elf_check_arch(x) ( (x)->e_machine == EM_AVR32 ) | ||
68 | |||
69 | /* | ||
70 | * These are used to set parameters in the core dumps. | ||
71 | */ | ||
72 | #define ELF_CLASS ELFCLASS32 | ||
73 | #ifdef __LITTLE_ENDIAN__ | ||
74 | #define ELF_DATA ELFDATA2LSB | ||
75 | #else | ||
76 | #define ELF_DATA ELFDATA2MSB | ||
77 | #endif | ||
78 | #define ELF_ARCH EM_AVR32 | ||
79 | |||
80 | #define USE_ELF_CORE_DUMP | ||
81 | #define ELF_EXEC_PAGESIZE 4096 | ||
82 | |||
83 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | ||
84 | use of this is to invoke "./ld.so someprog" to test out a new version of | ||
85 | the loader. We need to make sure that it is out of the way of the program | ||
86 | that it will "exec", and that there is sufficient room for the brk. */ | ||
87 | |||
88 | #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) | ||
89 | |||
90 | |||
91 | /* This yields a mask that user programs can use to figure out what | ||
92 | instruction set this CPU supports. This could be done in user space, | ||
93 | but it's not easy, and we've already done it here. */ | ||
94 | |||
95 | #define ELF_HWCAP (0) | ||
96 | |||
97 | /* This yields a string that ld.so will use to load implementation | ||
98 | specific libraries for optimization. This is more specific in | ||
99 | intent than poking at uname or /proc/cpuinfo. | ||
100 | |||
101 | For the moment, we have only optimizations for the Intel generations, | ||
102 | but that could change... */ | ||
103 | |||
104 | #define ELF_PLATFORM (NULL) | ||
105 | |||
106 | #ifdef __KERNEL__ | ||
107 | #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) | ||
108 | #endif | ||
109 | |||
110 | #endif /* __ASM_AVR32_ELF_H */ | ||
diff --git a/include/asm-avr32/emergency-restart.h b/include/asm-avr32/emergency-restart.h new file mode 100644 index 000000000000..3e7e014776ba --- /dev/null +++ b/include/asm-avr32/emergency-restart.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_EMERGENCY_RESTART_H | ||
2 | #define __ASM_AVR32_EMERGENCY_RESTART_H | ||
3 | |||
4 | #include <asm-generic/emergency-restart.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_EMERGENCY_RESTART_H */ | ||
diff --git a/include/asm-avr32/errno.h b/include/asm-avr32/errno.h new file mode 100644 index 000000000000..558a7249f06d --- /dev/null +++ b/include/asm-avr32/errno.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_ERRNO_H | ||
2 | #define __ASM_AVR32_ERRNO_H | ||
3 | |||
4 | #include <asm-generic/errno.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_ERRNO_H */ | ||
diff --git a/include/asm-avr32/fcntl.h b/include/asm-avr32/fcntl.h new file mode 100644 index 000000000000..14c0c4402b11 --- /dev/null +++ b/include/asm-avr32/fcntl.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_FCNTL_H | ||
2 | #define __ASM_AVR32_FCNTL_H | ||
3 | |||
4 | #include <asm-generic/fcntl.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_FCNTL_H */ | ||
diff --git a/include/asm-avr32/futex.h b/include/asm-avr32/futex.h new file mode 100644 index 000000000000..10419f14a68a --- /dev/null +++ b/include/asm-avr32/futex.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_FUTEX_H | ||
2 | #define __ASM_AVR32_FUTEX_H | ||
3 | |||
4 | #include <asm-generic/futex.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_FUTEX_H */ | ||
diff --git a/include/asm-avr32/hardirq.h b/include/asm-avr32/hardirq.h new file mode 100644 index 000000000000..267354356f60 --- /dev/null +++ b/include/asm-avr32/hardirq.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef __ASM_AVR32_HARDIRQ_H | ||
2 | #define __ASM_AVR32_HARDIRQ_H | ||
3 | |||
4 | #include <linux/threads.h> | ||
5 | #include <asm/irq.h> | ||
6 | |||
7 | #ifndef __ASSEMBLY__ | ||
8 | |||
9 | #include <linux/cache.h> | ||
10 | |||
11 | /* entry.S is sensitive to the offsets of these fields */ | ||
12 | typedef struct { | ||
13 | unsigned int __softirq_pending; | ||
14 | } ____cacheline_aligned irq_cpustat_t; | ||
15 | |||
16 | void ack_bad_irq(unsigned int irq); | ||
17 | |||
18 | /* Standard mappings for irq_cpustat_t above */ | ||
19 | #include <linux/irq_cpustat.h> | ||
20 | |||
21 | #endif /* __ASSEMBLY__ */ | ||
22 | |||
23 | #define HARDIRQ_BITS 12 | ||
24 | |||
25 | /* | ||
26 | * The hardirq mask has to be large enough to have | ||
27 | * space for potentially all IRQ sources in the system | ||
28 | * nesting on a single CPU: | ||
29 | */ | ||
30 | #if (1 << HARDIRQ_BITS) < NR_IRQS | ||
31 | # error HARDIRQ_BITS is too low! | ||
32 | #endif | ||
33 | |||
34 | #endif /* __ASM_AVR32_HARDIRQ_H */ | ||
diff --git a/include/asm-avr32/hw_irq.h b/include/asm-avr32/hw_irq.h new file mode 100644 index 000000000000..218b0a6bfd1b --- /dev/null +++ b/include/asm-avr32/hw_irq.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef __ASM_AVR32_HW_IRQ_H | ||
2 | #define __ASM_AVR32_HW_IRQ_H | ||
3 | |||
4 | static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) | ||
5 | { | ||
6 | /* Nothing to do */ | ||
7 | } | ||
8 | |||
9 | #endif /* __ASM_AVR32_HW_IRQ_H */ | ||
diff --git a/include/asm-avr32/intc.h b/include/asm-avr32/intc.h new file mode 100644 index 000000000000..1ac9ca75e8fd --- /dev/null +++ b/include/asm-avr32/intc.h | |||
@@ -0,0 +1,128 @@ | |||
1 | #ifndef __ASM_AVR32_INTC_H | ||
2 | #define __ASM_AVR32_INTC_H | ||
3 | |||
4 | #include <linux/sysdev.h> | ||
5 | #include <linux/interrupt.h> | ||
6 | |||
7 | struct irq_controller; | ||
8 | struct irqaction; | ||
9 | struct pt_regs; | ||
10 | |||
11 | struct platform_device; | ||
12 | |||
13 | /* Information about the internal interrupt controller */ | ||
14 | struct intc_device { | ||
15 | /* ioremapped address of configuration block */ | ||
16 | void __iomem *regs; | ||
17 | |||
18 | /* the physical device */ | ||
19 | struct platform_device *pdev; | ||
20 | |||
21 | /* Number of interrupt lines per group. */ | ||
22 | unsigned int irqs_per_group; | ||
23 | |||
24 | /* The highest group ID + 1 */ | ||
25 | unsigned int nr_groups; | ||
26 | |||
27 | /* | ||
28 | * Bitfield indicating which groups are actually in use. The | ||
29 | * size of the array is | ||
30 | * ceil(group_max / (8 * sizeof(unsigned int))). | ||
31 | */ | ||
32 | unsigned int group_mask[]; | ||
33 | }; | ||
34 | |||
35 | struct irq_controller_class { | ||
36 | /* | ||
37 | * A short name identifying this kind of controller. | ||
38 | */ | ||
39 | const char *typename; | ||
40 | /* | ||
41 | * Handle the IRQ. Must do any necessary acking and masking. | ||
42 | */ | ||
43 | irqreturn_t (*handle)(int irq, void *dev_id, struct pt_regs *regs); | ||
44 | /* | ||
45 | * Register a new IRQ handler. | ||
46 | */ | ||
47 | int (*setup)(struct irq_controller *ctrl, unsigned int irq, | ||
48 | struct irqaction *action); | ||
49 | /* | ||
50 | * Unregister a IRQ handler. | ||
51 | */ | ||
52 | void (*free)(struct irq_controller *ctrl, unsigned int irq, | ||
53 | void *dev_id); | ||
54 | /* | ||
55 | * Mask the IRQ in the interrupt controller. | ||
56 | */ | ||
57 | void (*mask)(struct irq_controller *ctrl, unsigned int irq); | ||
58 | /* | ||
59 | * Unmask the IRQ in the interrupt controller. | ||
60 | */ | ||
61 | void (*unmask)(struct irq_controller *ctrl, unsigned int irq); | ||
62 | /* | ||
63 | * Set the type of the IRQ. See below for possible types. | ||
64 | * Return -EINVAL if a given type is not supported | ||
65 | */ | ||
66 | int (*set_type)(struct irq_controller *ctrl, unsigned int irq, | ||
67 | unsigned int type); | ||
68 | /* | ||
69 | * Return the IRQ type currently set | ||
70 | */ | ||
71 | unsigned int (*get_type)(struct irq_controller *ctrl, unsigned int irq); | ||
72 | }; | ||
73 | |||
74 | struct irq_controller { | ||
75 | struct irq_controller_class *class; | ||
76 | unsigned int irq_group; | ||
77 | unsigned int first_irq; | ||
78 | unsigned int nr_irqs; | ||
79 | struct list_head list; | ||
80 | }; | ||
81 | |||
82 | struct intc_group_desc { | ||
83 | struct irq_controller *ctrl; | ||
84 | irqreturn_t (*handle)(int, void *, struct pt_regs *); | ||
85 | unsigned long flags; | ||
86 | void *dev_id; | ||
87 | const char *devname; | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * The internal interrupt controller. Defined in board/part-specific | ||
92 | * devices.c. | ||
93 | * TODO: Should probably be defined per-cpu. | ||
94 | */ | ||
95 | extern struct intc_device intc; | ||
96 | |||
97 | extern int request_internal_irq(unsigned int irq, | ||
98 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
99 | unsigned long irqflags, | ||
100 | const char *devname, void *dev_id); | ||
101 | extern void free_internal_irq(unsigned int irq); | ||
102 | |||
103 | /* Only used by time_init() */ | ||
104 | extern int setup_internal_irq(unsigned int irq, struct intc_group_desc *desc); | ||
105 | |||
106 | /* | ||
107 | * Set interrupt priority for a given group. `group' can be found by | ||
108 | * using irq_to_group(irq). Priority can be from 0 (lowest) to 3 | ||
109 | * (highest). Higher-priority interrupts will preempt lower-priority | ||
110 | * interrupts (unless interrupts are masked globally). | ||
111 | * | ||
112 | * This function does not check for conflicts within a group. | ||
113 | */ | ||
114 | extern int intc_set_priority(unsigned int group, | ||
115 | unsigned int priority); | ||
116 | |||
117 | /* | ||
118 | * Returns a bitmask of pending interrupts in a group. | ||
119 | */ | ||
120 | extern unsigned long intc_get_pending(unsigned int group); | ||
121 | |||
122 | /* | ||
123 | * Register a new external interrupt controller. Returns the first | ||
124 | * external IRQ number that is assigned to the new controller. | ||
125 | */ | ||
126 | extern int intc_register_controller(struct irq_controller *ctrl); | ||
127 | |||
128 | #endif /* __ASM_AVR32_INTC_H */ | ||
diff --git a/include/asm-avr32/io.h b/include/asm-avr32/io.h new file mode 100644 index 000000000000..2fc8f111dce9 --- /dev/null +++ b/include/asm-avr32/io.h | |||
@@ -0,0 +1,253 @@ | |||
1 | #ifndef __ASM_AVR32_IO_H | ||
2 | #define __ASM_AVR32_IO_H | ||
3 | |||
4 | #include <linux/string.h> | ||
5 | |||
6 | #ifdef __KERNEL__ | ||
7 | |||
8 | #include <asm/addrspace.h> | ||
9 | #include <asm/byteorder.h> | ||
10 | |||
11 | /* virt_to_phys will only work when address is in P1 or P2 */ | ||
12 | static __inline__ unsigned long virt_to_phys(volatile void *address) | ||
13 | { | ||
14 | return PHYSADDR(address); | ||
15 | } | ||
16 | |||
17 | static __inline__ void * phys_to_virt(unsigned long address) | ||
18 | { | ||
19 | return (void *)P1SEGADDR(address); | ||
20 | } | ||
21 | |||
22 | #define cached_to_phys(addr) ((unsigned long)PHYSADDR(addr)) | ||
23 | #define uncached_to_phys(addr) ((unsigned long)PHYSADDR(addr)) | ||
24 | #define phys_to_cached(addr) ((void *)P1SEGADDR(addr)) | ||
25 | #define phys_to_uncached(addr) ((void *)P2SEGADDR(addr)) | ||
26 | |||
27 | /* | ||
28 | * Generic IO read/write. These perform native-endian accesses. Note | ||
29 | * that some architectures will want to re-define __raw_{read,write}w. | ||
30 | */ | ||
31 | extern void __raw_writesb(unsigned int addr, const void *data, int bytelen); | ||
32 | extern void __raw_writesw(unsigned int addr, const void *data, int wordlen); | ||
33 | extern void __raw_writesl(unsigned int addr, const void *data, int longlen); | ||
34 | |||
35 | extern void __raw_readsb(unsigned int addr, void *data, int bytelen); | ||
36 | extern void __raw_readsw(unsigned int addr, void *data, int wordlen); | ||
37 | extern void __raw_readsl(unsigned int addr, void *data, int longlen); | ||
38 | |||
39 | static inline void writeb(unsigned char b, volatile void __iomem *addr) | ||
40 | { | ||
41 | *(volatile unsigned char __force *)addr = b; | ||
42 | } | ||
43 | static inline void writew(unsigned short b, volatile void __iomem *addr) | ||
44 | { | ||
45 | *(volatile unsigned short __force *)addr = b; | ||
46 | } | ||
47 | static inline void writel(unsigned int b, volatile void __iomem *addr) | ||
48 | { | ||
49 | *(volatile unsigned int __force *)addr = b; | ||
50 | } | ||
51 | #define __raw_writeb writeb | ||
52 | #define __raw_writew writew | ||
53 | #define __raw_writel writel | ||
54 | |||
55 | static inline unsigned char readb(const volatile void __iomem *addr) | ||
56 | { | ||
57 | return *(const volatile unsigned char __force *)addr; | ||
58 | } | ||
59 | static inline unsigned short readw(const volatile void __iomem *addr) | ||
60 | { | ||
61 | return *(const volatile unsigned short __force *)addr; | ||
62 | } | ||
63 | static inline unsigned int readl(const volatile void __iomem *addr) | ||
64 | { | ||
65 | return *(const volatile unsigned int __force *)addr; | ||
66 | } | ||
67 | #define __raw_readb readb | ||
68 | #define __raw_readw readw | ||
69 | #define __raw_readl readl | ||
70 | |||
71 | #define writesb(p, d, l) __raw_writesb((unsigned int)p, d, l) | ||
72 | #define writesw(p, d, l) __raw_writesw((unsigned int)p, d, l) | ||
73 | #define writesl(p, d, l) __raw_writesl((unsigned int)p, d, l) | ||
74 | |||
75 | #define readsb(p, d, l) __raw_readsb((unsigned int)p, d, l) | ||
76 | #define readsw(p, d, l) __raw_readsw((unsigned int)p, d, l) | ||
77 | #define readsl(p, d, l) __raw_readsl((unsigned int)p, d, l) | ||
78 | |||
79 | /* | ||
80 | * These two are only here because ALSA _thinks_ it needs them... | ||
81 | */ | ||
82 | static inline void memcpy_fromio(void * to, const volatile void __iomem *from, | ||
83 | unsigned long count) | ||
84 | { | ||
85 | char *p = to; | ||
86 | while (count) { | ||
87 | count--; | ||
88 | *p = readb(from); | ||
89 | p++; | ||
90 | from++; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static inline void memcpy_toio(volatile void __iomem *to, const void * from, | ||
95 | unsigned long count) | ||
96 | { | ||
97 | const char *p = from; | ||
98 | while (count) { | ||
99 | count--; | ||
100 | writeb(*p, to); | ||
101 | p++; | ||
102 | to++; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static inline void memset_io(volatile void __iomem *addr, unsigned char val, | ||
107 | unsigned long count) | ||
108 | { | ||
109 | memset((void __force *)addr, val, count); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Bad read/write accesses... | ||
114 | */ | ||
115 | extern void __readwrite_bug(const char *fn); | ||
116 | |||
117 | #define IO_SPACE_LIMIT 0xffffffff | ||
118 | |||
119 | /* Convert I/O port address to virtual address */ | ||
120 | #define __io(p) ((void __iomem *)phys_to_uncached(p)) | ||
121 | |||
122 | /* | ||
123 | * IO port access primitives | ||
124 | * ------------------------- | ||
125 | * | ||
126 | * The AVR32 doesn't have special IO access instructions; all IO is memory | ||
127 | * mapped. Note that these are defined to perform little endian accesses | ||
128 | * only. Their primary purpose is to access PCI and ISA peripherals. | ||
129 | * | ||
130 | * Note that for a big endian machine, this implies that the following | ||
131 | * big endian mode connectivity is in place. | ||
132 | * | ||
133 | * The machine specific io.h include defines __io to translate an "IO" | ||
134 | * address to a memory address. | ||
135 | * | ||
136 | * Note that we prevent GCC re-ordering or caching values in expressions | ||
137 | * by introducing sequence points into the in*() definitions. Note that | ||
138 | * __raw_* do not guarantee this behaviour. | ||
139 | * | ||
140 | * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space. | ||
141 | */ | ||
142 | #define outb(v, p) __raw_writeb(v, __io(p)) | ||
143 | #define outw(v, p) __raw_writew(cpu_to_le16(v), __io(p)) | ||
144 | #define outl(v, p) __raw_writel(cpu_to_le32(v), __io(p)) | ||
145 | |||
146 | #define inb(p) __raw_readb(__io(p)) | ||
147 | #define inw(p) le16_to_cpu(__raw_readw(__io(p))) | ||
148 | #define inl(p) le32_to_cpu(__raw_readl(__io(p))) | ||
149 | |||
150 | static inline void __outsb(unsigned long port, void *addr, unsigned int count) | ||
151 | { | ||
152 | while (count--) { | ||
153 | outb(*(u8 *)addr, port); | ||
154 | addr++; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static inline void __insb(unsigned long port, void *addr, unsigned int count) | ||
159 | { | ||
160 | while (count--) { | ||
161 | *(u8 *)addr = inb(port); | ||
162 | addr++; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static inline void __outsw(unsigned long port, void *addr, unsigned int count) | ||
167 | { | ||
168 | while (count--) { | ||
169 | outw(*(u16 *)addr, port); | ||
170 | addr += 2; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static inline void __insw(unsigned long port, void *addr, unsigned int count) | ||
175 | { | ||
176 | while (count--) { | ||
177 | *(u16 *)addr = inw(port); | ||
178 | addr += 2; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | static inline void __outsl(unsigned long port, void *addr, unsigned int count) | ||
183 | { | ||
184 | while (count--) { | ||
185 | outl(*(u32 *)addr, port); | ||
186 | addr += 4; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | static inline void __insl(unsigned long port, void *addr, unsigned int count) | ||
191 | { | ||
192 | while (count--) { | ||
193 | *(u32 *)addr = inl(port); | ||
194 | addr += 4; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | #define outsb(port, addr, count) __outsb(port, addr, count) | ||
199 | #define insb(port, addr, count) __insb(port, addr, count) | ||
200 | #define outsw(port, addr, count) __outsw(port, addr, count) | ||
201 | #define insw(port, addr, count) __insw(port, addr, count) | ||
202 | #define outsl(port, addr, count) __outsl(port, addr, count) | ||
203 | #define insl(port, addr, count) __insl(port, addr, count) | ||
204 | |||
205 | extern void __iomem *__ioremap(unsigned long offset, size_t size, | ||
206 | unsigned long flags); | ||
207 | extern void __iounmap(void __iomem *addr); | ||
208 | |||
209 | /* | ||
210 | * ioremap - map bus memory into CPU space | ||
211 | * @offset bus address of the memory | ||
212 | * @size size of the resource to map | ||
213 | * | ||
214 | * ioremap performs a platform specific sequence of operations to make | ||
215 | * bus memory CPU accessible via the readb/.../writel functions and | ||
216 | * the other mmio helpers. The returned address is not guaranteed to | ||
217 | * be usable directly as a virtual address. | ||
218 | */ | ||
219 | #define ioremap(offset, size) \ | ||
220 | __ioremap((offset), (size), 0) | ||
221 | |||
222 | #define iounmap(addr) \ | ||
223 | __iounmap(addr) | ||
224 | |||
225 | #define cached(addr) P1SEGADDR(addr) | ||
226 | #define uncached(addr) P2SEGADDR(addr) | ||
227 | |||
228 | #define virt_to_bus virt_to_phys | ||
229 | #define bus_to_virt phys_to_virt | ||
230 | #define page_to_bus page_to_phys | ||
231 | #define bus_to_page phys_to_page | ||
232 | |||
233 | #define dma_cache_wback_inv(_start, _size) \ | ||
234 | flush_dcache_region(_start, _size) | ||
235 | #define dma_cache_inv(_start, _size) \ | ||
236 | invalidate_dcache_region(_start, _size) | ||
237 | #define dma_cache_wback(_start, _size) \ | ||
238 | clean_dcache_region(_start, _size) | ||
239 | |||
240 | /* | ||
241 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | ||
242 | * access | ||
243 | */ | ||
244 | #define xlate_dev_mem_ptr(p) __va(p) | ||
245 | |||
246 | /* | ||
247 | * Convert a virtual cached pointer to an uncached pointer | ||
248 | */ | ||
249 | #define xlate_dev_kmem_ptr(p) p | ||
250 | |||
251 | #endif /* __KERNEL__ */ | ||
252 | |||
253 | #endif /* __ASM_AVR32_IO_H */ | ||
diff --git a/include/asm-avr32/ioctl.h b/include/asm-avr32/ioctl.h new file mode 100644 index 000000000000..c8472c1398ef --- /dev/null +++ b/include/asm-avr32/ioctl.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_IOCTL_H | ||
2 | #define __ASM_AVR32_IOCTL_H | ||
3 | |||
4 | #include <asm-generic/ioctl.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_IOCTL_H */ | ||
diff --git a/include/asm-avr32/ioctls.h b/include/asm-avr32/ioctls.h new file mode 100644 index 000000000000..0500426b7186 --- /dev/null +++ b/include/asm-avr32/ioctls.h | |||
@@ -0,0 +1,83 @@ | |||
1 | #ifndef __ASM_AVR32_IOCTLS_H | ||
2 | #define __ASM_AVR32_IOCTLS_H | ||
3 | |||
4 | #include <asm/ioctl.h> | ||
5 | |||
6 | /* 0x54 is just a magic number to make these relatively unique ('T') */ | ||
7 | |||
8 | #define TCGETS 0x5401 | ||
9 | #define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ | ||
10 | #define TCSETSW 0x5403 | ||
11 | #define TCSETSF 0x5404 | ||
12 | #define TCGETA 0x5405 | ||
13 | #define TCSETA 0x5406 | ||
14 | #define TCSETAW 0x5407 | ||
15 | #define TCSETAF 0x5408 | ||
16 | #define TCSBRK 0x5409 | ||
17 | #define TCXONC 0x540A | ||
18 | #define TCFLSH 0x540B | ||
19 | #define TIOCEXCL 0x540C | ||
20 | #define TIOCNXCL 0x540D | ||
21 | #define TIOCSCTTY 0x540E | ||
22 | #define TIOCGPGRP 0x540F | ||
23 | #define TIOCSPGRP 0x5410 | ||
24 | #define TIOCOUTQ 0x5411 | ||
25 | #define TIOCSTI 0x5412 | ||
26 | #define TIOCGWINSZ 0x5413 | ||
27 | #define TIOCSWINSZ 0x5414 | ||
28 | #define TIOCMGET 0x5415 | ||
29 | #define TIOCMBIS 0x5416 | ||
30 | #define TIOCMBIC 0x5417 | ||
31 | #define TIOCMSET 0x5418 | ||
32 | #define TIOCGSOFTCAR 0x5419 | ||
33 | #define TIOCSSOFTCAR 0x541A | ||
34 | #define FIONREAD 0x541B | ||
35 | #define TIOCINQ FIONREAD | ||
36 | #define TIOCLINUX 0x541C | ||
37 | #define TIOCCONS 0x541D | ||
38 | #define TIOCGSERIAL 0x541E | ||
39 | #define TIOCSSERIAL 0x541F | ||
40 | #define TIOCPKT 0x5420 | ||
41 | #define FIONBIO 0x5421 | ||
42 | #define TIOCNOTTY 0x5422 | ||
43 | #define TIOCSETD 0x5423 | ||
44 | #define TIOCGETD 0x5424 | ||
45 | #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ | ||
46 | /* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */ | ||
47 | #define TIOCSBRK 0x5427 /* BSD compatibility */ | ||
48 | #define TIOCCBRK 0x5428 /* BSD compatibility */ | ||
49 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ | ||
50 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | ||
51 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | ||
52 | |||
53 | #define FIONCLEX 0x5450 | ||
54 | #define FIOCLEX 0x5451 | ||
55 | #define FIOASYNC 0x5452 | ||
56 | #define TIOCSERCONFIG 0x5453 | ||
57 | #define TIOCSERGWILD 0x5454 | ||
58 | #define TIOCSERSWILD 0x5455 | ||
59 | #define TIOCGLCKTRMIOS 0x5456 | ||
60 | #define TIOCSLCKTRMIOS 0x5457 | ||
61 | #define TIOCSERGSTRUCT 0x5458 /* For debugging only */ | ||
62 | #define TIOCSERGETLSR 0x5459 /* Get line status register */ | ||
63 | #define TIOCSERGETMULTI 0x545A /* Get multiport config */ | ||
64 | #define TIOCSERSETMULTI 0x545B /* Set multiport config */ | ||
65 | |||
66 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | ||
67 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | ||
68 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
69 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
70 | #define FIOQSIZE 0x5460 | ||
71 | |||
72 | /* Used for packet mode */ | ||
73 | #define TIOCPKT_DATA 0 | ||
74 | #define TIOCPKT_FLUSHREAD 1 | ||
75 | #define TIOCPKT_FLUSHWRITE 2 | ||
76 | #define TIOCPKT_STOP 4 | ||
77 | #define TIOCPKT_START 8 | ||
78 | #define TIOCPKT_NOSTOP 16 | ||
79 | #define TIOCPKT_DOSTOP 32 | ||
80 | |||
81 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | ||
82 | |||
83 | #endif /* __ASM_AVR32_IOCTLS_H */ | ||
diff --git a/include/asm-avr32/ipcbuf.h b/include/asm-avr32/ipcbuf.h new file mode 100644 index 000000000000..1552c9698f5e --- /dev/null +++ b/include/asm-avr32/ipcbuf.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ASM_AVR32_IPCBUF_H | ||
2 | #define __ASM_AVR32_IPCBUF_H | ||
3 | |||
4 | /* | ||
5 | * The user_ipc_perm structure for AVR32 architecture. | ||
6 | * Note extra padding because this structure is passed back and forth | ||
7 | * between kernel and user space. | ||
8 | * | ||
9 | * Pad space is left for: | ||
10 | * - 32-bit mode_t and seq | ||
11 | * - 2 miscellaneous 32-bit values | ||
12 | */ | ||
13 | |||
14 | struct ipc64_perm | ||
15 | { | ||
16 | __kernel_key_t key; | ||
17 | __kernel_uid32_t uid; | ||
18 | __kernel_gid32_t gid; | ||
19 | __kernel_uid32_t cuid; | ||
20 | __kernel_gid32_t cgid; | ||
21 | __kernel_mode_t mode; | ||
22 | unsigned short __pad1; | ||
23 | unsigned short seq; | ||
24 | unsigned short __pad2; | ||
25 | unsigned long __unused1; | ||
26 | unsigned long __unused2; | ||
27 | }; | ||
28 | |||
29 | #endif /* __ASM_AVR32_IPCBUF_H */ | ||
diff --git a/include/asm-avr32/irq.h b/include/asm-avr32/irq.h new file mode 100644 index 000000000000..f7e725707dd7 --- /dev/null +++ b/include/asm-avr32/irq.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __ASM_AVR32_IRQ_H | ||
2 | #define __ASM_AVR32_IRQ_H | ||
3 | |||
4 | #define NR_INTERNAL_IRQS 64 | ||
5 | #define NR_EXTERNAL_IRQS 64 | ||
6 | #define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS) | ||
7 | |||
8 | #define irq_canonicalize(i) (i) | ||
9 | |||
10 | #endif /* __ASM_AVR32_IOCTLS_H */ | ||
diff --git a/include/asm-avr32/irqflags.h b/include/asm-avr32/irqflags.h new file mode 100644 index 000000000000..93570daac38a --- /dev/null +++ b/include/asm-avr32/irqflags.h | |||
@@ -0,0 +1,68 @@ | |||
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 | #ifndef __ASM_AVR32_IRQFLAGS_H | ||
9 | #define __ASM_AVR32_IRQFLAGS_H | ||
10 | |||
11 | #include <asm/sysreg.h> | ||
12 | |||
13 | static inline unsigned long __raw_local_save_flags(void) | ||
14 | { | ||
15 | return sysreg_read(SR); | ||
16 | } | ||
17 | |||
18 | #define raw_local_save_flags(x) \ | ||
19 | do { (x) = __raw_local_save_flags(); } while (0) | ||
20 | |||
21 | /* | ||
22 | * This will restore ALL status register flags, not only the interrupt | ||
23 | * mask flag. | ||
24 | * | ||
25 | * The empty asm statement informs the compiler of this fact while | ||
26 | * also serving as a barrier. | ||
27 | */ | ||
28 | static inline void raw_local_irq_restore(unsigned long flags) | ||
29 | { | ||
30 | sysreg_write(SR, flags); | ||
31 | asm volatile("" : : : "memory", "cc"); | ||
32 | } | ||
33 | |||
34 | static inline void raw_local_irq_disable(void) | ||
35 | { | ||
36 | asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory"); | ||
37 | } | ||
38 | |||
39 | static inline void raw_local_irq_enable(void) | ||
40 | { | ||
41 | asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory"); | ||
42 | } | ||
43 | |||
44 | static inline int raw_irqs_disabled_flags(unsigned long flags) | ||
45 | { | ||
46 | return (flags & SYSREG_BIT(GM)) != 0; | ||
47 | } | ||
48 | |||
49 | static inline int raw_irqs_disabled(void) | ||
50 | { | ||
51 | unsigned long flags = __raw_local_save_flags(); | ||
52 | |||
53 | return raw_irqs_disabled_flags(flags); | ||
54 | } | ||
55 | |||
56 | static inline unsigned long __raw_local_irq_save(void) | ||
57 | { | ||
58 | unsigned long flags = __raw_local_save_flags(); | ||
59 | |||
60 | raw_local_irq_disable(); | ||
61 | |||
62 | return flags; | ||
63 | } | ||
64 | |||
65 | #define raw_local_irq_save(flags) \ | ||
66 | do { (flags) = __raw_local_irq_save(); } while (0) | ||
67 | |||
68 | #endif /* __ASM_AVR32_IRQFLAGS_H */ | ||
diff --git a/include/asm-avr32/kdebug.h b/include/asm-avr32/kdebug.h new file mode 100644 index 000000000000..f583b643ffb2 --- /dev/null +++ b/include/asm-avr32/kdebug.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef __ASM_AVR32_KDEBUG_H | ||
2 | #define __ASM_AVR32_KDEBUG_H | ||
3 | |||
4 | #include <linux/notifier.h> | ||
5 | |||
6 | struct pt_regs; | ||
7 | |||
8 | struct die_args { | ||
9 | struct pt_regs *regs; | ||
10 | int trapnr; | ||
11 | }; | ||
12 | |||
13 | int register_die_notifier(struct notifier_block *nb); | ||
14 | int unregister_die_notifier(struct notifier_block *nb); | ||
15 | int register_page_fault_notifier(struct notifier_block *nb); | ||
16 | int unregister_page_fault_notifier(struct notifier_block *nb); | ||
17 | extern struct atomic_notifier_head avr32_die_chain; | ||
18 | |||
19 | /* Grossly misnamed. */ | ||
20 | enum die_val { | ||
21 | DIE_FAULT, | ||
22 | DIE_BREAKPOINT, | ||
23 | DIE_SSTEP, | ||
24 | DIE_PAGE_FAULT, | ||
25 | }; | ||
26 | |||
27 | static inline int notify_die(enum die_val val, struct pt_regs *regs, | ||
28 | int trap, int sig) | ||
29 | { | ||
30 | struct die_args args = { | ||
31 | .regs = regs, | ||
32 | .trapnr = trap, | ||
33 | }; | ||
34 | |||
35 | return atomic_notifier_call_chain(&avr32_die_chain, val, &args); | ||
36 | } | ||
37 | |||
38 | #endif /* __ASM_AVR32_KDEBUG_H */ | ||
diff --git a/include/asm-avr32/kmap_types.h b/include/asm-avr32/kmap_types.h new file mode 100644 index 000000000000..b7f5c6870107 --- /dev/null +++ b/include/asm-avr32/kmap_types.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef __ASM_AVR32_KMAP_TYPES_H | ||
2 | #define __ASM_AVR32_KMAP_TYPES_H | ||
3 | |||
4 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
5 | # define D(n) __KM_FENCE_##n , | ||
6 | #else | ||
7 | # define D(n) | ||
8 | #endif | ||
9 | |||
10 | enum km_type { | ||
11 | D(0) KM_BOUNCE_READ, | ||
12 | D(1) KM_SKB_SUNRPC_DATA, | ||
13 | D(2) KM_SKB_DATA_SOFTIRQ, | ||
14 | D(3) KM_USER0, | ||
15 | D(4) KM_USER1, | ||
16 | D(5) KM_BIO_SRC_IRQ, | ||
17 | D(6) KM_BIO_DST_IRQ, | ||
18 | D(7) KM_PTE0, | ||
19 | D(8) KM_PTE1, | ||
20 | D(9) KM_PTE2, | ||
21 | D(10) KM_IRQ0, | ||
22 | D(11) KM_IRQ1, | ||
23 | D(12) KM_SOFTIRQ0, | ||
24 | D(13) KM_SOFTIRQ1, | ||
25 | D(14) KM_TYPE_NR | ||
26 | }; | ||
27 | |||
28 | #undef D | ||
29 | |||
30 | #endif /* __ASM_AVR32_KMAP_TYPES_H */ | ||
diff --git a/include/asm-avr32/kprobes.h b/include/asm-avr32/kprobes.h new file mode 100644 index 000000000000..09a5cbe2f896 --- /dev/null +++ b/include/asm-avr32/kprobes.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Kernel Probes (KProbes) | ||
3 | * | ||
4 | * Copyright (C) 2005-2006 Atmel Corporation | ||
5 | * Copyright (C) IBM Corporation, 2002, 2004 | ||
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 | #ifndef __ASM_AVR32_KPROBES_H | ||
12 | #define __ASM_AVR32_KPROBES_H | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | |||
16 | typedef u16 kprobe_opcode_t; | ||
17 | #define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */ | ||
18 | #define MAX_INSN_SIZE 2 | ||
19 | |||
20 | #define ARCH_INACTIVE_KPROBE_COUNT 1 | ||
21 | |||
22 | #define arch_remove_kprobe(p) do { } while (0) | ||
23 | |||
24 | /* Architecture specific copy of original instruction */ | ||
25 | struct arch_specific_insn { | ||
26 | kprobe_opcode_t insn[MAX_INSN_SIZE]; | ||
27 | }; | ||
28 | |||
29 | extern int kprobe_exceptions_notify(struct notifier_block *self, | ||
30 | unsigned long val, void *data); | ||
31 | |||
32 | #define flush_insn_slot(p) do { } while (0) | ||
33 | |||
34 | #endif /* __ASM_AVR32_KPROBES_H */ | ||
diff --git a/include/asm-avr32/linkage.h b/include/asm-avr32/linkage.h new file mode 100644 index 000000000000..f7b285e910d4 --- /dev/null +++ b/include/asm-avr32/linkage.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_LINKAGE_H | ||
2 | #define __ASM_LINKAGE_H | ||
3 | |||
4 | #define __ALIGN .balign 2 | ||
5 | #define __ALIGN_STR ".balign 2" | ||
6 | |||
7 | #endif /* __ASM_LINKAGE_H */ | ||
diff --git a/include/asm-avr32/local.h b/include/asm-avr32/local.h new file mode 100644 index 000000000000..1c1619694da3 --- /dev/null +++ b/include/asm-avr32/local.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_LOCAL_H | ||
2 | #define __ASM_AVR32_LOCAL_H | ||
3 | |||
4 | #include <asm-generic/local.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_LOCAL_H */ | ||
diff --git a/include/asm-avr32/mach/serial_at91.h b/include/asm-avr32/mach/serial_at91.h new file mode 100644 index 000000000000..1290bb32802d --- /dev/null +++ b/include/asm-avr32/mach/serial_at91.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * linux/include/asm-arm/mach/serial_at91.h | ||
3 | * | ||
4 | * Based on serial_sa1100.h by Nicolas Pitre | ||
5 | * | ||
6 | * Copyright (C) 2002 ATMEL Rousset | ||
7 | * | ||
8 | * Low level machine dependent UART functions. | ||
9 | */ | ||
10 | |||
11 | struct uart_port; | ||
12 | |||
13 | /* | ||
14 | * This is a temporary structure for registering these | ||
15 | * functions; it is intended to be discarded after boot. | ||
16 | */ | ||
17 | struct at91_port_fns { | ||
18 | void (*set_mctrl)(struct uart_port *, u_int); | ||
19 | u_int (*get_mctrl)(struct uart_port *); | ||
20 | void (*enable_ms)(struct uart_port *); | ||
21 | void (*pm)(struct uart_port *, u_int, u_int); | ||
22 | int (*set_wake)(struct uart_port *, u_int); | ||
23 | int (*open)(struct uart_port *); | ||
24 | void (*close)(struct uart_port *); | ||
25 | }; | ||
26 | |||
27 | #if defined(CONFIG_SERIAL_AT91) | ||
28 | void at91_register_uart_fns(struct at91_port_fns *fns); | ||
29 | #else | ||
30 | #define at91_register_uart_fns(fns) do { } while (0) | ||
31 | #endif | ||
32 | |||
33 | |||
diff --git a/include/asm-avr32/mman.h b/include/asm-avr32/mman.h new file mode 100644 index 000000000000..648f91e7187a --- /dev/null +++ b/include/asm-avr32/mman.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef __ASM_AVR32_MMAN_H__ | ||
2 | #define __ASM_AVR32_MMAN_H__ | ||
3 | |||
4 | #include <asm-generic/mman.h> | ||
5 | |||
6 | #define MAP_GROWSDOWN 0x0100 /* stack-like segment */ | ||
7 | #define MAP_DENYWRITE 0x0800 /* ETXTBSY */ | ||
8 | #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ | ||
9 | #define MAP_LOCKED 0x2000 /* pages are locked */ | ||
10 | #define MAP_NORESERVE 0x4000 /* don't check for reservations */ | ||
11 | #define MAP_POPULATE 0x8000 /* populate (prefault) page tables */ | ||
12 | #define MAP_NONBLOCK 0x10000 /* do not block on IO */ | ||
13 | |||
14 | #define MCL_CURRENT 1 /* lock all current mappings */ | ||
15 | #define MCL_FUTURE 2 /* lock all future mappings */ | ||
16 | |||
17 | #endif /* __ASM_AVR32_MMAN_H__ */ | ||
diff --git a/include/asm-avr32/mmu.h b/include/asm-avr32/mmu.h new file mode 100644 index 000000000000..60c2d2650d32 --- /dev/null +++ b/include/asm-avr32/mmu.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __ASM_AVR32_MMU_H | ||
2 | #define __ASM_AVR32_MMU_H | ||
3 | |||
4 | /* Default "unsigned long" context */ | ||
5 | typedef unsigned long mm_context_t; | ||
6 | |||
7 | #define MMU_ITLB_ENTRIES 64 | ||
8 | #define MMU_DTLB_ENTRIES 64 | ||
9 | |||
10 | #endif /* __ASM_AVR32_MMU_H */ | ||
diff --git a/include/asm-avr32/mmu_context.h b/include/asm-avr32/mmu_context.h new file mode 100644 index 000000000000..31add1ae8089 --- /dev/null +++ b/include/asm-avr32/mmu_context.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * ASID handling taken from SH implementation. | ||
5 | * Copyright (C) 1999 Niibe Yutaka | ||
6 | * Copyright (C) 2003 Paul Mundt | ||
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 | #ifndef __ASM_AVR32_MMU_CONTEXT_H | ||
13 | #define __ASM_AVR32_MMU_CONTEXT_H | ||
14 | |||
15 | #include <asm/tlbflush.h> | ||
16 | #include <asm/pgalloc.h> | ||
17 | #include <asm/sysreg.h> | ||
18 | |||
19 | /* | ||
20 | * The MMU "context" consists of two things: | ||
21 | * (a) TLB cache version | ||
22 | * (b) ASID (Address Space IDentifier) | ||
23 | */ | ||
24 | #define MMU_CONTEXT_ASID_MASK 0x000000ff | ||
25 | #define MMU_CONTEXT_VERSION_MASK 0xffffff00 | ||
26 | #define MMU_CONTEXT_FIRST_VERSION 0x00000100 | ||
27 | #define NO_CONTEXT 0 | ||
28 | |||
29 | #define MMU_NO_ASID 0x100 | ||
30 | |||
31 | /* Virtual Page Number mask */ | ||
32 | #define MMU_VPN_MASK 0xfffff000 | ||
33 | |||
34 | /* Cache of MMU context last used */ | ||
35 | extern unsigned long mmu_context_cache; | ||
36 | |||
37 | /* | ||
38 | * Get MMU context if needed | ||
39 | */ | ||
40 | static inline void | ||
41 | get_mmu_context(struct mm_struct *mm) | ||
42 | { | ||
43 | unsigned long mc = mmu_context_cache; | ||
44 | |||
45 | if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0) | ||
46 | /* It's up to date, do nothing */ | ||
47 | return; | ||
48 | |||
49 | /* It's old, we need to get new context with new version */ | ||
50 | mc = ++mmu_context_cache; | ||
51 | if (!(mc & MMU_CONTEXT_ASID_MASK)) { | ||
52 | /* | ||
53 | * We have exhausted all ASIDs of this version. | ||
54 | * Flush the TLB and start new cycle. | ||
55 | */ | ||
56 | flush_tlb_all(); | ||
57 | /* | ||
58 | * Fix version. Note that we avoid version #0 | ||
59 | * to distinguish NO_CONTEXT. | ||
60 | */ | ||
61 | if (!mc) | ||
62 | mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION; | ||
63 | } | ||
64 | mm->context = mc; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * Initialize the context related info for a new mm_struct | ||
69 | * instance. | ||
70 | */ | ||
71 | static inline int init_new_context(struct task_struct *tsk, | ||
72 | struct mm_struct *mm) | ||
73 | { | ||
74 | mm->context = NO_CONTEXT; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Destroy context related info for an mm_struct that is about | ||
80 | * to be put to rest. | ||
81 | */ | ||
82 | static inline void destroy_context(struct mm_struct *mm) | ||
83 | { | ||
84 | /* Do nothing */ | ||
85 | } | ||
86 | |||
87 | static inline void set_asid(unsigned long asid) | ||
88 | { | ||
89 | /* XXX: We're destroying TLBEHI[8:31] */ | ||
90 | sysreg_write(TLBEHI, asid & MMU_CONTEXT_ASID_MASK); | ||
91 | cpu_sync_pipeline(); | ||
92 | } | ||
93 | |||
94 | static inline unsigned long get_asid(void) | ||
95 | { | ||
96 | unsigned long asid; | ||
97 | |||
98 | asid = sysreg_read(TLBEHI); | ||
99 | return asid & MMU_CONTEXT_ASID_MASK; | ||
100 | } | ||
101 | |||
102 | static inline void activate_context(struct mm_struct *mm) | ||
103 | { | ||
104 | get_mmu_context(mm); | ||
105 | set_asid(mm->context & MMU_CONTEXT_ASID_MASK); | ||
106 | } | ||
107 | |||
108 | static inline void switch_mm(struct mm_struct *prev, | ||
109 | struct mm_struct *next, | ||
110 | struct task_struct *tsk) | ||
111 | { | ||
112 | if (likely(prev != next)) { | ||
113 | unsigned long __pgdir = (unsigned long)next->pgd; | ||
114 | |||
115 | sysreg_write(PTBR, __pgdir); | ||
116 | activate_context(next); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | #define deactivate_mm(tsk,mm) do { } while(0) | ||
121 | |||
122 | #define activate_mm(prev, next) switch_mm((prev), (next), NULL) | ||
123 | |||
124 | static inline void | ||
125 | enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | ||
126 | { | ||
127 | } | ||
128 | |||
129 | |||
130 | static inline void enable_mmu(void) | ||
131 | { | ||
132 | sysreg_write(MMUCR, (SYSREG_BIT(MMUCR_S) | ||
133 | | SYSREG_BIT(E) | ||
134 | | SYSREG_BIT(MMUCR_I))); | ||
135 | nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); | ||
136 | |||
137 | if (mmu_context_cache == NO_CONTEXT) | ||
138 | mmu_context_cache = MMU_CONTEXT_FIRST_VERSION; | ||
139 | |||
140 | set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK); | ||
141 | } | ||
142 | |||
143 | static inline void disable_mmu(void) | ||
144 | { | ||
145 | sysreg_write(MMUCR, SYSREG_BIT(MMUCR_S)); | ||
146 | } | ||
147 | |||
148 | #endif /* __ASM_AVR32_MMU_CONTEXT_H */ | ||
diff --git a/include/asm-avr32/module.h b/include/asm-avr32/module.h new file mode 100644 index 000000000000..451444538a1b --- /dev/null +++ b/include/asm-avr32/module.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef __ASM_AVR32_MODULE_H | ||
2 | #define __ASM_AVR32_MODULE_H | ||
3 | |||
4 | struct mod_arch_syminfo { | ||
5 | unsigned long got_offset; | ||
6 | int got_initialized; | ||
7 | }; | ||
8 | |||
9 | struct mod_arch_specific { | ||
10 | /* Starting offset of got in the module core memory. */ | ||
11 | unsigned long got_offset; | ||
12 | /* Size of the got. */ | ||
13 | unsigned long got_size; | ||
14 | /* Number of symbols in syminfo. */ | ||
15 | int nsyms; | ||
16 | /* Additional symbol information (got offsets). */ | ||
17 | struct mod_arch_syminfo *syminfo; | ||
18 | }; | ||
19 | |||
20 | #define Elf_Shdr Elf32_Shdr | ||
21 | #define Elf_Sym Elf32_Sym | ||
22 | #define Elf_Ehdr Elf32_Ehdr | ||
23 | |||
24 | #define MODULE_PROC_FAMILY "AVR32v1" | ||
25 | |||
26 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY | ||
27 | |||
28 | #endif /* __ASM_AVR32_MODULE_H */ | ||
diff --git a/include/asm-avr32/msgbuf.h b/include/asm-avr32/msgbuf.h new file mode 100644 index 000000000000..ac18bc4da7f7 --- /dev/null +++ b/include/asm-avr32/msgbuf.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef __ASM_AVR32_MSGBUF_H | ||
2 | #define __ASM_AVR32_MSGBUF_H | ||
3 | |||
4 | /* | ||
5 | * The msqid64_ds structure for i386 architecture. | ||
6 | * Note extra padding because this structure is passed back and forth | ||
7 | * between kernel and user space. | ||
8 | * | ||
9 | * Pad space is left for: | ||
10 | * - 64-bit time_t to solve y2038 problem | ||
11 | * - 2 miscellaneous 32-bit values | ||
12 | */ | ||
13 | |||
14 | struct msqid64_ds { | ||
15 | struct ipc64_perm msg_perm; | ||
16 | __kernel_time_t msg_stime; /* last msgsnd time */ | ||
17 | unsigned long __unused1; | ||
18 | __kernel_time_t msg_rtime; /* last msgrcv time */ | ||
19 | unsigned long __unused2; | ||
20 | __kernel_time_t msg_ctime; /* last change time */ | ||
21 | unsigned long __unused3; | ||
22 | unsigned long msg_cbytes; /* current number of bytes on queue */ | ||
23 | unsigned long msg_qnum; /* number of messages in queue */ | ||
24 | unsigned long msg_qbytes; /* max number of bytes on queue */ | ||
25 | __kernel_pid_t msg_lspid; /* pid of last msgsnd */ | ||
26 | __kernel_pid_t msg_lrpid; /* last receive pid */ | ||
27 | unsigned long __unused4; | ||
28 | unsigned long __unused5; | ||
29 | }; | ||
30 | |||
31 | #endif /* __ASM_AVR32_MSGBUF_H */ | ||
diff --git a/include/asm-avr32/mutex.h b/include/asm-avr32/mutex.h new file mode 100644 index 000000000000..458c1f7fbc18 --- /dev/null +++ b/include/asm-avr32/mutex.h | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * Pull in the generic implementation for the mutex fastpath. | ||
3 | * | ||
4 | * TODO: implement optimized primitives instead, or leave the generic | ||
5 | * implementation in place, or pick the atomic_xchg() based generic | ||
6 | * implementation. (see asm-generic/mutex-xchg.h for details) | ||
7 | */ | ||
8 | |||
9 | #include <asm-generic/mutex-dec.h> | ||
diff --git a/include/asm-avr32/namei.h b/include/asm-avr32/namei.h new file mode 100644 index 000000000000..f0a26de06cab --- /dev/null +++ b/include/asm-avr32/namei.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_AVR32_NAMEI_H | ||
2 | #define __ASM_AVR32_NAMEI_H | ||
3 | |||
4 | /* This dummy routine may be changed to something useful */ | ||
5 | #define __emul_prefix() NULL | ||
6 | |||
7 | #endif /* __ASM_AVR32_NAMEI_H */ | ||
diff --git a/include/asm-avr32/numnodes.h b/include/asm-avr32/numnodes.h new file mode 100644 index 000000000000..0b864d7ce330 --- /dev/null +++ b/include/asm-avr32/numnodes.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_AVR32_NUMNODES_H | ||
2 | #define __ASM_AVR32_NUMNODES_H | ||
3 | |||
4 | /* Max 4 nodes */ | ||
5 | #define NODES_SHIFT 2 | ||
6 | |||
7 | #endif /* __ASM_AVR32_NUMNODES_H */ | ||
diff --git a/include/asm-avr32/ocd.h b/include/asm-avr32/ocd.h new file mode 100644 index 000000000000..46f73180a127 --- /dev/null +++ b/include/asm-avr32/ocd.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * AVR32 OCD Registers | ||
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 __ASM_AVR32_OCD_H | ||
11 | #define __ASM_AVR32_OCD_H | ||
12 | |||
13 | /* Debug Registers */ | ||
14 | #define DBGREG_DID 0 | ||
15 | #define DBGREG_DC 8 | ||
16 | #define DBGREG_DS 16 | ||
17 | #define DBGREG_RWCS 28 | ||
18 | #define DBGREG_RWA 36 | ||
19 | #define DBGREG_RWD 40 | ||
20 | #define DBGREG_WT 44 | ||
21 | #define DBGREG_DTC 52 | ||
22 | #define DBGREG_DTSA0 56 | ||
23 | #define DBGREG_DTSA1 60 | ||
24 | #define DBGREG_DTEA0 72 | ||
25 | #define DBGREG_DTEA1 76 | ||
26 | #define DBGREG_BWC0A 88 | ||
27 | #define DBGREG_BWC0B 92 | ||
28 | #define DBGREG_BWC1A 96 | ||
29 | #define DBGREG_BWC1B 100 | ||
30 | #define DBGREG_BWC2A 104 | ||
31 | #define DBGREG_BWC2B 108 | ||
32 | #define DBGREG_BWC3A 112 | ||
33 | #define DBGREG_BWC3B 116 | ||
34 | #define DBGREG_BWA0A 120 | ||
35 | #define DBGREG_BWA0B 124 | ||
36 | #define DBGREG_BWA1A 128 | ||
37 | #define DBGREG_BWA1B 132 | ||
38 | #define DBGREG_BWA2A 136 | ||
39 | #define DBGREG_BWA2B 140 | ||
40 | #define DBGREG_BWA3A 144 | ||
41 | #define DBGREG_BWA3B 148 | ||
42 | #define DBGREG_BWD3A 153 | ||
43 | #define DBGREG_BWD3B 156 | ||
44 | |||
45 | #define DBGREG_PID 284 | ||
46 | |||
47 | #define SABAH_OCD 0x01 | ||
48 | #define SABAH_ICACHE 0x02 | ||
49 | #define SABAH_MEM_CACHED 0x04 | ||
50 | #define SABAH_MEM_UNCACHED 0x05 | ||
51 | |||
52 | /* Fields in the Development Control register */ | ||
53 | #define DC_SS_BIT 8 | ||
54 | |||
55 | #define DC_SS (1 << DC_SS_BIT) | ||
56 | #define DC_DBE (1 << 13) | ||
57 | #define DC_RID (1 << 27) | ||
58 | #define DC_ORP (1 << 28) | ||
59 | #define DC_MM (1 << 29) | ||
60 | #define DC_RES (1 << 30) | ||
61 | |||
62 | /* Fields in the Development Status register */ | ||
63 | #define DS_SSS (1 << 0) | ||
64 | #define DS_SWB (1 << 1) | ||
65 | #define DS_HWB (1 << 2) | ||
66 | #define DS_BP_SHIFT 8 | ||
67 | #define DS_BP_MASK (0xff << DS_BP_SHIFT) | ||
68 | |||
69 | #define __mfdr(addr) \ | ||
70 | ({ \ | ||
71 | register unsigned long value; \ | ||
72 | asm volatile("mfdr %0, %1" : "=r"(value) : "i"(addr)); \ | ||
73 | value; \ | ||
74 | }) | ||
75 | #define __mtdr(addr, value) \ | ||
76 | asm volatile("mtdr %0, %1" : : "i"(addr), "r"(value)) | ||
77 | |||
78 | #endif /* __ASM_AVR32_OCD_H */ | ||
diff --git a/include/asm-avr32/page.h b/include/asm-avr32/page.h new file mode 100644 index 000000000000..0f630b3e9932 --- /dev/null +++ b/include/asm-avr32/page.h | |||
@@ -0,0 +1,112 @@ | |||
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 | #ifndef __ASM_AVR32_PAGE_H | ||
9 | #define __ASM_AVR32_PAGE_H | ||
10 | |||
11 | #ifdef __KERNEL__ | ||
12 | |||
13 | /* PAGE_SHIFT determines the page size */ | ||
14 | #define PAGE_SHIFT 12 | ||
15 | #ifdef __ASSEMBLY__ | ||
16 | #define PAGE_SIZE (1 << PAGE_SHIFT) | ||
17 | #else | ||
18 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | ||
19 | #endif | ||
20 | #define PAGE_MASK (~(PAGE_SIZE-1)) | ||
21 | #define PTE_MASK PAGE_MASK | ||
22 | |||
23 | #ifndef __ASSEMBLY__ | ||
24 | |||
25 | #include <asm/addrspace.h> | ||
26 | |||
27 | extern void clear_page(void *to); | ||
28 | extern void copy_page(void *to, void *from); | ||
29 | |||
30 | #define clear_user_page(page, vaddr, pg) clear_page(page) | ||
31 | #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) | ||
32 | |||
33 | /* | ||
34 | * These are used to make use of C type-checking.. | ||
35 | */ | ||
36 | typedef struct { unsigned long pte; } pte_t; | ||
37 | typedef struct { unsigned long pgd; } pgd_t; | ||
38 | typedef struct { unsigned long pgprot; } pgprot_t; | ||
39 | |||
40 | #define pte_val(x) ((x).pte) | ||
41 | #define pgd_val(x) ((x).pgd) | ||
42 | #define pgprot_val(x) ((x).pgprot) | ||
43 | |||
44 | #define __pte(x) ((pte_t) { (x) }) | ||
45 | #define __pgd(x) ((pgd_t) { (x) }) | ||
46 | #define __pgprot(x) ((pgprot_t) { (x) }) | ||
47 | |||
48 | /* FIXME: These should be removed soon */ | ||
49 | extern unsigned long memory_start, memory_end; | ||
50 | |||
51 | /* Pure 2^n version of get_order */ | ||
52 | static inline int get_order(unsigned long size) | ||
53 | { | ||
54 | unsigned lz; | ||
55 | |||
56 | size = (size - 1) >> PAGE_SHIFT; | ||
57 | asm("clz %0, %1" : "=r"(lz) : "r"(size)); | ||
58 | return 32 - lz; | ||
59 | } | ||
60 | |||
61 | #endif /* !__ASSEMBLY__ */ | ||
62 | |||
63 | /* Align the pointer to the (next) page boundary */ | ||
64 | #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | ||
65 | |||
66 | /* | ||
67 | * The hardware maps the virtual addresses 0x80000000 -> 0x9fffffff | ||
68 | * permanently to the physical addresses 0x00000000 -> 0x1fffffff when | ||
69 | * segmentation is enabled. We want to make use of this in order to | ||
70 | * minimize TLB pressure. | ||
71 | */ | ||
72 | #define PAGE_OFFSET (0x80000000UL) | ||
73 | |||
74 | /* | ||
75 | * ALSA uses virt_to_page() on DMA pages, which I'm not entirely sure | ||
76 | * is a good idea. Anyway, we can't simply subtract PAGE_OFFSET here | ||
77 | * in that case, so we'll have to mask out the three most significant | ||
78 | * bits of the address instead... | ||
79 | * | ||
80 | * What's the difference between __pa() and virt_to_phys() anyway? | ||
81 | */ | ||
82 | #define __pa(x) PHYSADDR(x) | ||
83 | #define __va(x) ((void *)(P1SEGADDR(x))) | ||
84 | |||
85 | #define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) | ||
86 | |||
87 | #define phys_to_page(phys) (pfn_to_page(phys >> PAGE_SHIFT)) | ||
88 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) | ||
89 | |||
90 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
91 | |||
92 | #define PHYS_PFN_OFFSET (CONFIG_PHYS_OFFSET >> PAGE_SHIFT) | ||
93 | |||
94 | #define pfn_to_page(pfn) (mem_map + ((pfn) - PHYS_PFN_OFFSET)) | ||
95 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PHYS_PFN_OFFSET) | ||
96 | #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) | ||
97 | #endif /* CONFIG_NEED_MULTIPLE_NODES */ | ||
98 | |||
99 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
100 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | ||
101 | |||
102 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ | ||
103 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
104 | |||
105 | /* | ||
106 | * Memory above this physical address will be considered highmem. | ||
107 | */ | ||
108 | #define HIGHMEM_START 0x20000000UL | ||
109 | |||
110 | #endif /* __KERNEL__ */ | ||
111 | |||
112 | #endif /* __ASM_AVR32_PAGE_H */ | ||
diff --git a/include/asm-avr32/param.h b/include/asm-avr32/param.h new file mode 100644 index 000000000000..34bc8d4c3b29 --- /dev/null +++ b/include/asm-avr32/param.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef __ASM_AVR32_PARAM_H | ||
2 | #define __ASM_AVR32_PARAM_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | # define HZ CONFIG_HZ | ||
6 | # define USER_HZ 100 /* User interfaces are in "ticks" */ | ||
7 | # define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ | ||
8 | #endif | ||
9 | |||
10 | #ifndef HZ | ||
11 | # define HZ 100 | ||
12 | #endif | ||
13 | |||
14 | /* TODO: Should be configurable */ | ||
15 | #define EXEC_PAGESIZE 4096 | ||
16 | |||
17 | #ifndef NOGROUP | ||
18 | # define NOGROUP (-1) | ||
19 | #endif | ||
20 | |||
21 | #define MAXHOSTNAMELEN 64 | ||
22 | |||
23 | #endif /* __ASM_AVR32_PARAM_H */ | ||
diff --git a/include/asm-avr32/pci.h b/include/asm-avr32/pci.h new file mode 100644 index 000000000000..0f5f134b896a --- /dev/null +++ b/include/asm-avr32/pci.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __ASM_AVR32_PCI_H__ | ||
2 | #define __ASM_AVR32_PCI_H__ | ||
3 | |||
4 | /* We don't support PCI yet, but some drivers require this file anyway */ | ||
5 | |||
6 | #define PCI_DMA_BUS_IS_PHYS (1) | ||
7 | |||
8 | #endif /* __ASM_AVR32_PCI_H__ */ | ||
diff --git a/include/asm-avr32/percpu.h b/include/asm-avr32/percpu.h new file mode 100644 index 000000000000..69227b4cd0d4 --- /dev/null +++ b/include/asm-avr32/percpu.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_PERCPU_H | ||
2 | #define __ASM_AVR32_PERCPU_H | ||
3 | |||
4 | #include <asm-generic/percpu.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_PERCPU_H */ | ||
diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h new file mode 100644 index 000000000000..7492cfb92ced --- /dev/null +++ b/include/asm-avr32/pgalloc.h | |||
@@ -0,0 +1,96 @@ | |||
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 | #ifndef __ASM_AVR32_PGALLOC_H | ||
9 | #define __ASM_AVR32_PGALLOC_H | ||
10 | |||
11 | #include <asm/processor.h> | ||
12 | #include <linux/threads.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/mm.h> | ||
15 | |||
16 | #define pmd_populate_kernel(mm, pmd, pte) \ | ||
17 | set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) | ||
18 | |||
19 | static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | ||
20 | struct page *pte) | ||
21 | { | ||
22 | set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); | ||
23 | } | ||
24 | |||
25 | /* | ||
26 | * Allocate and free page tables | ||
27 | */ | ||
28 | static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm) | ||
29 | { | ||
30 | unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t)); | ||
31 | pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL); | ||
32 | |||
33 | if (pgd) | ||
34 | memset(pgd, 0, pgd_size); | ||
35 | |||
36 | return pgd; | ||
37 | } | ||
38 | |||
39 | static inline void pgd_free(pgd_t *pgd) | ||
40 | { | ||
41 | kfree(pgd); | ||
42 | } | ||
43 | |||
44 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | ||
45 | unsigned long address) | ||
46 | { | ||
47 | int count = 0; | ||
48 | pte_t *pte; | ||
49 | |||
50 | do { | ||
51 | pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT); | ||
52 | if (pte) | ||
53 | clear_page(pte); | ||
54 | else { | ||
55 | current->state = TASK_UNINTERRUPTIBLE; | ||
56 | schedule_timeout(HZ); | ||
57 | } | ||
58 | } while (!pte && (count++ < 10)); | ||
59 | |||
60 | return pte; | ||
61 | } | ||
62 | |||
63 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | ||
64 | unsigned long address) | ||
65 | { | ||
66 | int count = 0; | ||
67 | struct page *pte; | ||
68 | |||
69 | do { | ||
70 | pte = alloc_pages(GFP_KERNEL, 0); | ||
71 | if (pte) | ||
72 | clear_page(page_address(pte)); | ||
73 | else { | ||
74 | current->state = TASK_UNINTERRUPTIBLE; | ||
75 | schedule_timeout(HZ); | ||
76 | } | ||
77 | } while (!pte && (count++ < 10)); | ||
78 | |||
79 | return pte; | ||
80 | } | ||
81 | |||
82 | static inline void pte_free_kernel(pte_t *pte) | ||
83 | { | ||
84 | free_page((unsigned long)pte); | ||
85 | } | ||
86 | |||
87 | static inline void pte_free(struct page *pte) | ||
88 | { | ||
89 | __free_page(pte); | ||
90 | } | ||
91 | |||
92 | #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) | ||
93 | |||
94 | #define check_pgt_cache() do { } while(0) | ||
95 | |||
96 | #endif /* __ASM_AVR32_PGALLOC_H */ | ||
diff --git a/include/asm-avr32/pgtable-2level.h b/include/asm-avr32/pgtable-2level.h new file mode 100644 index 000000000000..425dd567b5b9 --- /dev/null +++ b/include/asm-avr32/pgtable-2level.h | |||
@@ -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 | #ifndef __ASM_AVR32_PGTABLE_2LEVEL_H | ||
9 | #define __ASM_AVR32_PGTABLE_2LEVEL_H | ||
10 | |||
11 | #include <asm-generic/pgtable-nopmd.h> | ||
12 | |||
13 | /* | ||
14 | * Traditional 2-level paging structure | ||
15 | */ | ||
16 | #define PGDIR_SHIFT 22 | ||
17 | #define PTRS_PER_PGD 1024 | ||
18 | |||
19 | #define PTRS_PER_PTE 1024 | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | #define pte_ERROR(e) \ | ||
23 | printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) | ||
24 | #define pgd_ERROR(e) \ | ||
25 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) | ||
26 | |||
27 | /* | ||
28 | * Certain architectures need to do special things when PTEs | ||
29 | * within a page table are directly modified. Thus, the following | ||
30 | * hook is made available. | ||
31 | */ | ||
32 | #define set_pte(pteptr, pteval) (*(pteptr) = pteval) | ||
33 | #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep, pteval) | ||
34 | |||
35 | /* | ||
36 | * (pmds are folded into pgds so this doesn't get actually called, | ||
37 | * but the define is needed for a generic inline function.) | ||
38 | */ | ||
39 | #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) | ||
40 | |||
41 | #define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) | ||
42 | #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) | ||
43 | #define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) | ||
44 | |||
45 | #endif /* !__ASSEMBLY__ */ | ||
46 | |||
47 | #endif /* __ASM_AVR32_PGTABLE_2LEVEL_H */ | ||
diff --git a/include/asm-avr32/pgtable.h b/include/asm-avr32/pgtable.h new file mode 100644 index 000000000000..6b8ca9db2bd5 --- /dev/null +++ b/include/asm-avr32/pgtable.h | |||
@@ -0,0 +1,408 @@ | |||
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 | #ifndef __ASM_AVR32_PGTABLE_H | ||
9 | #define __ASM_AVR32_PGTABLE_H | ||
10 | |||
11 | #include <asm/addrspace.h> | ||
12 | |||
13 | #ifndef __ASSEMBLY__ | ||
14 | #include <linux/sched.h> | ||
15 | |||
16 | #endif /* !__ASSEMBLY__ */ | ||
17 | |||
18 | /* | ||
19 | * Use two-level page tables just as the i386 (without PAE) | ||
20 | */ | ||
21 | #include <asm/pgtable-2level.h> | ||
22 | |||
23 | /* | ||
24 | * The following code might need some cleanup when the values are | ||
25 | * final... | ||
26 | */ | ||
27 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
28 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
29 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
30 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
31 | |||
32 | #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) | ||
33 | #define FIRST_USER_ADDRESS 0 | ||
34 | |||
35 | #define PTE_PHYS_MASK 0x1ffff000 | ||
36 | |||
37 | #ifndef __ASSEMBLY__ | ||
38 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
39 | extern void paging_init(void); | ||
40 | |||
41 | /* | ||
42 | * ZERO_PAGE is a global shared page that is always zero: used for | ||
43 | * zero-mapped memory areas etc. | ||
44 | */ | ||
45 | extern struct page *empty_zero_page; | ||
46 | #define ZERO_PAGE(vaddr) (empty_zero_page) | ||
47 | |||
48 | /* | ||
49 | * Just any arbitrary offset to the start of the vmalloc VM area: the | ||
50 | * current 8 MiB value just means that there will be a 8 MiB "hole" | ||
51 | * after the uncached physical memory (P2 segment) until the vmalloc | ||
52 | * area starts. That means that any out-of-bounds memory accesses will | ||
53 | * hopefully be caught; we don't know if the end of the P1/P2 segments | ||
54 | * are actually used for anything, but it is anyway safer to let the | ||
55 | * MMU catch these kinds of errors than to rely on the memory bus. | ||
56 | * | ||
57 | * A "hole" of the same size is added to the end of the P3 segment as | ||
58 | * well. It might seem wasteful to use 16 MiB of virtual address space | ||
59 | * on this, but we do have 512 MiB of it... | ||
60 | * | ||
61 | * The vmalloc() routines leave a hole of 4 KiB between each vmalloced | ||
62 | * area for the same reason. | ||
63 | */ | ||
64 | #define VMALLOC_OFFSET (8 * 1024 * 1024) | ||
65 | #define VMALLOC_START (P3SEG + VMALLOC_OFFSET) | ||
66 | #define VMALLOC_END (P4SEG - VMALLOC_OFFSET) | ||
67 | #endif /* !__ASSEMBLY__ */ | ||
68 | |||
69 | /* | ||
70 | * Page flags. Some of these flags are not directly supported by | ||
71 | * hardware, so we have to emulate them. | ||
72 | */ | ||
73 | #define _TLBEHI_BIT_VALID 9 | ||
74 | #define _TLBEHI_VALID (1 << _TLBEHI_BIT_VALID) | ||
75 | |||
76 | #define _PAGE_BIT_WT 0 /* W-bit : write-through */ | ||
77 | #define _PAGE_BIT_DIRTY 1 /* D-bit : page changed */ | ||
78 | #define _PAGE_BIT_SZ0 2 /* SZ0-bit : Size of page */ | ||
79 | #define _PAGE_BIT_SZ1 3 /* SZ1-bit : Size of page */ | ||
80 | #define _PAGE_BIT_EXECUTE 4 /* X-bit : execute access allowed */ | ||
81 | #define _PAGE_BIT_RW 5 /* AP0-bit : write access allowed */ | ||
82 | #define _PAGE_BIT_USER 6 /* AP1-bit : user space access allowed */ | ||
83 | #define _PAGE_BIT_BUFFER 7 /* B-bit : bufferable */ | ||
84 | #define _PAGE_BIT_GLOBAL 8 /* G-bit : global (ignore ASID) */ | ||
85 | #define _PAGE_BIT_CACHABLE 9 /* C-bit : cachable */ | ||
86 | |||
87 | /* If we drop support for 1K pages, we get two extra bits */ | ||
88 | #define _PAGE_BIT_PRESENT 10 | ||
89 | #define _PAGE_BIT_ACCESSED 11 /* software: page was accessed */ | ||
90 | |||
91 | /* The following flags are only valid when !PRESENT */ | ||
92 | #define _PAGE_BIT_FILE 0 /* software: pagecache or swap? */ | ||
93 | |||
94 | #define _PAGE_WT (1 << _PAGE_BIT_WT) | ||
95 | #define _PAGE_DIRTY (1 << _PAGE_BIT_DIRTY) | ||
96 | #define _PAGE_EXECUTE (1 << _PAGE_BIT_EXECUTE) | ||
97 | #define _PAGE_RW (1 << _PAGE_BIT_RW) | ||
98 | #define _PAGE_USER (1 << _PAGE_BIT_USER) | ||
99 | #define _PAGE_BUFFER (1 << _PAGE_BIT_BUFFER) | ||
100 | #define _PAGE_GLOBAL (1 << _PAGE_BIT_GLOBAL) | ||
101 | #define _PAGE_CACHABLE (1 << _PAGE_BIT_CACHABLE) | ||
102 | |||
103 | /* Software flags */ | ||
104 | #define _PAGE_ACCESSED (1 << _PAGE_BIT_ACCESSED) | ||
105 | #define _PAGE_PRESENT (1 << _PAGE_BIT_PRESENT) | ||
106 | #define _PAGE_FILE (1 << _PAGE_BIT_FILE) | ||
107 | |||
108 | /* | ||
109 | * Page types, i.e. sizes. _PAGE_TYPE_NONE corresponds to what is | ||
110 | * usually called _PAGE_PROTNONE on other architectures. | ||
111 | * | ||
112 | * XXX: Find out if _PAGE_PROTNONE is equivalent with !_PAGE_USER. If | ||
113 | * so, we can encode all possible page sizes (although we can't really | ||
114 | * support 1K pages anyway due to the _PAGE_PRESENT and _PAGE_ACCESSED | ||
115 | * bits) | ||
116 | * | ||
117 | */ | ||
118 | #define _PAGE_TYPE_MASK ((1 << _PAGE_BIT_SZ0) | (1 << _PAGE_BIT_SZ1)) | ||
119 | #define _PAGE_TYPE_NONE (0 << _PAGE_BIT_SZ0) | ||
120 | #define _PAGE_TYPE_SMALL (1 << _PAGE_BIT_SZ0) | ||
121 | #define _PAGE_TYPE_MEDIUM (2 << _PAGE_BIT_SZ0) | ||
122 | #define _PAGE_TYPE_LARGE (3 << _PAGE_BIT_SZ0) | ||
123 | |||
124 | /* | ||
125 | * Mask which drop software flags. We currently can't handle more than | ||
126 | * 512 MiB of physical memory, so we can use bits 29-31 for other | ||
127 | * stuff. With a fixed 4K page size, we can use bits 10-11 as well as | ||
128 | * bits 2-3 (SZ) | ||
129 | */ | ||
130 | #define _PAGE_FLAGS_HARDWARE_MASK 0xfffff3ff | ||
131 | |||
132 | #define _PAGE_FLAGS_CACHE_MASK (_PAGE_CACHABLE | _PAGE_BUFFER | _PAGE_WT) | ||
133 | |||
134 | /* TODO: Check for saneness */ | ||
135 | /* User-mode page table flags (to be set in a pgd or pmd entry) */ | ||
136 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \ | ||
137 | | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
138 | /* Kernel-mode page table flags */ | ||
139 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_TYPE_SMALL | _PAGE_RW \ | ||
140 | | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
141 | /* Flags that may be modified by software */ | ||
142 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY \ | ||
143 | | _PAGE_FLAGS_CACHE_MASK) | ||
144 | |||
145 | #define _PAGE_FLAGS_READ (_PAGE_CACHABLE | _PAGE_BUFFER) | ||
146 | #define _PAGE_FLAGS_WRITE (_PAGE_FLAGS_READ | _PAGE_RW | _PAGE_DIRTY) | ||
147 | |||
148 | #define _PAGE_NORMAL(x) __pgprot((x) | _PAGE_PRESENT | _PAGE_TYPE_SMALL \ | ||
149 | | _PAGE_ACCESSED) | ||
150 | |||
151 | #define PAGE_NONE (_PAGE_ACCESSED | _PAGE_TYPE_NONE) | ||
152 | #define PAGE_READ (_PAGE_FLAGS_READ | _PAGE_USER) | ||
153 | #define PAGE_EXEC (_PAGE_FLAGS_READ | _PAGE_EXECUTE | _PAGE_USER) | ||
154 | #define PAGE_WRITE (_PAGE_FLAGS_WRITE | _PAGE_USER) | ||
155 | #define PAGE_KERNEL _PAGE_NORMAL(_PAGE_FLAGS_WRITE | _PAGE_EXECUTE | _PAGE_GLOBAL) | ||
156 | #define PAGE_KERNEL_RO _PAGE_NORMAL(_PAGE_FLAGS_READ | _PAGE_EXECUTE | _PAGE_GLOBAL) | ||
157 | |||
158 | #define _PAGE_P(x) _PAGE_NORMAL((x) & ~(_PAGE_RW | _PAGE_DIRTY)) | ||
159 | #define _PAGE_S(x) _PAGE_NORMAL(x) | ||
160 | |||
161 | #define PAGE_COPY _PAGE_P(PAGE_WRITE | PAGE_READ) | ||
162 | |||
163 | #ifndef __ASSEMBLY__ | ||
164 | /* | ||
165 | * The hardware supports flags for write- and execute access. Read is | ||
166 | * always allowed if the page is loaded into the TLB, so the "-w-", | ||
167 | * "--x" and "-wx" mappings are implemented as "rw-", "r-x" and "rwx", | ||
168 | * respectively. | ||
169 | * | ||
170 | * The "---" case is handled by software; the page will simply not be | ||
171 | * loaded into the TLB if the page type is _PAGE_TYPE_NONE. | ||
172 | */ | ||
173 | |||
174 | #define __P000 __pgprot(PAGE_NONE) | ||
175 | #define __P001 _PAGE_P(PAGE_READ) | ||
176 | #define __P010 _PAGE_P(PAGE_WRITE) | ||
177 | #define __P011 _PAGE_P(PAGE_WRITE | PAGE_READ) | ||
178 | #define __P100 _PAGE_P(PAGE_EXEC) | ||
179 | #define __P101 _PAGE_P(PAGE_EXEC | PAGE_READ) | ||
180 | #define __P110 _PAGE_P(PAGE_EXEC | PAGE_WRITE) | ||
181 | #define __P111 _PAGE_P(PAGE_EXEC | PAGE_WRITE | PAGE_READ) | ||
182 | |||
183 | #define __S000 __pgprot(PAGE_NONE) | ||
184 | #define __S001 _PAGE_S(PAGE_READ) | ||
185 | #define __S010 _PAGE_S(PAGE_WRITE) | ||
186 | #define __S011 _PAGE_S(PAGE_WRITE | PAGE_READ) | ||
187 | #define __S100 _PAGE_S(PAGE_EXEC) | ||
188 | #define __S101 _PAGE_S(PAGE_EXEC | PAGE_READ) | ||
189 | #define __S110 _PAGE_S(PAGE_EXEC | PAGE_WRITE) | ||
190 | #define __S111 _PAGE_S(PAGE_EXEC | PAGE_WRITE | PAGE_READ) | ||
191 | |||
192 | #define pte_none(x) (!pte_val(x)) | ||
193 | #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) | ||
194 | |||
195 | #define pte_clear(mm,addr,xp) \ | ||
196 | do { \ | ||
197 | set_pte_at(mm, addr, xp, __pte(0)); \ | ||
198 | } while (0) | ||
199 | |||
200 | /* | ||
201 | * The following only work if pte_present() is true. | ||
202 | * Undefined behaviour if not.. | ||
203 | */ | ||
204 | static inline int pte_read(pte_t pte) | ||
205 | { | ||
206 | return pte_val(pte) & _PAGE_USER; | ||
207 | } | ||
208 | static inline int pte_write(pte_t pte) | ||
209 | { | ||
210 | return pte_val(pte) & _PAGE_RW; | ||
211 | } | ||
212 | static inline int pte_exec(pte_t pte) | ||
213 | { | ||
214 | return pte_val(pte) & _PAGE_EXECUTE; | ||
215 | } | ||
216 | static inline int pte_dirty(pte_t pte) | ||
217 | { | ||
218 | return pte_val(pte) & _PAGE_DIRTY; | ||
219 | } | ||
220 | static inline int pte_young(pte_t pte) | ||
221 | { | ||
222 | return pte_val(pte) & _PAGE_ACCESSED; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * The following only work if pte_present() is not true. | ||
227 | */ | ||
228 | static inline int pte_file(pte_t pte) | ||
229 | { | ||
230 | return pte_val(pte) & _PAGE_FILE; | ||
231 | } | ||
232 | |||
233 | /* Mutator functions for PTE bits */ | ||
234 | static inline pte_t pte_rdprotect(pte_t pte) | ||
235 | { | ||
236 | set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); | ||
237 | return pte; | ||
238 | } | ||
239 | static inline pte_t pte_wrprotect(pte_t pte) | ||
240 | { | ||
241 | set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); | ||
242 | return pte; | ||
243 | } | ||
244 | static inline pte_t pte_exprotect(pte_t pte) | ||
245 | { | ||
246 | set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); | ||
247 | return pte; | ||
248 | } | ||
249 | static inline pte_t pte_mkclean(pte_t pte) | ||
250 | { | ||
251 | set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); | ||
252 | return pte; | ||
253 | } | ||
254 | static inline pte_t pte_mkold(pte_t pte) | ||
255 | { | ||
256 | set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); | ||
257 | return pte; | ||
258 | } | ||
259 | static inline pte_t pte_mkread(pte_t pte) | ||
260 | { | ||
261 | set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); | ||
262 | return pte; | ||
263 | } | ||
264 | static inline pte_t pte_mkwrite(pte_t pte) | ||
265 | { | ||
266 | set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); | ||
267 | return pte; | ||
268 | } | ||
269 | static inline pte_t pte_mkexec(pte_t pte) | ||
270 | { | ||
271 | set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); | ||
272 | return pte; | ||
273 | } | ||
274 | static inline pte_t pte_mkdirty(pte_t pte) | ||
275 | { | ||
276 | set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); | ||
277 | return pte; | ||
278 | } | ||
279 | static inline pte_t pte_mkyoung(pte_t pte) | ||
280 | { | ||
281 | set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); | ||
282 | return pte; | ||
283 | } | ||
284 | |||
285 | #define pmd_none(x) (!pmd_val(x)) | ||
286 | #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) | ||
287 | #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) | ||
288 | #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) \ | ||
289 | != _KERNPG_TABLE) | ||
290 | |||
291 | /* | ||
292 | * Permanent address of a page. We don't support highmem, so this is | ||
293 | * trivial. | ||
294 | */ | ||
295 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) | ||
296 | #define pte_page(x) phys_to_page(pte_val(x) & PTE_PHYS_MASK) | ||
297 | |||
298 | /* | ||
299 | * Mark the prot value as uncacheable and unbufferable | ||
300 | */ | ||
301 | #define pgprot_noncached(prot) \ | ||
302 | __pgprot(pgprot_val(prot) & ~(_PAGE_BUFFER | _PAGE_CACHABLE)) | ||
303 | |||
304 | /* | ||
305 | * Mark the prot value as uncacheable but bufferable | ||
306 | */ | ||
307 | #define pgprot_writecombine(prot) \ | ||
308 | __pgprot((pgprot_val(prot) & ~_PAGE_CACHABLE) | _PAGE_BUFFER) | ||
309 | |||
310 | /* | ||
311 | * Conversion functions: convert a page and protection to a page entry, | ||
312 | * and a page entry and page directory to the page they refer to. | ||
313 | * | ||
314 | * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) | ||
315 | */ | ||
316 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) | ||
317 | |||
318 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | ||
319 | { | ||
320 | set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | ||
321 | | pgprot_val(newprot))); | ||
322 | return pte; | ||
323 | } | ||
324 | |||
325 | #define page_pte(page) page_pte_prot(page, __pgprot(0)) | ||
326 | |||
327 | #define pmd_page_vaddr(pmd) \ | ||
328 | ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) | ||
329 | |||
330 | #define pmd_page(pmd) (phys_to_page(pmd_val(pmd))) | ||
331 | |||
332 | /* to find an entry in a page-table-directory. */ | ||
333 | #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) | ||
334 | #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) | ||
335 | #define pgd_offset_current(address) \ | ||
336 | ((pgd_t *)__mfsr(SYSREG_PTBR) + pgd_index(address)) | ||
337 | |||
338 | /* to find an entry in a kernel page-table-directory */ | ||
339 | #define pgd_offset_k(address) pgd_offset(&init_mm, address) | ||
340 | |||
341 | /* Find an entry in the third-level page table.. */ | ||
342 | #define pte_index(address) \ | ||
343 | ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||
344 | #define pte_offset(dir, address) \ | ||
345 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) | ||
346 | #define pte_offset_kernel(dir, address) \ | ||
347 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) | ||
348 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) | ||
349 | #define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) | ||
350 | #define pte_unmap(pte) do { } while (0) | ||
351 | #define pte_unmap_nested(pte) do { } while (0) | ||
352 | |||
353 | struct vm_area_struct; | ||
354 | extern void update_mmu_cache(struct vm_area_struct * vma, | ||
355 | unsigned long address, pte_t pte); | ||
356 | |||
357 | /* | ||
358 | * Encode and decode a swap entry | ||
359 | * | ||
360 | * Constraints: | ||
361 | * _PAGE_FILE at bit 0 | ||
362 | * _PAGE_TYPE_* at bits 2-3 (for emulating _PAGE_PROTNONE) | ||
363 | * _PAGE_PRESENT at bit 10 | ||
364 | * | ||
365 | * We encode the type into bits 4-9 and offset into bits 11-31. This | ||
366 | * gives us a 21 bits offset, or 2**21 * 4K = 8G usable swap space per | ||
367 | * device, and 64 possible types. | ||
368 | * | ||
369 | * NOTE: We should set ZEROs at the position of _PAGE_PRESENT | ||
370 | * and _PAGE_PROTNONE bits | ||
371 | */ | ||
372 | #define __swp_type(x) (((x).val >> 4) & 0x3f) | ||
373 | #define __swp_offset(x) ((x).val >> 11) | ||
374 | #define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 4) | ((offset) << 11) }) | ||
375 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | ||
376 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | ||
377 | |||
378 | /* | ||
379 | * Encode and decode a nonlinear file mapping entry. We have to | ||
380 | * preserve _PAGE_FILE and _PAGE_PRESENT here. _PAGE_TYPE_* isn't | ||
381 | * necessary, since _PAGE_FILE implies !_PAGE_PROTNONE (?) | ||
382 | */ | ||
383 | #define PTE_FILE_MAX_BITS 30 | ||
384 | #define pte_to_pgoff(pte) (((pte_val(pte) >> 1) & 0x1ff) \ | ||
385 | | ((pte_val(pte) >> 11) << 9)) | ||
386 | #define pgoff_to_pte(off) ((pte_t) { ((((off) & 0x1ff) << 1) \ | ||
387 | | (((off) >> 9) << 11) \ | ||
388 | | _PAGE_FILE) }) | ||
389 | |||
390 | typedef pte_t *pte_addr_t; | ||
391 | |||
392 | #define kern_addr_valid(addr) (1) | ||
393 | |||
394 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
395 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
396 | |||
397 | #define MK_IOSPACE_PFN(space, pfn) (pfn) | ||
398 | #define GET_IOSPACE(pfn) 0 | ||
399 | #define GET_PFN(pfn) (pfn) | ||
400 | |||
401 | /* No page table caches to initialize (?) */ | ||
402 | #define pgtable_cache_init() do { } while(0) | ||
403 | |||
404 | #include <asm-generic/pgtable.h> | ||
405 | |||
406 | #endif /* !__ASSEMBLY__ */ | ||
407 | |||
408 | #endif /* __ASM_AVR32_PGTABLE_H */ | ||
diff --git a/include/asm-avr32/poll.h b/include/asm-avr32/poll.h new file mode 100644 index 000000000000..736e29755dfc --- /dev/null +++ b/include/asm-avr32/poll.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __ASM_AVR32_POLL_H | ||
2 | #define __ASM_AVR32_POLL_H | ||
3 | |||
4 | /* These are specified by iBCS2 */ | ||
5 | #define POLLIN 0x0001 | ||
6 | #define POLLPRI 0x0002 | ||
7 | #define POLLOUT 0x0004 | ||
8 | #define POLLERR 0x0008 | ||
9 | #define POLLHUP 0x0010 | ||
10 | #define POLLNVAL 0x0020 | ||
11 | |||
12 | /* The rest seem to be more-or-less nonstandard. Check them! */ | ||
13 | #define POLLRDNORM 0x0040 | ||
14 | #define POLLRDBAND 0x0080 | ||
15 | #define POLLWRNORM 0x0100 | ||
16 | #define POLLWRBAND 0x0200 | ||
17 | #define POLLMSG 0x0400 | ||
18 | #define POLLREMOVE 0x1000 | ||
19 | #define POLLRDHUP 0x2000 | ||
20 | |||
21 | struct pollfd { | ||
22 | int fd; | ||
23 | short events; | ||
24 | short revents; | ||
25 | }; | ||
26 | |||
27 | #endif /* __ASM_AVR32_POLL_H */ | ||
diff --git a/include/asm-avr32/posix_types.h b/include/asm-avr32/posix_types.h new file mode 100644 index 000000000000..2831b039b349 --- /dev/null +++ b/include/asm-avr32/posix_types.h | |||
@@ -0,0 +1,129 @@ | |||
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 | #ifndef __ASM_AVR32_POSIX_TYPES_H | ||
9 | #define __ASM_AVR32_POSIX_TYPES_H | ||
10 | |||
11 | /* | ||
12 | * This file is generally used by user-level software, so you need to | ||
13 | * be a little careful about namespace pollution etc. Also, we cannot | ||
14 | * assume GCC is being used. | ||
15 | */ | ||
16 | |||
17 | typedef unsigned long __kernel_ino_t; | ||
18 | typedef unsigned short __kernel_mode_t; | ||
19 | typedef unsigned short __kernel_nlink_t; | ||
20 | typedef long __kernel_off_t; | ||
21 | typedef int __kernel_pid_t; | ||
22 | typedef unsigned short __kernel_ipc_pid_t; | ||
23 | typedef unsigned int __kernel_uid_t; | ||
24 | typedef unsigned int __kernel_gid_t; | ||
25 | typedef unsigned long __kernel_size_t; | ||
26 | typedef int __kernel_ssize_t; | ||
27 | typedef int __kernel_ptrdiff_t; | ||
28 | typedef long __kernel_time_t; | ||
29 | typedef long __kernel_suseconds_t; | ||
30 | typedef long __kernel_clock_t; | ||
31 | typedef int __kernel_timer_t; | ||
32 | typedef int __kernel_clockid_t; | ||
33 | typedef int __kernel_daddr_t; | ||
34 | typedef char * __kernel_caddr_t; | ||
35 | typedef unsigned short __kernel_uid16_t; | ||
36 | typedef unsigned short __kernel_gid16_t; | ||
37 | typedef unsigned int __kernel_uid32_t; | ||
38 | typedef unsigned int __kernel_gid32_t; | ||
39 | |||
40 | typedef unsigned short __kernel_old_uid_t; | ||
41 | typedef unsigned short __kernel_old_gid_t; | ||
42 | typedef unsigned short __kernel_old_dev_t; | ||
43 | |||
44 | #ifdef __GNUC__ | ||
45 | typedef long long __kernel_loff_t; | ||
46 | #endif | ||
47 | |||
48 | typedef struct { | ||
49 | #if defined(__KERNEL__) || defined(__USE_ALL) | ||
50 | int val[2]; | ||
51 | #else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ | ||
52 | int __val[2]; | ||
53 | #endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ | ||
54 | } __kernel_fsid_t; | ||
55 | |||
56 | #if defined(__KERNEL__) | ||
57 | |||
58 | #undef __FD_SET | ||
59 | static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) | ||
60 | { | ||
61 | unsigned long __tmp = __fd / __NFDBITS; | ||
62 | unsigned long __rem = __fd % __NFDBITS; | ||
63 | __fdsetp->fds_bits[__tmp] |= (1UL<<__rem); | ||
64 | } | ||
65 | |||
66 | #undef __FD_CLR | ||
67 | static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) | ||
68 | { | ||
69 | unsigned long __tmp = __fd / __NFDBITS; | ||
70 | unsigned long __rem = __fd % __NFDBITS; | ||
71 | __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); | ||
72 | } | ||
73 | |||
74 | |||
75 | #undef __FD_ISSET | ||
76 | static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) | ||
77 | { | ||
78 | unsigned long __tmp = __fd / __NFDBITS; | ||
79 | unsigned long __rem = __fd % __NFDBITS; | ||
80 | return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * This will unroll the loop for the normal constant case (8 ints, | ||
85 | * for a 256-bit fd_set) | ||
86 | */ | ||
87 | #undef __FD_ZERO | ||
88 | static __inline__ void __FD_ZERO(__kernel_fd_set *__p) | ||
89 | { | ||
90 | unsigned long *__tmp = __p->fds_bits; | ||
91 | int __i; | ||
92 | |||
93 | if (__builtin_constant_p(__FDSET_LONGS)) { | ||
94 | switch (__FDSET_LONGS) { | ||
95 | case 16: | ||
96 | __tmp[ 0] = 0; __tmp[ 1] = 0; | ||
97 | __tmp[ 2] = 0; __tmp[ 3] = 0; | ||
98 | __tmp[ 4] = 0; __tmp[ 5] = 0; | ||
99 | __tmp[ 6] = 0; __tmp[ 7] = 0; | ||
100 | __tmp[ 8] = 0; __tmp[ 9] = 0; | ||
101 | __tmp[10] = 0; __tmp[11] = 0; | ||
102 | __tmp[12] = 0; __tmp[13] = 0; | ||
103 | __tmp[14] = 0; __tmp[15] = 0; | ||
104 | return; | ||
105 | |||
106 | case 8: | ||
107 | __tmp[ 0] = 0; __tmp[ 1] = 0; | ||
108 | __tmp[ 2] = 0; __tmp[ 3] = 0; | ||
109 | __tmp[ 4] = 0; __tmp[ 5] = 0; | ||
110 | __tmp[ 6] = 0; __tmp[ 7] = 0; | ||
111 | return; | ||
112 | |||
113 | case 4: | ||
114 | __tmp[ 0] = 0; __tmp[ 1] = 0; | ||
115 | __tmp[ 2] = 0; __tmp[ 3] = 0; | ||
116 | return; | ||
117 | } | ||
118 | } | ||
119 | __i = __FDSET_LONGS; | ||
120 | while (__i) { | ||
121 | __i--; | ||
122 | *__tmp = 0; | ||
123 | __tmp++; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | #endif /* defined(__KERNEL__) */ | ||
128 | |||
129 | #endif /* __ASM_AVR32_POSIX_TYPES_H */ | ||
diff --git a/include/asm-avr32/processor.h b/include/asm-avr32/processor.h new file mode 100644 index 000000000000..f6913778a45f --- /dev/null +++ b/include/asm-avr32/processor.h | |||
@@ -0,0 +1,147 @@ | |||
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 | #ifndef __ASM_AVR32_PROCESSOR_H | ||
9 | #define __ASM_AVR32_PROCESSOR_H | ||
10 | |||
11 | #include <asm/page.h> | ||
12 | #include <asm/cache.h> | ||
13 | |||
14 | #define TASK_SIZE 0x80000000 | ||
15 | |||
16 | #ifndef __ASSEMBLY__ | ||
17 | |||
18 | static inline void *current_text_addr(void) | ||
19 | { | ||
20 | register void *pc asm("pc"); | ||
21 | return pc; | ||
22 | } | ||
23 | |||
24 | enum arch_type { | ||
25 | ARCH_AVR32A, | ||
26 | ARCH_AVR32B, | ||
27 | ARCH_MAX | ||
28 | }; | ||
29 | |||
30 | enum cpu_type { | ||
31 | CPU_MORGAN, | ||
32 | CPU_AT32AP, | ||
33 | CPU_MAX | ||
34 | }; | ||
35 | |||
36 | enum tlb_config { | ||
37 | TLB_NONE, | ||
38 | TLB_SPLIT, | ||
39 | TLB_UNIFIED, | ||
40 | TLB_INVALID | ||
41 | }; | ||
42 | |||
43 | struct avr32_cpuinfo { | ||
44 | struct clk *clk; | ||
45 | unsigned long loops_per_jiffy; | ||
46 | enum arch_type arch_type; | ||
47 | enum cpu_type cpu_type; | ||
48 | unsigned short arch_revision; | ||
49 | unsigned short cpu_revision; | ||
50 | enum tlb_config tlb_config; | ||
51 | |||
52 | struct cache_info icache; | ||
53 | struct cache_info dcache; | ||
54 | }; | ||
55 | |||
56 | extern struct avr32_cpuinfo boot_cpu_data; | ||
57 | |||
58 | #ifdef CONFIG_SMP | ||
59 | extern struct avr32_cpuinfo cpu_data[]; | ||
60 | #define current_cpu_data cpu_data[smp_processor_id()] | ||
61 | #else | ||
62 | #define cpu_data (&boot_cpu_data) | ||
63 | #define current_cpu_data boot_cpu_data | ||
64 | #endif | ||
65 | |||
66 | /* This decides where the kernel will search for a free chunk of vm | ||
67 | * space during mmap's | ||
68 | */ | ||
69 | #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) | ||
70 | |||
71 | #define cpu_relax() barrier() | ||
72 | #define cpu_sync_pipeline() asm volatile("sub pc, -2" : : : "memory") | ||
73 | |||
74 | struct cpu_context { | ||
75 | unsigned long sr; | ||
76 | unsigned long pc; | ||
77 | unsigned long ksp; /* Kernel stack pointer */ | ||
78 | unsigned long r7; | ||
79 | unsigned long r6; | ||
80 | unsigned long r5; | ||
81 | unsigned long r4; | ||
82 | unsigned long r3; | ||
83 | unsigned long r2; | ||
84 | unsigned long r1; | ||
85 | unsigned long r0; | ||
86 | }; | ||
87 | |||
88 | /* This struct contains the CPU context as stored by switch_to() */ | ||
89 | struct thread_struct { | ||
90 | struct cpu_context cpu_context; | ||
91 | unsigned long single_step_addr; | ||
92 | u16 single_step_insn; | ||
93 | }; | ||
94 | |||
95 | #define INIT_THREAD { \ | ||
96 | .cpu_context = { \ | ||
97 | .ksp = sizeof(init_stack) + (long)&init_stack, \ | ||
98 | }, \ | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Do necessary setup to start up a newly executed thread. | ||
103 | */ | ||
104 | #define start_thread(regs, new_pc, new_sp) \ | ||
105 | do { \ | ||
106 | set_fs(USER_DS); \ | ||
107 | memset(regs, 0, sizeof(*regs)); \ | ||
108 | regs->sr = MODE_USER; \ | ||
109 | regs->pc = new_pc & ~1; \ | ||
110 | regs->sp = new_sp; \ | ||
111 | } while(0) | ||
112 | |||
113 | struct task_struct; | ||
114 | |||
115 | /* Free all resources held by a thread */ | ||
116 | extern void release_thread(struct task_struct *); | ||
117 | |||
118 | /* Create a kernel thread without removing it from tasklists */ | ||
119 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
120 | |||
121 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
122 | #define prepare_to_copy(tsk) do { } while(0) | ||
123 | |||
124 | /* Return saved PC of a blocked thread */ | ||
125 | #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) | ||
126 | |||
127 | struct pt_regs; | ||
128 | void show_trace(struct task_struct *task, unsigned long *stack, | ||
129 | struct pt_regs *regs); | ||
130 | |||
131 | extern unsigned long get_wchan(struct task_struct *p); | ||
132 | |||
133 | #define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc) | ||
134 | #define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp) | ||
135 | |||
136 | #define ARCH_HAS_PREFETCH | ||
137 | |||
138 | static inline void prefetch(const void *x) | ||
139 | { | ||
140 | const char *c = x; | ||
141 | asm volatile("pref %0" : : "r"(c)); | ||
142 | } | ||
143 | #define PREFETCH_STRIDE L1_CACHE_BYTES | ||
144 | |||
145 | #endif /* __ASSEMBLY__ */ | ||
146 | |||
147 | #endif /* __ASM_AVR32_PROCESSOR_H */ | ||
diff --git a/include/asm-avr32/ptrace.h b/include/asm-avr32/ptrace.h new file mode 100644 index 000000000000..60f0f19a81f1 --- /dev/null +++ b/include/asm-avr32/ptrace.h | |||
@@ -0,0 +1,154 @@ | |||
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 | #ifndef __ASM_AVR32_PTRACE_H | ||
9 | #define __ASM_AVR32_PTRACE_H | ||
10 | |||
11 | #define PTRACE_GETREGS 12 | ||
12 | #define PTRACE_SETREGS 13 | ||
13 | |||
14 | /* | ||
15 | * Status Register bits | ||
16 | */ | ||
17 | #define SR_H 0x40000000 | ||
18 | #define SR_R 0x20000000 | ||
19 | #define SR_J 0x10000000 | ||
20 | #define SR_DM 0x08000000 | ||
21 | #define SR_D 0x04000000 | ||
22 | #define MODE_NMI 0x01c00000 | ||
23 | #define MODE_EXCEPTION 0x01800000 | ||
24 | #define MODE_INT3 0x01400000 | ||
25 | #define MODE_INT2 0x01000000 | ||
26 | #define MODE_INT1 0x00c00000 | ||
27 | #define MODE_INT0 0x00800000 | ||
28 | #define MODE_SUPERVISOR 0x00400000 | ||
29 | #define MODE_USER 0x00000000 | ||
30 | #define MODE_MASK 0x01c00000 | ||
31 | #define SR_EM 0x00200000 | ||
32 | #define SR_I3M 0x00100000 | ||
33 | #define SR_I2M 0x00080000 | ||
34 | #define SR_I1M 0x00040000 | ||
35 | #define SR_I0M 0x00020000 | ||
36 | #define SR_GM 0x00010000 | ||
37 | |||
38 | #define SR_H_BIT 30 | ||
39 | #define SR_R_BIT 29 | ||
40 | #define SR_J_BIT 28 | ||
41 | #define SR_DM_BIT 27 | ||
42 | #define SR_D_BIT 26 | ||
43 | #define MODE_SHIFT 22 | ||
44 | #define SR_EM_BIT 21 | ||
45 | #define SR_I3M_BIT 20 | ||
46 | #define SR_I2M_BIT 19 | ||
47 | #define SR_I1M_BIT 18 | ||
48 | #define SR_I0M_BIT 17 | ||
49 | #define SR_GM_BIT 16 | ||
50 | |||
51 | /* The user-visible part */ | ||
52 | #define SR_L 0x00000020 | ||
53 | #define SR_Q 0x00000010 | ||
54 | #define SR_V 0x00000008 | ||
55 | #define SR_N 0x00000004 | ||
56 | #define SR_Z 0x00000002 | ||
57 | #define SR_C 0x00000001 | ||
58 | |||
59 | #define SR_L_BIT 5 | ||
60 | #define SR_Q_BIT 4 | ||
61 | #define SR_V_BIT 3 | ||
62 | #define SR_N_BIT 2 | ||
63 | #define SR_Z_BIT 1 | ||
64 | #define SR_C_BIT 0 | ||
65 | |||
66 | /* | ||
67 | * The order is defined by the stmts instruction. r0 is stored first, | ||
68 | * so it gets the highest address. | ||
69 | * | ||
70 | * Registers 0-12 are general-purpose registers (r12 is normally used for | ||
71 | * the function return value). | ||
72 | * Register 13 is the stack pointer | ||
73 | * Register 14 is the link register | ||
74 | * Register 15 is the program counter (retrieved from the RAR sysreg) | ||
75 | */ | ||
76 | #define FRAME_SIZE_FULL 72 | ||
77 | #define REG_R12_ORIG 68 | ||
78 | #define REG_R0 64 | ||
79 | #define REG_R1 60 | ||
80 | #define REG_R2 56 | ||
81 | #define REG_R3 52 | ||
82 | #define REG_R4 48 | ||
83 | #define REG_R5 44 | ||
84 | #define REG_R6 40 | ||
85 | #define REG_R7 36 | ||
86 | #define REG_R8 32 | ||
87 | #define REG_R9 28 | ||
88 | #define REG_R10 24 | ||
89 | #define REG_R11 20 | ||
90 | #define REG_R12 16 | ||
91 | #define REG_SP 12 | ||
92 | #define REG_LR 8 | ||
93 | |||
94 | #define FRAME_SIZE_MIN 8 | ||
95 | #define REG_PC 4 | ||
96 | #define REG_SR 0 | ||
97 | |||
98 | #ifndef __ASSEMBLY__ | ||
99 | struct pt_regs { | ||
100 | /* These are always saved */ | ||
101 | unsigned long sr; | ||
102 | unsigned long pc; | ||
103 | |||
104 | /* These are sometimes saved */ | ||
105 | unsigned long lr; | ||
106 | unsigned long sp; | ||
107 | unsigned long r12; | ||
108 | unsigned long r11; | ||
109 | unsigned long r10; | ||
110 | unsigned long r9; | ||
111 | unsigned long r8; | ||
112 | unsigned long r7; | ||
113 | unsigned long r6; | ||
114 | unsigned long r5; | ||
115 | unsigned long r4; | ||
116 | unsigned long r3; | ||
117 | unsigned long r2; | ||
118 | unsigned long r1; | ||
119 | unsigned long r0; | ||
120 | |||
121 | /* Only saved on system call */ | ||
122 | unsigned long r12_orig; | ||
123 | }; | ||
124 | |||
125 | #ifdef __KERNEL__ | ||
126 | # define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER) | ||
127 | extern void show_regs (struct pt_regs *); | ||
128 | |||
129 | static __inline__ int valid_user_regs(struct pt_regs *regs) | ||
130 | { | ||
131 | /* | ||
132 | * Some of the Java bits might be acceptable if/when we | ||
133 | * implement some support for that stuff... | ||
134 | */ | ||
135 | if ((regs->sr & 0xffff0000) == 0) | ||
136 | return 1; | ||
137 | |||
138 | /* | ||
139 | * Force status register flags to be sane and report this | ||
140 | * illegal behaviour... | ||
141 | */ | ||
142 | regs->sr &= 0x0000ffff; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | #define instruction_pointer(regs) ((regs)->pc) | ||
147 | |||
148 | #define profile_pc(regs) instruction_pointer(regs) | ||
149 | |||
150 | #endif /* __KERNEL__ */ | ||
151 | |||
152 | #endif /* ! __ASSEMBLY__ */ | ||
153 | |||
154 | #endif /* __ASM_AVR32_PTRACE_H */ | ||
diff --git a/include/asm-avr32/resource.h b/include/asm-avr32/resource.h new file mode 100644 index 000000000000..c6dd101472b1 --- /dev/null +++ b/include/asm-avr32/resource.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_RESOURCE_H | ||
2 | #define __ASM_AVR32_RESOURCE_H | ||
3 | |||
4 | #include <asm-generic/resource.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_RESOURCE_H */ | ||
diff --git a/include/asm-avr32/scatterlist.h b/include/asm-avr32/scatterlist.h new file mode 100644 index 000000000000..bfe7d753423c --- /dev/null +++ b/include/asm-avr32/scatterlist.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef __ASM_AVR32_SCATTERLIST_H | ||
2 | #define __ASM_AVR32_SCATTERLIST_H | ||
3 | |||
4 | struct scatterlist { | ||
5 | struct page *page; | ||
6 | unsigned int offset; | ||
7 | dma_addr_t dma_address; | ||
8 | unsigned int length; | ||
9 | }; | ||
10 | |||
11 | /* These macros should be used after a pci_map_sg call has been done | ||
12 | * to get bus addresses of each of the SG entries and their lengths. | ||
13 | * You should only work with the number of sg entries pci_map_sg | ||
14 | * returns. | ||
15 | */ | ||
16 | #define sg_dma_address(sg) ((sg)->dma_address) | ||
17 | #define sg_dma_len(sg) ((sg)->length) | ||
18 | |||
19 | #define ISA_DMA_THRESHOLD (0xffffffff) | ||
20 | |||
21 | #endif /* __ASM_AVR32_SCATTERLIST_H */ | ||
diff --git a/include/asm-avr32/sections.h b/include/asm-avr32/sections.h new file mode 100644 index 000000000000..aa14252e4181 --- /dev/null +++ b/include/asm-avr32/sections.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_SECTIONS_H | ||
2 | #define __ASM_AVR32_SECTIONS_H | ||
3 | |||
4 | #include <asm-generic/sections.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_SECTIONS_H */ | ||
diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h new file mode 100644 index 000000000000..ef99ddccc10c --- /dev/null +++ b/include/asm-avr32/semaphore.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * SMP- and interrupt-safe semaphores. | ||
3 | * | ||
4 | * Copyright (C) 2006 Atmel Corporation | ||
5 | * | ||
6 | * Based on include/asm-i386/semaphore.h | ||
7 | * Copyright (C) 1996 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 | #ifndef __ASM_AVR32_SEMAPHORE_H | ||
14 | #define __ASM_AVR32_SEMAPHORE_H | ||
15 | |||
16 | #include <linux/linkage.h> | ||
17 | |||
18 | #include <asm/system.h> | ||
19 | #include <asm/atomic.h> | ||
20 | #include <linux/wait.h> | ||
21 | #include <linux/rwsem.h> | ||
22 | |||
23 | struct semaphore { | ||
24 | atomic_t count; | ||
25 | int sleepers; | ||
26 | wait_queue_head_t wait; | ||
27 | }; | ||
28 | |||
29 | #define __SEMAPHORE_INITIALIZER(name, n) \ | ||
30 | { \ | ||
31 | .count = ATOMIC_INIT(n), \ | ||
32 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ | ||
33 | } | ||
34 | |||
35 | #define __DECLARE_SEMAPHORE_GENERIC(name,count) \ | ||
36 | struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) | ||
37 | |||
38 | #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) | ||
39 | #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) | ||
40 | |||
41 | static inline void sema_init (struct semaphore *sem, int val) | ||
42 | { | ||
43 | atomic_set(&sem->count, val); | ||
44 | sem->sleepers = 0; | ||
45 | init_waitqueue_head(&sem->wait); | ||
46 | } | ||
47 | |||
48 | static inline void init_MUTEX (struct semaphore *sem) | ||
49 | { | ||
50 | sema_init(sem, 1); | ||
51 | } | ||
52 | |||
53 | static inline void init_MUTEX_LOCKED (struct semaphore *sem) | ||
54 | { | ||
55 | sema_init(sem, 0); | ||
56 | } | ||
57 | |||
58 | void __down(struct semaphore * sem); | ||
59 | int __down_interruptible(struct semaphore * sem); | ||
60 | void __up(struct semaphore * sem); | ||
61 | |||
62 | /* | ||
63 | * This is ugly, but we want the default case to fall through. | ||
64 | * "__down_failed" is a special asm handler that calls the C | ||
65 | * routine that actually waits. See arch/i386/kernel/semaphore.c | ||
66 | */ | ||
67 | static inline void down(struct semaphore * sem) | ||
68 | { | ||
69 | might_sleep(); | ||
70 | if (unlikely(atomic_dec_return (&sem->count) < 0)) | ||
71 | __down (sem); | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Interruptible try to acquire a semaphore. If we obtained | ||
76 | * it, return zero. If we were interrupted, returns -EINTR | ||
77 | */ | ||
78 | static inline int down_interruptible(struct semaphore * sem) | ||
79 | { | ||
80 | int ret = 0; | ||
81 | |||
82 | might_sleep(); | ||
83 | if (unlikely(atomic_dec_return (&sem->count) < 0)) | ||
84 | ret = __down_interruptible (sem); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Non-blockingly attempt to down() a semaphore. | ||
90 | * Returns zero if we acquired it | ||
91 | */ | ||
92 | static inline int down_trylock(struct semaphore * sem) | ||
93 | { | ||
94 | return atomic_dec_if_positive(&sem->count) < 0; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Note! This is subtle. We jump to wake people up only if | ||
99 | * the semaphore was negative (== somebody was waiting on it). | ||
100 | * The default case (no contention) will result in NO | ||
101 | * jumps for both down() and up(). | ||
102 | */ | ||
103 | static inline void up(struct semaphore * sem) | ||
104 | { | ||
105 | if (unlikely(atomic_inc_return (&sem->count) <= 0)) | ||
106 | __up (sem); | ||
107 | } | ||
108 | |||
109 | #endif /*__ASM_AVR32_SEMAPHORE_H */ | ||
diff --git a/include/asm-avr32/sembuf.h b/include/asm-avr32/sembuf.h new file mode 100644 index 000000000000..e472216e0c97 --- /dev/null +++ b/include/asm-avr32/sembuf.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __ASM_AVR32_SEMBUF_H | ||
2 | #define __ASM_AVR32_SEMBUF_H | ||
3 | |||
4 | /* | ||
5 | * The semid64_ds structure for AVR32 architecture. | ||
6 | * Note extra padding because this structure is passed back and forth | ||
7 | * between kernel and user space. | ||
8 | * | ||
9 | * Pad space is left for: | ||
10 | * - 64-bit time_t to solve y2038 problem | ||
11 | * - 2 miscellaneous 32-bit values | ||
12 | */ | ||
13 | |||
14 | struct semid64_ds { | ||
15 | struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ | ||
16 | __kernel_time_t sem_otime; /* last semop time */ | ||
17 | unsigned long __unused1; | ||
18 | __kernel_time_t sem_ctime; /* last change time */ | ||
19 | unsigned long __unused2; | ||
20 | unsigned long sem_nsems; /* no. of semaphores in array */ | ||
21 | unsigned long __unused3; | ||
22 | unsigned long __unused4; | ||
23 | }; | ||
24 | |||
25 | #endif /* __ASM_AVR32_SEMBUF_H */ | ||
diff --git a/include/asm-avr32/setup.h b/include/asm-avr32/setup.h new file mode 100644 index 000000000000..10193da4113b --- /dev/null +++ b/include/asm-avr32/setup.h | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * Based on linux/include/asm-arm/setup.h | ||
5 | * Copyright (C) 1997-1999 Russel 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 | #ifndef __ASM_AVR32_SETUP_H__ | ||
12 | #define __ASM_AVR32_SETUP_H__ | ||
13 | |||
14 | #define COMMAND_LINE_SIZE 256 | ||
15 | |||
16 | /* Magic number indicating that a tag table is present */ | ||
17 | #define ATAG_MAGIC 0xa2a25441 | ||
18 | |||
19 | #ifndef __ASSEMBLY__ | ||
20 | |||
21 | /* | ||
22 | * Generic memory range, used by several tags. | ||
23 | * | ||
24 | * addr is always physical. | ||
25 | * size is measured in bytes. | ||
26 | * next is for use by the OS, e.g. for grouping regions into | ||
27 | * linked lists. | ||
28 | */ | ||
29 | struct tag_mem_range { | ||
30 | u32 addr; | ||
31 | u32 size; | ||
32 | struct tag_mem_range * next; | ||
33 | }; | ||
34 | |||
35 | /* The list ends with an ATAG_NONE node. */ | ||
36 | #define ATAG_NONE 0x00000000 | ||
37 | |||
38 | struct tag_header { | ||
39 | u32 size; | ||
40 | u32 tag; | ||
41 | }; | ||
42 | |||
43 | /* The list must start with an ATAG_CORE node */ | ||
44 | #define ATAG_CORE 0x54410001 | ||
45 | |||
46 | struct tag_core { | ||
47 | u32 flags; | ||
48 | u32 pagesize; | ||
49 | u32 rootdev; | ||
50 | }; | ||
51 | |||
52 | /* it is allowed to have multiple ATAG_MEM nodes */ | ||
53 | #define ATAG_MEM 0x54410002 | ||
54 | /* ATAG_MEM uses tag_mem_range */ | ||
55 | |||
56 | /* command line: \0 terminated string */ | ||
57 | #define ATAG_CMDLINE 0x54410003 | ||
58 | |||
59 | struct tag_cmdline { | ||
60 | char cmdline[1]; /* this is the minimum size */ | ||
61 | }; | ||
62 | |||
63 | /* Ramdisk image (may be compressed) */ | ||
64 | #define ATAG_RDIMG 0x54410004 | ||
65 | /* ATAG_RDIMG uses tag_mem_range */ | ||
66 | |||
67 | /* Information about various clocks present in the system */ | ||
68 | #define ATAG_CLOCK 0x54410005 | ||
69 | |||
70 | struct tag_clock { | ||
71 | u32 clock_id; /* Which clock are we talking about? */ | ||
72 | u32 clock_flags; /* Special features */ | ||
73 | u64 clock_hz; /* Clock speed in Hz */ | ||
74 | }; | ||
75 | |||
76 | /* The clock types we know about */ | ||
77 | #define CLOCK_BOOTCPU 0 | ||
78 | |||
79 | /* Memory reserved for the system (e.g. the bootloader) */ | ||
80 | #define ATAG_RSVD_MEM 0x54410006 | ||
81 | /* ATAG_RSVD_MEM uses tag_mem_range */ | ||
82 | |||
83 | /* Ethernet information */ | ||
84 | |||
85 | #define ATAG_ETHERNET 0x54410007 | ||
86 | |||
87 | struct tag_ethernet { | ||
88 | u8 mac_index; | ||
89 | u8 mii_phy_addr; | ||
90 | u8 hw_address[6]; | ||
91 | }; | ||
92 | |||
93 | #define ETH_INVALID_PHY 0xff | ||
94 | |||
95 | struct tag { | ||
96 | struct tag_header hdr; | ||
97 | union { | ||
98 | struct tag_core core; | ||
99 | struct tag_mem_range mem_range; | ||
100 | struct tag_cmdline cmdline; | ||
101 | struct tag_clock clock; | ||
102 | struct tag_ethernet ethernet; | ||
103 | } u; | ||
104 | }; | ||
105 | |||
106 | struct tagtable { | ||
107 | u32 tag; | ||
108 | int (*parse)(struct tag *); | ||
109 | }; | ||
110 | |||
111 | #define __tag __attribute_used__ __attribute__((__section__(".taglist"))) | ||
112 | #define __tagtable(tag, fn) \ | ||
113 | static struct tagtable __tagtable_##fn __tag = { tag, fn } | ||
114 | |||
115 | #define tag_member_present(tag,member) \ | ||
116 | ((unsigned long)(&((struct tag *)0L)->member + 1) \ | ||
117 | <= (tag)->hdr.size * 4) | ||
118 | |||
119 | #define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) | ||
120 | #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) | ||
121 | |||
122 | #define for_each_tag(t,base) \ | ||
123 | for (t = base; t->hdr.size; t = tag_next(t)) | ||
124 | |||
125 | extern struct tag_mem_range *mem_phys; | ||
126 | extern struct tag_mem_range *mem_reserved; | ||
127 | extern struct tag_mem_range *mem_ramdisk; | ||
128 | |||
129 | extern struct tag *bootloader_tags; | ||
130 | |||
131 | extern void setup_bootmem(void); | ||
132 | extern void setup_processor(void); | ||
133 | extern void board_setup_fbmem(unsigned long fbmem_start, | ||
134 | unsigned long fbmem_size); | ||
135 | |||
136 | /* Chip-specific hook to enable the use of SDRAM */ | ||
137 | void chip_enable_sdram(void); | ||
138 | |||
139 | #endif /* !__ASSEMBLY__ */ | ||
140 | |||
141 | #endif /* __ASM_AVR32_SETUP_H__ */ | ||
diff --git a/include/asm-avr32/shmbuf.h b/include/asm-avr32/shmbuf.h new file mode 100644 index 000000000000..c62fba41739a --- /dev/null +++ b/include/asm-avr32/shmbuf.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef __ASM_AVR32_SHMBUF_H | ||
2 | #define __ASM_AVR32_SHMBUF_H | ||
3 | |||
4 | /* | ||
5 | * The shmid64_ds structure for i386 architecture. | ||
6 | * Note extra padding because this structure is passed back and forth | ||
7 | * between kernel and user space. | ||
8 | * | ||
9 | * Pad space is left for: | ||
10 | * - 64-bit time_t to solve y2038 problem | ||
11 | * - 2 miscellaneous 32-bit values | ||
12 | */ | ||
13 | |||
14 | struct shmid64_ds { | ||
15 | struct ipc64_perm shm_perm; /* operation perms */ | ||
16 | size_t shm_segsz; /* size of segment (bytes) */ | ||
17 | __kernel_time_t shm_atime; /* last attach time */ | ||
18 | unsigned long __unused1; | ||
19 | __kernel_time_t shm_dtime; /* last detach time */ | ||
20 | unsigned long __unused2; | ||
21 | __kernel_time_t shm_ctime; /* last change time */ | ||
22 | unsigned long __unused3; | ||
23 | __kernel_pid_t shm_cpid; /* pid of creator */ | ||
24 | __kernel_pid_t shm_lpid; /* pid of last operator */ | ||
25 | unsigned long shm_nattch; /* no. of current attaches */ | ||
26 | unsigned long __unused4; | ||
27 | unsigned long __unused5; | ||
28 | }; | ||
29 | |||
30 | struct shminfo64 { | ||
31 | unsigned long shmmax; | ||
32 | unsigned long shmmin; | ||
33 | unsigned long shmmni; | ||
34 | unsigned long shmseg; | ||
35 | unsigned long shmall; | ||
36 | unsigned long __unused1; | ||
37 | unsigned long __unused2; | ||
38 | unsigned long __unused3; | ||
39 | unsigned long __unused4; | ||
40 | }; | ||
41 | |||
42 | #endif /* __ASM_AVR32_SHMBUF_H */ | ||
diff --git a/include/asm-avr32/shmparam.h b/include/asm-avr32/shmparam.h new file mode 100644 index 000000000000..3681266c77f7 --- /dev/null +++ b/include/asm-avr32/shmparam.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_SHMPARAM_H | ||
2 | #define __ASM_AVR32_SHMPARAM_H | ||
3 | |||
4 | #define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ | ||
5 | |||
6 | #endif /* __ASM_AVR32_SHMPARAM_H */ | ||
diff --git a/include/asm-avr32/sigcontext.h b/include/asm-avr32/sigcontext.h new file mode 100644 index 000000000000..e04062b5f39f --- /dev/null +++ b/include/asm-avr32/sigcontext.h | |||
@@ -0,0 +1,34 @@ | |||
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 | #ifndef __ASM_AVR32_SIGCONTEXT_H | ||
9 | #define __ASM_AVR32_SIGCONTEXT_H | ||
10 | |||
11 | struct sigcontext { | ||
12 | unsigned long oldmask; | ||
13 | |||
14 | /* CPU registers */ | ||
15 | unsigned long sr; | ||
16 | unsigned long pc; | ||
17 | unsigned long lr; | ||
18 | unsigned long sp; | ||
19 | unsigned long r12; | ||
20 | unsigned long r11; | ||
21 | unsigned long r10; | ||
22 | unsigned long r9; | ||
23 | unsigned long r8; | ||
24 | unsigned long r7; | ||
25 | unsigned long r6; | ||
26 | unsigned long r5; | ||
27 | unsigned long r4; | ||
28 | unsigned long r3; | ||
29 | unsigned long r2; | ||
30 | unsigned long r1; | ||
31 | unsigned long r0; | ||
32 | }; | ||
33 | |||
34 | #endif /* __ASM_AVR32_SIGCONTEXT_H */ | ||
diff --git a/include/asm-avr32/siginfo.h b/include/asm-avr32/siginfo.h new file mode 100644 index 000000000000..5ee93f40a8a8 --- /dev/null +++ b/include/asm-avr32/siginfo.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _AVR32_SIGINFO_H | ||
2 | #define _AVR32_SIGINFO_H | ||
3 | |||
4 | #include <asm-generic/siginfo.h> | ||
5 | |||
6 | #endif | ||
diff --git a/include/asm-avr32/signal.h b/include/asm-avr32/signal.h new file mode 100644 index 000000000000..caffefeeba1f --- /dev/null +++ b/include/asm-avr32/signal.h | |||
@@ -0,0 +1,168 @@ | |||
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 | #ifndef __ASM_AVR32_SIGNAL_H | ||
9 | #define __ASM_AVR32_SIGNAL_H | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | |||
13 | /* Avoid too many header ordering problems. */ | ||
14 | struct siginfo; | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | /* Most things should be clean enough to redefine this at will, if care | ||
18 | is taken to make libc match. */ | ||
19 | |||
20 | #define _NSIG 64 | ||
21 | #define _NSIG_BPW 32 | ||
22 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | ||
23 | |||
24 | typedef unsigned long old_sigset_t; /* at least 32 bits */ | ||
25 | |||
26 | typedef struct { | ||
27 | unsigned long sig[_NSIG_WORDS]; | ||
28 | } sigset_t; | ||
29 | |||
30 | #else | ||
31 | /* Here we must cater to libcs that poke about in kernel headers. */ | ||
32 | |||
33 | #define NSIG 32 | ||
34 | typedef unsigned long sigset_t; | ||
35 | |||
36 | #endif /* __KERNEL__ */ | ||
37 | |||
38 | #define SIGHUP 1 | ||
39 | #define SIGINT 2 | ||
40 | #define SIGQUIT 3 | ||
41 | #define SIGILL 4 | ||
42 | #define SIGTRAP 5 | ||
43 | #define SIGABRT 6 | ||
44 | #define SIGIOT 6 | ||
45 | #define SIGBUS 7 | ||
46 | #define SIGFPE 8 | ||
47 | #define SIGKILL 9 | ||
48 | #define SIGUSR1 10 | ||
49 | #define SIGSEGV 11 | ||
50 | #define SIGUSR2 12 | ||
51 | #define SIGPIPE 13 | ||
52 | #define SIGALRM 14 | ||
53 | #define SIGTERM 15 | ||
54 | #define SIGSTKFLT 16 | ||
55 | #define SIGCHLD 17 | ||
56 | #define SIGCONT 18 | ||
57 | #define SIGSTOP 19 | ||
58 | #define SIGTSTP 20 | ||
59 | #define SIGTTIN 21 | ||
60 | #define SIGTTOU 22 | ||
61 | #define SIGURG 23 | ||
62 | #define SIGXCPU 24 | ||
63 | #define SIGXFSZ 25 | ||
64 | #define SIGVTALRM 26 | ||
65 | #define SIGPROF 27 | ||
66 | #define SIGWINCH 28 | ||
67 | #define SIGIO 29 | ||
68 | #define SIGPOLL SIGIO | ||
69 | /* | ||
70 | #define SIGLOST 29 | ||
71 | */ | ||
72 | #define SIGPWR 30 | ||
73 | #define SIGSYS 31 | ||
74 | #define SIGUNUSED 31 | ||
75 | |||
76 | /* These should not be considered constants from userland. */ | ||
77 | #define SIGRTMIN 32 | ||
78 | #define SIGRTMAX (_NSIG-1) | ||
79 | |||
80 | /* | ||
81 | * SA_FLAGS values: | ||
82 | * | ||
83 | * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. | ||
84 | * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. | ||
85 | * SA_SIGINFO deliver the signal with SIGINFO structs | ||
86 | * SA_ONSTACK indicates that a registered stack_t will be used. | ||
87 | * SA_RESTART flag to get restarting signals (which were the default long ago) | ||
88 | * SA_NODEFER prevents the current signal from being masked in the handler. | ||
89 | * SA_RESETHAND clears the handler when the signal is delivered. | ||
90 | * | ||
91 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | ||
92 | * Unix names RESETHAND and NODEFER respectively. | ||
93 | */ | ||
94 | #define SA_NOCLDSTOP 0x00000001 | ||
95 | #define SA_NOCLDWAIT 0x00000002 | ||
96 | #define SA_SIGINFO 0x00000004 | ||
97 | #define SA_RESTORER 0x04000000 | ||
98 | #define SA_ONSTACK 0x08000000 | ||
99 | #define SA_RESTART 0x10000000 | ||
100 | #define SA_NODEFER 0x40000000 | ||
101 | #define SA_RESETHAND 0x80000000 | ||
102 | |||
103 | #define SA_NOMASK SA_NODEFER | ||
104 | #define SA_ONESHOT SA_RESETHAND | ||
105 | |||
106 | /* | ||
107 | * sigaltstack controls | ||
108 | */ | ||
109 | #define SS_ONSTACK 1 | ||
110 | #define SS_DISABLE 2 | ||
111 | |||
112 | #define MINSIGSTKSZ 2048 | ||
113 | #define SIGSTKSZ 8192 | ||
114 | |||
115 | #include <asm-generic/signal.h> | ||
116 | |||
117 | #ifdef __KERNEL__ | ||
118 | struct old_sigaction { | ||
119 | __sighandler_t sa_handler; | ||
120 | old_sigset_t sa_mask; | ||
121 | unsigned long sa_flags; | ||
122 | __sigrestore_t sa_restorer; | ||
123 | }; | ||
124 | |||
125 | struct sigaction { | ||
126 | __sighandler_t sa_handler; | ||
127 | unsigned long sa_flags; | ||
128 | __sigrestore_t sa_restorer; | ||
129 | sigset_t sa_mask; /* mask last for extensibility */ | ||
130 | }; | ||
131 | |||
132 | struct k_sigaction { | ||
133 | struct sigaction sa; | ||
134 | }; | ||
135 | #else | ||
136 | /* Here we must cater to libcs that poke about in kernel headers. */ | ||
137 | |||
138 | struct sigaction { | ||
139 | union { | ||
140 | __sighandler_t _sa_handler; | ||
141 | void (*_sa_sigaction)(int, struct siginfo *, void *); | ||
142 | } _u; | ||
143 | sigset_t sa_mask; | ||
144 | unsigned long sa_flags; | ||
145 | void (*sa_restorer)(void); | ||
146 | }; | ||
147 | |||
148 | #define sa_handler _u._sa_handler | ||
149 | #define sa_sigaction _u._sa_sigaction | ||
150 | |||
151 | #endif /* __KERNEL__ */ | ||
152 | |||
153 | typedef struct sigaltstack { | ||
154 | void __user *ss_sp; | ||
155 | int ss_flags; | ||
156 | size_t ss_size; | ||
157 | } stack_t; | ||
158 | |||
159 | #ifdef __KERNEL__ | ||
160 | |||
161 | #include <asm/sigcontext.h> | ||
162 | #undef __HAVE_ARCH_SIG_BITOPS | ||
163 | |||
164 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
165 | |||
166 | #endif /* __KERNEL__ */ | ||
167 | |||
168 | #endif | ||
diff --git a/include/asm-avr32/socket.h b/include/asm-avr32/socket.h new file mode 100644 index 000000000000..543229de8173 --- /dev/null +++ b/include/asm-avr32/socket.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef __ASM_AVR32_SOCKET_H | ||
2 | #define __ASM_AVR32_SOCKET_H | ||
3 | |||
4 | #include <asm/sockios.h> | ||
5 | |||
6 | /* For setsockopt(2) */ | ||
7 | #define SOL_SOCKET 1 | ||
8 | |||
9 | #define SO_DEBUG 1 | ||
10 | #define SO_REUSEADDR 2 | ||
11 | #define SO_TYPE 3 | ||
12 | #define SO_ERROR 4 | ||
13 | #define SO_DONTROUTE 5 | ||
14 | #define SO_BROADCAST 6 | ||
15 | #define SO_SNDBUF 7 | ||
16 | #define SO_RCVBUF 8 | ||
17 | #define SO_SNDBUFFORCE 32 | ||
18 | #define SO_RCVBUFFORCE 33 | ||
19 | #define SO_KEEPALIVE 9 | ||
20 | #define SO_OOBINLINE 10 | ||
21 | #define SO_NO_CHECK 11 | ||
22 | #define SO_PRIORITY 12 | ||
23 | #define SO_LINGER 13 | ||
24 | #define SO_BSDCOMPAT 14 | ||
25 | /* To add :#define SO_REUSEPORT 15 */ | ||
26 | #define SO_PASSCRED 16 | ||
27 | #define SO_PEERCRED 17 | ||
28 | #define SO_RCVLOWAT 18 | ||
29 | #define SO_SNDLOWAT 19 | ||
30 | #define SO_RCVTIMEO 20 | ||
31 | #define SO_SNDTIMEO 21 | ||
32 | |||
33 | /* Security levels - as per NRL IPv6 - don't actually do anything */ | ||
34 | #define SO_SECURITY_AUTHENTICATION 22 | ||
35 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 23 | ||
36 | #define SO_SECURITY_ENCRYPTION_NETWORK 24 | ||
37 | |||
38 | #define SO_BINDTODEVICE 25 | ||
39 | |||
40 | /* Socket filtering */ | ||
41 | #define SO_ATTACH_FILTER 26 | ||
42 | #define SO_DETACH_FILTER 27 | ||
43 | |||
44 | #define SO_PEERNAME 28 | ||
45 | #define SO_TIMESTAMP 29 | ||
46 | #define SCM_TIMESTAMP SO_TIMESTAMP | ||
47 | |||
48 | #define SO_ACCEPTCONN 30 | ||
49 | |||
50 | #define SO_PEERSEC 31 | ||
51 | #define SO_PASSSEC 34 | ||
52 | |||
53 | #endif /* __ASM_AVR32_SOCKET_H */ | ||
diff --git a/include/asm-avr32/sockios.h b/include/asm-avr32/sockios.h new file mode 100644 index 000000000000..84f3d65b3b3b --- /dev/null +++ b/include/asm-avr32/sockios.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __ASM_AVR32_SOCKIOS_H | ||
2 | #define __ASM_AVR32_SOCKIOS_H | ||
3 | |||
4 | /* Socket-level I/O control calls. */ | ||
5 | #define FIOSETOWN 0x8901 | ||
6 | #define SIOCSPGRP 0x8902 | ||
7 | #define FIOGETOWN 0x8903 | ||
8 | #define SIOCGPGRP 0x8904 | ||
9 | #define SIOCATMARK 0x8905 | ||
10 | #define SIOCGSTAMP 0x8906 /* Get stamp */ | ||
11 | |||
12 | #endif /* __ASM_AVR32_SOCKIOS_H */ | ||
diff --git a/include/asm-avr32/stat.h b/include/asm-avr32/stat.h new file mode 100644 index 000000000000..e72881e10230 --- /dev/null +++ b/include/asm-avr32/stat.h | |||
@@ -0,0 +1,79 @@ | |||
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 | #ifndef __ASM_AVR32_STAT_H | ||
9 | #define __ASM_AVR32_STAT_H | ||
10 | |||
11 | struct __old_kernel_stat { | ||
12 | unsigned short st_dev; | ||
13 | unsigned short st_ino; | ||
14 | unsigned short st_mode; | ||
15 | unsigned short st_nlink; | ||
16 | unsigned short st_uid; | ||
17 | unsigned short st_gid; | ||
18 | unsigned short st_rdev; | ||
19 | unsigned long st_size; | ||
20 | unsigned long st_atime; | ||
21 | unsigned long st_mtime; | ||
22 | unsigned long st_ctime; | ||
23 | }; | ||
24 | |||
25 | struct stat { | ||
26 | unsigned long st_dev; | ||
27 | unsigned long st_ino; | ||
28 | unsigned short st_mode; | ||
29 | unsigned short st_nlink; | ||
30 | unsigned short st_uid; | ||
31 | unsigned short st_gid; | ||
32 | unsigned long st_rdev; | ||
33 | unsigned long st_size; | ||
34 | unsigned long st_blksize; | ||
35 | unsigned long st_blocks; | ||
36 | unsigned long st_atime; | ||
37 | unsigned long st_atime_nsec; | ||
38 | unsigned long st_mtime; | ||
39 | unsigned long st_mtime_nsec; | ||
40 | unsigned long st_ctime; | ||
41 | unsigned long st_ctime_nsec; | ||
42 | unsigned long __unused4; | ||
43 | unsigned long __unused5; | ||
44 | }; | ||
45 | |||
46 | #define STAT_HAVE_NSEC 1 | ||
47 | |||
48 | struct stat64 { | ||
49 | unsigned long long st_dev; | ||
50 | |||
51 | unsigned long long st_ino; | ||
52 | unsigned int st_mode; | ||
53 | unsigned int st_nlink; | ||
54 | |||
55 | unsigned long st_uid; | ||
56 | unsigned long st_gid; | ||
57 | |||
58 | unsigned long long st_rdev; | ||
59 | |||
60 | long long st_size; | ||
61 | unsigned long __pad1; /* align 64-bit st_blocks */ | ||
62 | unsigned long st_blksize; | ||
63 | |||
64 | unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ | ||
65 | |||
66 | unsigned long st_atime; | ||
67 | unsigned long st_atime_nsec; | ||
68 | |||
69 | unsigned long st_mtime; | ||
70 | unsigned long st_mtime_nsec; | ||
71 | |||
72 | unsigned long st_ctime; | ||
73 | unsigned long st_ctime_nsec; | ||
74 | |||
75 | unsigned long __unused1; | ||
76 | unsigned long __unused2; | ||
77 | }; | ||
78 | |||
79 | #endif /* __ASM_AVR32_STAT_H */ | ||
diff --git a/include/asm-avr32/statfs.h b/include/asm-avr32/statfs.h new file mode 100644 index 000000000000..2961bd18c50e --- /dev/null +++ b/include/asm-avr32/statfs.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_STATFS_H | ||
2 | #define __ASM_AVR32_STATFS_H | ||
3 | |||
4 | #include <asm-generic/statfs.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_STATFS_H */ | ||
diff --git a/include/asm-avr32/string.h b/include/asm-avr32/string.h new file mode 100644 index 000000000000..c91a623cd585 --- /dev/null +++ b/include/asm-avr32/string.h | |||
@@ -0,0 +1,17 @@ | |||
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 | #ifndef __ASM_AVR32_STRING_H | ||
9 | #define __ASM_AVR32_STRING_H | ||
10 | |||
11 | #define __HAVE_ARCH_MEMSET | ||
12 | extern void *memset(void *b, int c, size_t len); | ||
13 | |||
14 | #define __HAVE_ARCH_MEMCPY | ||
15 | extern void *memcpy(void *to, const void *from, size_t len); | ||
16 | |||
17 | #endif /* __ASM_AVR32_STRING_H */ | ||
diff --git a/include/asm-avr32/sysreg.h b/include/asm-avr32/sysreg.h new file mode 100644 index 000000000000..f91975f330f6 --- /dev/null +++ b/include/asm-avr32/sysreg.h | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * AVR32 System Registers | ||
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 __ASM_AVR32_SYSREG_H__ | ||
11 | #define __ASM_AVR32_SYSREG_H__ | ||
12 | |||
13 | /* sysreg register offsets */ | ||
14 | #define SYSREG_SR 0x0000 | ||
15 | #define SYSREG_EVBA 0x0004 | ||
16 | #define SYSREG_ACBA 0x0008 | ||
17 | #define SYSREG_CPUCR 0x000c | ||
18 | #define SYSREG_ECR 0x0010 | ||
19 | #define SYSREG_RSR_SUP 0x0014 | ||
20 | #define SYSREG_RSR_INT0 0x0018 | ||
21 | #define SYSREG_RSR_INT1 0x001c | ||
22 | #define SYSREG_RSR_INT2 0x0020 | ||
23 | #define SYSREG_RSR_INT3 0x0024 | ||
24 | #define SYSREG_RSR_EX 0x0028 | ||
25 | #define SYSREG_RSR_NMI 0x002c | ||
26 | #define SYSREG_RSR_DBG 0x0030 | ||
27 | #define SYSREG_RAR_SUP 0x0034 | ||
28 | #define SYSREG_RAR_INT0 0x0038 | ||
29 | #define SYSREG_RAR_INT1 0x003c | ||
30 | #define SYSREG_RAR_INT2 0x0040 | ||
31 | #define SYSREG_RAR_INT3 0x0044 | ||
32 | #define SYSREG_RAR_EX 0x0048 | ||
33 | #define SYSREG_RAR_NMI 0x004c | ||
34 | #define SYSREG_RAR_DBG 0x0050 | ||
35 | #define SYSREG_JECR 0x0054 | ||
36 | #define SYSREG_JOSP 0x0058 | ||
37 | #define SYSREG_JAVA_LV0 0x005c | ||
38 | #define SYSREG_JAVA_LV1 0x0060 | ||
39 | #define SYSREG_JAVA_LV2 0x0064 | ||
40 | #define SYSREG_JAVA_LV3 0x0068 | ||
41 | #define SYSREG_JAVA_LV4 0x006c | ||
42 | #define SYSREG_JAVA_LV5 0x0070 | ||
43 | #define SYSREG_JAVA_LV6 0x0074 | ||
44 | #define SYSREG_JAVA_LV7 0x0078 | ||
45 | #define SYSREG_JTBA 0x007c | ||
46 | #define SYSREG_JBCR 0x0080 | ||
47 | #define SYSREG_CONFIG0 0x0100 | ||
48 | #define SYSREG_CONFIG1 0x0104 | ||
49 | #define SYSREG_COUNT 0x0108 | ||
50 | #define SYSREG_COMPARE 0x010c | ||
51 | #define SYSREG_TLBEHI 0x0110 | ||
52 | #define SYSREG_TLBELO 0x0114 | ||
53 | #define SYSREG_PTBR 0x0118 | ||
54 | #define SYSREG_TLBEAR 0x011c | ||
55 | #define SYSREG_MMUCR 0x0120 | ||
56 | #define SYSREG_TLBARLO 0x0124 | ||
57 | #define SYSREG_TLBARHI 0x0128 | ||
58 | #define SYSREG_PCCNT 0x012c | ||
59 | #define SYSREG_PCNT0 0x0130 | ||
60 | #define SYSREG_PCNT1 0x0134 | ||
61 | #define SYSREG_PCCR 0x0138 | ||
62 | #define SYSREG_BEAR 0x013c | ||
63 | |||
64 | /* Bitfields in SR */ | ||
65 | #define SYSREG_SR_C_OFFSET 0 | ||
66 | #define SYSREG_SR_C_SIZE 1 | ||
67 | #define SYSREG_Z_OFFSET 1 | ||
68 | #define SYSREG_Z_SIZE 1 | ||
69 | #define SYSREG_SR_N_OFFSET 2 | ||
70 | #define SYSREG_SR_N_SIZE 1 | ||
71 | #define SYSREG_SR_V_OFFSET 3 | ||
72 | #define SYSREG_SR_V_SIZE 1 | ||
73 | #define SYSREG_Q_OFFSET 4 | ||
74 | #define SYSREG_Q_SIZE 1 | ||
75 | #define SYSREG_GM_OFFSET 16 | ||
76 | #define SYSREG_GM_SIZE 1 | ||
77 | #define SYSREG_I0M_OFFSET 17 | ||
78 | #define SYSREG_I0M_SIZE 1 | ||
79 | #define SYSREG_I1M_OFFSET 18 | ||
80 | #define SYSREG_I1M_SIZE 1 | ||
81 | #define SYSREG_I2M_OFFSET 19 | ||
82 | #define SYSREG_I2M_SIZE 1 | ||
83 | #define SYSREG_I3M_OFFSET 20 | ||
84 | #define SYSREG_I3M_SIZE 1 | ||
85 | #define SYSREG_EM_OFFSET 21 | ||
86 | #define SYSREG_EM_SIZE 1 | ||
87 | #define SYSREG_M0_OFFSET 22 | ||
88 | #define SYSREG_M0_SIZE 1 | ||
89 | #define SYSREG_M1_OFFSET 23 | ||
90 | #define SYSREG_M1_SIZE 1 | ||
91 | #define SYSREG_M2_OFFSET 24 | ||
92 | #define SYSREG_M2_SIZE 1 | ||
93 | #define SYSREG_SR_D_OFFSET 26 | ||
94 | #define SYSREG_SR_D_SIZE 1 | ||
95 | #define SYSREG_DM_OFFSET 27 | ||
96 | #define SYSREG_DM_SIZE 1 | ||
97 | #define SYSREG_SR_J_OFFSET 28 | ||
98 | #define SYSREG_SR_J_SIZE 1 | ||
99 | #define SYSREG_R_OFFSET 29 | ||
100 | #define SYSREG_R_SIZE 1 | ||
101 | #define SYSREG_H_OFFSET 30 | ||
102 | #define SYSREG_H_SIZE 1 | ||
103 | |||
104 | /* Bitfields in EVBA */ | ||
105 | |||
106 | /* Bitfields in ACBA */ | ||
107 | |||
108 | /* Bitfields in CPUCR */ | ||
109 | #define SYSREG_BI_OFFSET 0 | ||
110 | #define SYSREG_BI_SIZE 1 | ||
111 | #define SYSREG_BE_OFFSET 1 | ||
112 | #define SYSREG_BE_SIZE 1 | ||
113 | #define SYSREG_FE_OFFSET 2 | ||
114 | #define SYSREG_FE_SIZE 1 | ||
115 | #define SYSREG_RE_OFFSET 3 | ||
116 | #define SYSREG_RE_SIZE 1 | ||
117 | #define SYSREG_IBE_OFFSET 4 | ||
118 | #define SYSREG_IBE_SIZE 1 | ||
119 | #define SYSREG_IEE_OFFSET 5 | ||
120 | #define SYSREG_IEE_SIZE 1 | ||
121 | |||
122 | /* Bitfields in ECR */ | ||
123 | #define SYSREG_ECR_OFFSET 0 | ||
124 | #define SYSREG_ECR_SIZE 32 | ||
125 | |||
126 | /* Bitfields in RSR_SUP */ | ||
127 | |||
128 | /* Bitfields in RSR_INT0 */ | ||
129 | |||
130 | /* Bitfields in RSR_INT1 */ | ||
131 | |||
132 | /* Bitfields in RSR_INT2 */ | ||
133 | |||
134 | /* Bitfields in RSR_INT3 */ | ||
135 | |||
136 | /* Bitfields in RSR_EX */ | ||
137 | |||
138 | /* Bitfields in RSR_NMI */ | ||
139 | |||
140 | /* Bitfields in RSR_DBG */ | ||
141 | |||
142 | /* Bitfields in RAR_SUP */ | ||
143 | |||
144 | /* Bitfields in RAR_INT0 */ | ||
145 | |||
146 | /* Bitfields in RAR_INT1 */ | ||
147 | |||
148 | /* Bitfields in RAR_INT2 */ | ||
149 | |||
150 | /* Bitfields in RAR_INT3 */ | ||
151 | |||
152 | /* Bitfields in RAR_EX */ | ||
153 | |||
154 | /* Bitfields in RAR_NMI */ | ||
155 | |||
156 | /* Bitfields in RAR_DBG */ | ||
157 | |||
158 | /* Bitfields in JECR */ | ||
159 | |||
160 | /* Bitfields in JOSP */ | ||
161 | |||
162 | /* Bitfields in JAVA_LV0 */ | ||
163 | |||
164 | /* Bitfields in JAVA_LV1 */ | ||
165 | |||
166 | /* Bitfields in JAVA_LV2 */ | ||
167 | |||
168 | /* Bitfields in JAVA_LV3 */ | ||
169 | |||
170 | /* Bitfields in JAVA_LV4 */ | ||
171 | |||
172 | /* Bitfields in JAVA_LV5 */ | ||
173 | |||
174 | /* Bitfields in JAVA_LV6 */ | ||
175 | |||
176 | /* Bitfields in JAVA_LV7 */ | ||
177 | |||
178 | /* Bitfields in JTBA */ | ||
179 | |||
180 | /* Bitfields in JBCR */ | ||
181 | |||
182 | /* Bitfields in CONFIG0 */ | ||
183 | #define SYSREG_CONFIG0_D_OFFSET 1 | ||
184 | #define SYSREG_CONFIG0_D_SIZE 1 | ||
185 | #define SYSREG_CONFIG0_S_OFFSET 2 | ||
186 | #define SYSREG_CONFIG0_S_SIZE 1 | ||
187 | #define SYSREG_O_OFFSET 3 | ||
188 | #define SYSREG_O_SIZE 1 | ||
189 | #define SYSREG_P_OFFSET 4 | ||
190 | #define SYSREG_P_SIZE 1 | ||
191 | #define SYSREG_CONFIG0_J_OFFSET 5 | ||
192 | #define SYSREG_CONFIG0_J_SIZE 1 | ||
193 | #define SYSREG_F_OFFSET 6 | ||
194 | #define SYSREG_F_SIZE 1 | ||
195 | #define SYSREG_MMUT_OFFSET 7 | ||
196 | #define SYSREG_MMUT_SIZE 3 | ||
197 | #define SYSREG_AR_OFFSET 10 | ||
198 | #define SYSREG_AR_SIZE 3 | ||
199 | #define SYSREG_AT_OFFSET 13 | ||
200 | #define SYSREG_AT_SIZE 3 | ||
201 | #define SYSREG_PROCESSORREVISION_OFFSET 16 | ||
202 | #define SYSREG_PROCESSORREVISION_SIZE 8 | ||
203 | #define SYSREG_PROCESSORID_OFFSET 24 | ||
204 | #define SYSREG_PROCESSORID_SIZE 8 | ||
205 | |||
206 | /* Bitfields in CONFIG1 */ | ||
207 | #define SYSREG_DASS_OFFSET 0 | ||
208 | #define SYSREG_DASS_SIZE 3 | ||
209 | #define SYSREG_DLSZ_OFFSET 3 | ||
210 | #define SYSREG_DLSZ_SIZE 3 | ||
211 | #define SYSREG_DSET_OFFSET 6 | ||
212 | #define SYSREG_DSET_SIZE 4 | ||
213 | #define SYSREG_IASS_OFFSET 10 | ||
214 | #define SYSREG_IASS_SIZE 2 | ||
215 | #define SYSREG_ILSZ_OFFSET 13 | ||
216 | #define SYSREG_ILSZ_SIZE 3 | ||
217 | #define SYSREG_ISET_OFFSET 16 | ||
218 | #define SYSREG_ISET_SIZE 4 | ||
219 | #define SYSREG_DMMUSZ_OFFSET 20 | ||
220 | #define SYSREG_DMMUSZ_SIZE 6 | ||
221 | #define SYSREG_IMMUSZ_OFFSET 26 | ||
222 | #define SYSREG_IMMUSZ_SIZE 6 | ||
223 | |||
224 | /* Bitfields in COUNT */ | ||
225 | |||
226 | /* Bitfields in COMPARE */ | ||
227 | |||
228 | /* Bitfields in TLBEHI */ | ||
229 | #define SYSREG_ASID_OFFSET 0 | ||
230 | #define SYSREG_ASID_SIZE 8 | ||
231 | #define SYSREG_TLBEHI_I_OFFSET 8 | ||
232 | #define SYSREG_TLBEHI_I_SIZE 1 | ||
233 | #define SYSREG_TLBEHI_V_OFFSET 9 | ||
234 | #define SYSREG_TLBEHI_V_SIZE 1 | ||
235 | #define SYSREG_VPN_OFFSET 10 | ||
236 | #define SYSREG_VPN_SIZE 22 | ||
237 | |||
238 | /* Bitfields in TLBELO */ | ||
239 | #define SYSREG_W_OFFSET 0 | ||
240 | #define SYSREG_W_SIZE 1 | ||
241 | #define SYSREG_TLBELO_D_OFFSET 1 | ||
242 | #define SYSREG_TLBELO_D_SIZE 1 | ||
243 | #define SYSREG_SZ_OFFSET 2 | ||
244 | #define SYSREG_SZ_SIZE 2 | ||
245 | #define SYSREG_AP_OFFSET 4 | ||
246 | #define SYSREG_AP_SIZE 3 | ||
247 | #define SYSREG_B_OFFSET 7 | ||
248 | #define SYSREG_B_SIZE 1 | ||
249 | #define SYSREG_G_OFFSET 8 | ||
250 | #define SYSREG_G_SIZE 1 | ||
251 | #define SYSREG_TLBELO_C_OFFSET 9 | ||
252 | #define SYSREG_TLBELO_C_SIZE 1 | ||
253 | #define SYSREG_PFN_OFFSET 10 | ||
254 | #define SYSREG_PFN_SIZE 22 | ||
255 | |||
256 | /* Bitfields in PTBR */ | ||
257 | |||
258 | /* Bitfields in TLBEAR */ | ||
259 | |||
260 | /* Bitfields in MMUCR */ | ||
261 | #define SYSREG_E_OFFSET 0 | ||
262 | #define SYSREG_E_SIZE 1 | ||
263 | #define SYSREG_M_OFFSET 1 | ||
264 | #define SYSREG_M_SIZE 1 | ||
265 | #define SYSREG_MMUCR_I_OFFSET 2 | ||
266 | #define SYSREG_MMUCR_I_SIZE 1 | ||
267 | #define SYSREG_MMUCR_N_OFFSET 3 | ||
268 | #define SYSREG_MMUCR_N_SIZE 1 | ||
269 | #define SYSREG_MMUCR_S_OFFSET 4 | ||
270 | #define SYSREG_MMUCR_S_SIZE 1 | ||
271 | #define SYSREG_DLA_OFFSET 8 | ||
272 | #define SYSREG_DLA_SIZE 6 | ||
273 | #define SYSREG_DRP_OFFSET 14 | ||
274 | #define SYSREG_DRP_SIZE 6 | ||
275 | #define SYSREG_ILA_OFFSET 20 | ||
276 | #define SYSREG_ILA_SIZE 6 | ||
277 | #define SYSREG_IRP_OFFSET 26 | ||
278 | #define SYSREG_IRP_SIZE 6 | ||
279 | |||
280 | /* Bitfields in TLBARLO */ | ||
281 | |||
282 | /* Bitfields in TLBARHI */ | ||
283 | |||
284 | /* Bitfields in PCCNT */ | ||
285 | |||
286 | /* Bitfields in PCNT0 */ | ||
287 | |||
288 | /* Bitfields in PCNT1 */ | ||
289 | |||
290 | /* Bitfields in PCCR */ | ||
291 | |||
292 | /* Bitfields in BEAR */ | ||
293 | |||
294 | /* Constants for ECR */ | ||
295 | #define ECR_UNRECOVERABLE 0 | ||
296 | #define ECR_TLB_MULTIPLE 1 | ||
297 | #define ECR_BUS_ERROR_WRITE 2 | ||
298 | #define ECR_BUS_ERROR_READ 3 | ||
299 | #define ECR_NMI 4 | ||
300 | #define ECR_ADDR_ALIGN_X 5 | ||
301 | #define ECR_PROTECTION_X 6 | ||
302 | #define ECR_DEBUG 7 | ||
303 | #define ECR_ILLEGAL_OPCODE 8 | ||
304 | #define ECR_UNIMPL_INSTRUCTION 9 | ||
305 | #define ECR_PRIVILEGE_VIOLATION 10 | ||
306 | #define ECR_FPE 11 | ||
307 | #define ECR_COPROC_ABSENT 12 | ||
308 | #define ECR_ADDR_ALIGN_R 13 | ||
309 | #define ECR_ADDR_ALIGN_W 14 | ||
310 | #define ECR_PROTECTION_R 15 | ||
311 | #define ECR_PROTECTION_W 16 | ||
312 | #define ECR_DTLB_MODIFIED 17 | ||
313 | #define ECR_TLB_MISS_X 20 | ||
314 | #define ECR_TLB_MISS_R 24 | ||
315 | #define ECR_TLB_MISS_W 28 | ||
316 | |||
317 | /* Bit manipulation macros */ | ||
318 | #define SYSREG_BIT(name) (1 << SYSREG_##name##_OFFSET) | ||
319 | #define SYSREG_BF(name,value) (((value) & ((1 << SYSREG_##name##_SIZE) - 1)) << SYSREG_##name##_OFFSET) | ||
320 | #define SYSREG_BFEXT(name,value) (((value) >> SYSREG_##name##_OFFSET) & ((1 << SYSREG_##name##_SIZE) - 1)) | ||
321 | #define SYSREG_BFINS(name,value,old) (((old) & ~(((1 << SYSREG_##name##_SIZE) - 1) << SYSREG_##name##_OFFSET)) | SYSREG_BF(name,value)) | ||
322 | |||
323 | #ifdef __CHECKER__ | ||
324 | extern unsigned long __builtin_mfsr(unsigned long reg); | ||
325 | extern void __builtin_mtsr(unsigned long reg, unsigned long value); | ||
326 | #endif | ||
327 | |||
328 | /* Register access macros */ | ||
329 | #define sysreg_read(reg) __builtin_mfsr(SYSREG_##reg) | ||
330 | #define sysreg_write(reg, value) __builtin_mtsr(SYSREG_##reg, value) | ||
331 | |||
332 | #endif /* __ASM_AVR32_SYSREG_H__ */ | ||
diff --git a/include/asm-avr32/system.h b/include/asm-avr32/system.h new file mode 100644 index 000000000000..ac596058697d --- /dev/null +++ b/include/asm-avr32/system.h | |||
@@ -0,0 +1,155 @@ | |||
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 | #ifndef __ASM_AVR32_SYSTEM_H | ||
9 | #define __ASM_AVR32_SYSTEM_H | ||
10 | |||
11 | #include <linux/compiler.h> | ||
12 | #include <linux/types.h> | ||
13 | |||
14 | #include <asm/ptrace.h> | ||
15 | #include <asm/sysreg.h> | ||
16 | |||
17 | #define xchg(ptr,x) \ | ||
18 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
19 | |||
20 | #define nop() asm volatile("nop") | ||
21 | |||
22 | #define mb() asm volatile("" : : : "memory") | ||
23 | #define rmb() mb() | ||
24 | #define wmb() asm volatile("sync 0" : : : "memory") | ||
25 | #define read_barrier_depends() do { } while(0) | ||
26 | #define set_mb(var, value) do { var = value; mb(); } while(0) | ||
27 | |||
28 | /* | ||
29 | * Help PathFinder and other Nexus-compliant debuggers keep track of | ||
30 | * the current PID by emitting an Ownership Trace Message each time we | ||
31 | * switch task. | ||
32 | */ | ||
33 | #ifdef CONFIG_OWNERSHIP_TRACE | ||
34 | #include <asm/ocd.h> | ||
35 | #define finish_arch_switch(prev) \ | ||
36 | do { \ | ||
37 | __mtdr(DBGREG_PID, prev->pid); \ | ||
38 | __mtdr(DBGREG_PID, current->pid); \ | ||
39 | } while(0) | ||
40 | #endif | ||
41 | |||
42 | /* | ||
43 | * switch_to(prev, next, last) should switch from task `prev' to task | ||
44 | * `next'. `prev' will never be the same as `next'. | ||
45 | * | ||
46 | * We just delegate everything to the __switch_to assembly function, | ||
47 | * which is implemented in arch/avr32/kernel/switch_to.S | ||
48 | * | ||
49 | * mb() tells GCC not to cache `current' across this call. | ||
50 | */ | ||
51 | struct cpu_context; | ||
52 | struct task_struct; | ||
53 | extern struct task_struct *__switch_to(struct task_struct *, | ||
54 | struct cpu_context *, | ||
55 | struct cpu_context *); | ||
56 | #define switch_to(prev, next, last) \ | ||
57 | do { \ | ||
58 | last = __switch_to(prev, &prev->thread.cpu_context + 1, \ | ||
59 | &next->thread.cpu_context); \ | ||
60 | } while (0) | ||
61 | |||
62 | #ifdef CONFIG_SMP | ||
63 | # error "The AVR32 port does not support SMP" | ||
64 | #else | ||
65 | # define smp_mb() barrier() | ||
66 | # define smp_rmb() barrier() | ||
67 | # define smp_wmb() barrier() | ||
68 | # define smp_read_barrier_depends() do { } while(0) | ||
69 | #endif | ||
70 | |||
71 | #include <linux/irqflags.h> | ||
72 | |||
73 | extern void __xchg_called_with_bad_pointer(void); | ||
74 | |||
75 | #ifdef __CHECKER__ | ||
76 | extern unsigned long __builtin_xchg(void *ptr, unsigned long x); | ||
77 | #endif | ||
78 | |||
79 | #define xchg_u32(val, m) __builtin_xchg((void *)m, val) | ||
80 | |||
81 | static inline unsigned long __xchg(unsigned long x, | ||
82 | volatile void *ptr, | ||
83 | int size) | ||
84 | { | ||
85 | switch(size) { | ||
86 | case 4: | ||
87 | return xchg_u32(x, ptr); | ||
88 | default: | ||
89 | __xchg_called_with_bad_pointer(); | ||
90 | return x; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, | ||
95 | unsigned long new) | ||
96 | { | ||
97 | __u32 ret; | ||
98 | |||
99 | asm volatile( | ||
100 | "1: ssrf 5\n" | ||
101 | " ld.w %[ret], %[m]\n" | ||
102 | " cp.w %[ret], %[old]\n" | ||
103 | " brne 2f\n" | ||
104 | " stcond %[m], %[new]\n" | ||
105 | " brne 1b\n" | ||
106 | "2:\n" | ||
107 | : [ret] "=&r"(ret), [m] "=m"(*m) | ||
108 | : "m"(m), [old] "ir"(old), [new] "r"(new) | ||
109 | : "memory", "cc"); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( | ||
114 | volatile int * m, unsigned long old, unsigned long new); | ||
115 | #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels | ||
116 | |||
117 | /* This function doesn't exist, so you'll get a linker error | ||
118 | if something tries to do an invalid cmpxchg(). */ | ||
119 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
120 | |||
121 | #define __HAVE_ARCH_CMPXCHG 1 | ||
122 | |||
123 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | ||
124 | unsigned long new, int size) | ||
125 | { | ||
126 | switch (size) { | ||
127 | case 4: | ||
128 | return __cmpxchg_u32(ptr, old, new); | ||
129 | case 8: | ||
130 | return __cmpxchg_u64(ptr, old, new); | ||
131 | } | ||
132 | |||
133 | __cmpxchg_called_with_bad_pointer(); | ||
134 | return old; | ||
135 | } | ||
136 | |||
137 | #define cmpxchg(ptr, old, new) \ | ||
138 | ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \ | ||
139 | (unsigned long)(new), \ | ||
140 | sizeof(*(ptr)))) | ||
141 | |||
142 | struct pt_regs; | ||
143 | extern void __die(const char *, struct pt_regs *, unsigned long, | ||
144 | const char *, const char *, unsigned long); | ||
145 | extern void __die_if_kernel(const char *, struct pt_regs *, unsigned long, | ||
146 | const char *, const char *, unsigned long); | ||
147 | |||
148 | #define die(msg, regs, err) \ | ||
149 | __die(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__) | ||
150 | #define die_if_kernel(msg, regs, err) \ | ||
151 | __die_if_kernel(msg, regs, err, __FILE__ ":", __FUNCTION__, __LINE__) | ||
152 | |||
153 | #define arch_align_stack(x) (x) | ||
154 | |||
155 | #endif /* __ASM_AVR32_SYSTEM_H */ | ||
diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h new file mode 100644 index 000000000000..9dc6eacafa33 --- /dev/null +++ b/include/asm-avr32/termbits.h | |||
@@ -0,0 +1,173 @@ | |||
1 | #ifndef __ASM_AVR32_TERMBITS_H | ||
2 | #define __ASM_AVR32_TERMBITS_H | ||
3 | |||
4 | #include <linux/posix_types.h> | ||
5 | |||
6 | typedef unsigned char cc_t; | ||
7 | typedef unsigned int speed_t; | ||
8 | typedef unsigned int tcflag_t; | ||
9 | |||
10 | #define NCCS 19 | ||
11 | struct termios { | ||
12 | tcflag_t c_iflag; /* input mode flags */ | ||
13 | tcflag_t c_oflag; /* output mode flags */ | ||
14 | tcflag_t c_cflag; /* control mode flags */ | ||
15 | tcflag_t c_lflag; /* local mode flags */ | ||
16 | cc_t c_line; /* line discipline */ | ||
17 | cc_t c_cc[NCCS]; /* control characters */ | ||
18 | }; | ||
19 | |||
20 | /* c_cc characters */ | ||
21 | #define VINTR 0 | ||
22 | #define VQUIT 1 | ||
23 | #define VERASE 2 | ||
24 | #define VKILL 3 | ||
25 | #define VEOF 4 | ||
26 | #define VTIME 5 | ||
27 | #define VMIN 6 | ||
28 | #define VSWTC 7 | ||
29 | #define VSTART 8 | ||
30 | #define VSTOP 9 | ||
31 | #define VSUSP 10 | ||
32 | #define VEOL 11 | ||
33 | #define VREPRINT 12 | ||
34 | #define VDISCARD 13 | ||
35 | #define VWERASE 14 | ||
36 | #define VLNEXT 15 | ||
37 | #define VEOL2 16 | ||
38 | |||
39 | /* c_iflag bits */ | ||
40 | #define IGNBRK 0000001 | ||
41 | #define BRKINT 0000002 | ||
42 | #define IGNPAR 0000004 | ||
43 | #define PARMRK 0000010 | ||
44 | #define INPCK 0000020 | ||
45 | #define ISTRIP 0000040 | ||
46 | #define INLCR 0000100 | ||
47 | #define IGNCR 0000200 | ||
48 | #define ICRNL 0000400 | ||
49 | #define IUCLC 0001000 | ||
50 | #define IXON 0002000 | ||
51 | #define IXANY 0004000 | ||
52 | #define IXOFF 0010000 | ||
53 | #define IMAXBEL 0020000 | ||
54 | #define IUTF8 0040000 | ||
55 | |||
56 | /* c_oflag bits */ | ||
57 | #define OPOST 0000001 | ||
58 | #define OLCUC 0000002 | ||
59 | #define ONLCR 0000004 | ||
60 | #define OCRNL 0000010 | ||
61 | #define ONOCR 0000020 | ||
62 | #define ONLRET 0000040 | ||
63 | #define OFILL 0000100 | ||
64 | #define OFDEL 0000200 | ||
65 | #define NLDLY 0000400 | ||
66 | #define NL0 0000000 | ||
67 | #define NL1 0000400 | ||
68 | #define CRDLY 0003000 | ||
69 | #define CR0 0000000 | ||
70 | #define CR1 0001000 | ||
71 | #define CR2 0002000 | ||
72 | #define CR3 0003000 | ||
73 | #define TABDLY 0014000 | ||
74 | #define TAB0 0000000 | ||
75 | #define TAB1 0004000 | ||
76 | #define TAB2 0010000 | ||
77 | #define TAB3 0014000 | ||
78 | #define XTABS 0014000 | ||
79 | #define BSDLY 0020000 | ||
80 | #define BS0 0000000 | ||
81 | #define BS1 0020000 | ||
82 | #define VTDLY 0040000 | ||
83 | #define VT0 0000000 | ||
84 | #define VT1 0040000 | ||
85 | #define FFDLY 0100000 | ||
86 | #define FF0 0000000 | ||
87 | #define FF1 0100000 | ||
88 | |||
89 | /* c_cflag bit meaning */ | ||
90 | #define CBAUD 0010017 | ||
91 | #define B0 0000000 /* hang up */ | ||
92 | #define B50 0000001 | ||
93 | #define B75 0000002 | ||
94 | #define B110 0000003 | ||
95 | #define B134 0000004 | ||
96 | #define B150 0000005 | ||
97 | #define B200 0000006 | ||
98 | #define B300 0000007 | ||
99 | #define B600 0000010 | ||
100 | #define B1200 0000011 | ||
101 | #define B1800 0000012 | ||
102 | #define B2400 0000013 | ||
103 | #define B4800 0000014 | ||
104 | #define B9600 0000015 | ||
105 | #define B19200 0000016 | ||
106 | #define B38400 0000017 | ||
107 | #define EXTA B19200 | ||
108 | #define EXTB B38400 | ||
109 | #define CSIZE 0000060 | ||
110 | #define CS5 0000000 | ||
111 | #define CS6 0000020 | ||
112 | #define CS7 0000040 | ||
113 | #define CS8 0000060 | ||
114 | #define CSTOPB 0000100 | ||
115 | #define CREAD 0000200 | ||
116 | #define PARENB 0000400 | ||
117 | #define PARODD 0001000 | ||
118 | #define HUPCL 0002000 | ||
119 | #define CLOCAL 0004000 | ||
120 | #define CBAUDEX 0010000 | ||
121 | #define B57600 0010001 | ||
122 | #define B115200 0010002 | ||
123 | #define B230400 0010003 | ||
124 | #define B460800 0010004 | ||
125 | #define B500000 0010005 | ||
126 | #define B576000 0010006 | ||
127 | #define B921600 0010007 | ||
128 | #define B1000000 0010010 | ||
129 | #define B1152000 0010011 | ||
130 | #define B1500000 0010012 | ||
131 | #define B2000000 0010013 | ||
132 | #define B2500000 0010014 | ||
133 | #define B3000000 0010015 | ||
134 | #define B3500000 0010016 | ||
135 | #define B4000000 0010017 | ||
136 | #define CIBAUD 002003600000 /* input baud rate (not used) */ | ||
137 | #define CMSPAR 010000000000 /* mark or space (stick) parity */ | ||
138 | #define CRTSCTS 020000000000 /* flow control */ | ||
139 | |||
140 | /* c_lflag bits */ | ||
141 | #define ISIG 0000001 | ||
142 | #define ICANON 0000002 | ||
143 | #define XCASE 0000004 | ||
144 | #define ECHO 0000010 | ||
145 | #define ECHOE 0000020 | ||
146 | #define ECHOK 0000040 | ||
147 | #define ECHONL 0000100 | ||
148 | #define NOFLSH 0000200 | ||
149 | #define TOSTOP 0000400 | ||
150 | #define ECHOCTL 0001000 | ||
151 | #define ECHOPRT 0002000 | ||
152 | #define ECHOKE 0004000 | ||
153 | #define FLUSHO 0010000 | ||
154 | #define PENDIN 0040000 | ||
155 | #define IEXTEN 0100000 | ||
156 | |||
157 | /* tcflow() and TCXONC use these */ | ||
158 | #define TCOOFF 0 | ||
159 | #define TCOON 1 | ||
160 | #define TCIOFF 2 | ||
161 | #define TCION 3 | ||
162 | |||
163 | /* tcflush() and TCFLSH use these */ | ||
164 | #define TCIFLUSH 0 | ||
165 | #define TCOFLUSH 1 | ||
166 | #define TCIOFLUSH 2 | ||
167 | |||
168 | /* tcsetattr uses these */ | ||
169 | #define TCSANOW 0 | ||
170 | #define TCSADRAIN 1 | ||
171 | #define TCSAFLUSH 2 | ||
172 | |||
173 | #endif /* __ASM_AVR32_TERMBITS_H */ | ||
diff --git a/include/asm-avr32/termios.h b/include/asm-avr32/termios.h new file mode 100644 index 000000000000..615bc0639e5c --- /dev/null +++ b/include/asm-avr32/termios.h | |||
@@ -0,0 +1,80 @@ | |||
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 | #ifndef __ASM_AVR32_TERMIOS_H | ||
9 | #define __ASM_AVR32_TERMIOS_H | ||
10 | |||
11 | #include <asm/termbits.h> | ||
12 | #include <asm/ioctls.h> | ||
13 | |||
14 | struct winsize { | ||
15 | unsigned short ws_row; | ||
16 | unsigned short ws_col; | ||
17 | unsigned short ws_xpixel; | ||
18 | unsigned short ws_ypixel; | ||
19 | }; | ||
20 | |||
21 | #define NCC 8 | ||
22 | struct termio { | ||
23 | unsigned short c_iflag; /* input mode flags */ | ||
24 | unsigned short c_oflag; /* output mode flags */ | ||
25 | unsigned short c_cflag; /* control mode flags */ | ||
26 | unsigned short c_lflag; /* local mode flags */ | ||
27 | unsigned char c_line; /* line discipline */ | ||
28 | unsigned char c_cc[NCC]; /* control characters */ | ||
29 | }; | ||
30 | |||
31 | /* modem lines */ | ||
32 | #define TIOCM_LE 0x001 | ||
33 | #define TIOCM_DTR 0x002 | ||
34 | #define TIOCM_RTS 0x004 | ||
35 | #define TIOCM_ST 0x008 | ||
36 | #define TIOCM_SR 0x010 | ||
37 | #define TIOCM_CTS 0x020 | ||
38 | #define TIOCM_CAR 0x040 | ||
39 | #define TIOCM_RNG 0x080 | ||
40 | #define TIOCM_DSR 0x100 | ||
41 | #define TIOCM_CD TIOCM_CAR | ||
42 | #define TIOCM_RI TIOCM_RNG | ||
43 | #define TIOCM_OUT1 0x2000 | ||
44 | #define TIOCM_OUT2 0x4000 | ||
45 | #define TIOCM_LOOP 0x8000 | ||
46 | |||
47 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ | ||
48 | |||
49 | /* line disciplines */ | ||
50 | #define N_TTY 0 | ||
51 | #define N_SLIP 1 | ||
52 | #define N_MOUSE 2 | ||
53 | #define N_PPP 3 | ||
54 | #define N_STRIP 4 | ||
55 | #define N_AX25 5 | ||
56 | #define N_X25 6 /* X.25 async */ | ||
57 | #define N_6PACK 7 | ||
58 | #define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */ | ||
59 | #define N_R3964 9 /* Reserved for Simatic R3964 module */ | ||
60 | #define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */ | ||
61 | #define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ | ||
62 | #define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ | ||
63 | #define N_HDLC 13 /* synchronous HDLC */ | ||
64 | #define N_SYNC_PPP 14 /* synchronous PPP */ | ||
65 | #define N_HCI 15 /* Bluetooth HCI UART */ | ||
66 | |||
67 | #ifdef __KERNEL__ | ||
68 | /* intr=^C quit=^\ erase=del kill=^U | ||
69 | eof=^D vtime=\0 vmin=\1 sxtc=\0 | ||
70 | start=^Q stop=^S susp=^Z eol=\0 | ||
71 | reprint=^R discard=^U werase=^W lnext=^V | ||
72 | eol2=\0 | ||
73 | */ | ||
74 | #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" | ||
75 | |||
76 | #include <asm-generic/termios.h> | ||
77 | |||
78 | #endif /* __KERNEL__ */ | ||
79 | |||
80 | #endif /* __ASM_AVR32_TERMIOS_H */ | ||
diff --git a/include/asm-avr32/thread_info.h b/include/asm-avr32/thread_info.h new file mode 100644 index 000000000000..d1f5b35ebd54 --- /dev/null +++ b/include/asm-avr32/thread_info.h | |||
@@ -0,0 +1,106 @@ | |||
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 | #ifndef __ASM_AVR32_THREAD_INFO_H | ||
9 | #define __ASM_AVR32_THREAD_INFO_H | ||
10 | |||
11 | #include <asm/page.h> | ||
12 | |||
13 | #define THREAD_SIZE_ORDER 1 | ||
14 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) | ||
15 | |||
16 | #ifndef __ASSEMBLY__ | ||
17 | #include <asm/types.h> | ||
18 | |||
19 | struct task_struct; | ||
20 | struct exec_domain; | ||
21 | |||
22 | struct thread_info { | ||
23 | struct task_struct *task; /* main task structure */ | ||
24 | struct exec_domain *exec_domain; /* execution domain */ | ||
25 | unsigned long flags; /* low level flags */ | ||
26 | __u32 cpu; | ||
27 | __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ | ||
28 | struct restart_block restart_block; | ||
29 | __u8 supervisor_stack[0]; | ||
30 | }; | ||
31 | |||
32 | #define INIT_THREAD_INFO(tsk) \ | ||
33 | { \ | ||
34 | .task = &tsk, \ | ||
35 | .exec_domain = &default_exec_domain, \ | ||
36 | .flags = 0, \ | ||
37 | .cpu = 0, \ | ||
38 | .preempt_count = 1, \ | ||
39 | .restart_block = { \ | ||
40 | .fn = do_no_restart_syscall \ | ||
41 | } \ | ||
42 | } | ||
43 | |||
44 | #define init_thread_info (init_thread_union.thread_info) | ||
45 | #define init_stack (init_thread_union.stack) | ||
46 | |||
47 | /* | ||
48 | * Get the thread information struct from C. | ||
49 | * We do the usual trick and use the lower end of the stack for this | ||
50 | */ | ||
51 | static inline struct thread_info *current_thread_info(void) | ||
52 | { | ||
53 | unsigned long addr = ~(THREAD_SIZE - 1); | ||
54 | |||
55 | asm("and %0, sp" : "=r"(addr) : "0"(addr)); | ||
56 | return (struct thread_info *)addr; | ||
57 | } | ||
58 | |||
59 | /* thread information allocation */ | ||
60 | #define alloc_thread_info(ti) \ | ||
61 | ((struct thread_info *) __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) | ||
62 | #define free_thread_info(ti) free_pages((unsigned long)(ti), 1) | ||
63 | #define get_thread_info(ti) get_task_struct((ti)->task) | ||
64 | #define put_thread_info(ti) put_task_struct((ti)->task) | ||
65 | |||
66 | #endif /* !__ASSEMBLY__ */ | ||
67 | |||
68 | #define PREEMPT_ACTIVE 0x40000000 | ||
69 | |||
70 | /* | ||
71 | * Thread information flags | ||
72 | * - these are process state flags that various assembly files may need to access | ||
73 | * - pending work-to-be-done flags are in LSW | ||
74 | * - other flags in MSW | ||
75 | */ | ||
76 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | ||
77 | #define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ | ||
78 | #define TIF_SIGPENDING 2 /* signal pending */ | ||
79 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | ||
80 | #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling | ||
81 | TIF_NEED_RESCHED */ | ||
82 | #define TIF_BREAKPOINT 5 /* true if we should break after return */ | ||
83 | #define TIF_SINGLE_STEP 6 /* single step after next break */ | ||
84 | #define TIF_MEMDIE 7 | ||
85 | #define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal */ | ||
86 | #define TIF_USERSPACE 31 /* true if FS sets userspace */ | ||
87 | |||
88 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | ||
89 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | ||
90 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | ||
91 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | ||
92 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | ||
93 | #define _TIF_BREAKPOINT (1 << TIF_BREAKPOINT) | ||
94 | #define _TIF_SINGLE_STEP (1 << TIF_SINGLE_STEP) | ||
95 | #define _TIF_MEMDIE (1 << TIF_MEMDIE) | ||
96 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) | ||
97 | |||
98 | /* XXX: These two masks must never span more than 16 bits! */ | ||
99 | /* work to do on interrupt/exception return */ | ||
100 | #define _TIF_WORK_MASK 0x0000013e | ||
101 | /* work to do on any return to userspace */ | ||
102 | #define _TIF_ALLWORK_MASK 0x0000013f | ||
103 | /* work to do on return from debug mode */ | ||
104 | #define _TIF_DBGWORK_MASK 0x0000017e | ||
105 | |||
106 | #endif /* __ASM_AVR32_THREAD_INFO_H */ | ||
diff --git a/include/asm-avr32/timex.h b/include/asm-avr32/timex.h new file mode 100644 index 000000000000..5e44ecb3ce0c --- /dev/null +++ b/include/asm-avr32/timex.h | |||
@@ -0,0 +1,40 @@ | |||
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 | #ifndef __ASM_AVR32_TIMEX_H | ||
9 | #define __ASM_AVR32_TIMEX_H | ||
10 | |||
11 | /* | ||
12 | * This is the frequency of the timer used for Linux's timer interrupt. | ||
13 | * The value should be defined as accurate as possible or under certain | ||
14 | * circumstances Linux timekeeping might become inaccurate or fail. | ||
15 | * | ||
16 | * For many system the exact clockrate of the timer isn't known but due to | ||
17 | * the way this value is used we can get away with a wrong value as long | ||
18 | * as this value is: | ||
19 | * | ||
20 | * - a multiple of HZ | ||
21 | * - a divisor of the actual rate | ||
22 | * | ||
23 | * 500000 is a good such cheat value. | ||
24 | * | ||
25 | * The obscure number 1193182 is the same as used by the original i8254 | ||
26 | * time in legacy PC hardware; the chip is never found in AVR32 systems. | ||
27 | */ | ||
28 | #define CLOCK_TICK_RATE 500000 /* Underlying HZ */ | ||
29 | |||
30 | typedef unsigned long cycles_t; | ||
31 | |||
32 | static inline cycles_t get_cycles (void) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | extern int read_current_timer(unsigned long *timer_value); | ||
38 | #define ARCH_HAS_READ_CURRENT_TIMER 1 | ||
39 | |||
40 | #endif /* __ASM_AVR32_TIMEX_H */ | ||
diff --git a/include/asm-avr32/tlb.h b/include/asm-avr32/tlb.h new file mode 100644 index 000000000000..5c55f9ce7c7d --- /dev/null +++ b/include/asm-avr32/tlb.h | |||
@@ -0,0 +1,32 @@ | |||
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 | #ifndef __ASM_AVR32_TLB_H | ||
9 | #define __ASM_AVR32_TLB_H | ||
10 | |||
11 | #define tlb_start_vma(tlb, vma) \ | ||
12 | flush_cache_range(vma, vma->vm_start, vma->vm_end) | ||
13 | |||
14 | #define tlb_end_vma(tlb, vma) \ | ||
15 | flush_tlb_range(vma, vma->vm_start, vma->vm_end) | ||
16 | |||
17 | #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while(0) | ||
18 | |||
19 | /* | ||
20 | * Flush whole TLB for MM | ||
21 | */ | ||
22 | #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) | ||
23 | |||
24 | #include <asm-generic/tlb.h> | ||
25 | |||
26 | /* | ||
27 | * For debugging purposes | ||
28 | */ | ||
29 | extern void show_dtlb_entry(unsigned int index); | ||
30 | extern void dump_dtlb(void); | ||
31 | |||
32 | #endif /* __ASM_AVR32_TLB_H */ | ||
diff --git a/include/asm-avr32/tlbflush.h b/include/asm-avr32/tlbflush.h new file mode 100644 index 000000000000..730e268f81f3 --- /dev/null +++ b/include/asm-avr32/tlbflush.h | |||
@@ -0,0 +1,40 @@ | |||
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 | #ifndef __ASM_AVR32_TLBFLUSH_H | ||
9 | #define __ASM_AVR32_TLBFLUSH_H | ||
10 | |||
11 | #include <asm/mmu.h> | ||
12 | |||
13 | /* | ||
14 | * TLB flushing: | ||
15 | * | ||
16 | * - flush_tlb() flushes the current mm struct TLBs | ||
17 | * - flush_tlb_all() flushes all processes' TLB entries | ||
18 | * - flush_tlb_mm(mm) flushes the specified mm context TLBs | ||
19 | * - flush_tlb_page(vma, vmaddr) flushes one page | ||
20 | * - flush_tlb_range(vma, start, end) flushes a range of pages | ||
21 | * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages | ||
22 | * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables | ||
23 | */ | ||
24 | extern void flush_tlb(void); | ||
25 | extern void flush_tlb_all(void); | ||
26 | extern void flush_tlb_mm(struct mm_struct *mm); | ||
27 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | ||
28 | unsigned long end); | ||
29 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); | ||
30 | extern void __flush_tlb_page(unsigned long asid, unsigned long page); | ||
31 | |||
32 | static inline void flush_tlb_pgtables(struct mm_struct *mm, | ||
33 | unsigned long start, unsigned long end) | ||
34 | { | ||
35 | /* Nothing to do */ | ||
36 | } | ||
37 | |||
38 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); | ||
39 | |||
40 | #endif /* __ASM_AVR32_TLBFLUSH_H */ | ||
diff --git a/include/asm-avr32/topology.h b/include/asm-avr32/topology.h new file mode 100644 index 000000000000..5b766cbb4806 --- /dev/null +++ b/include/asm-avr32/topology.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __ASM_AVR32_TOPOLOGY_H | ||
2 | #define __ASM_AVR32_TOPOLOGY_H | ||
3 | |||
4 | #include <asm-generic/topology.h> | ||
5 | |||
6 | #endif /* __ASM_AVR32_TOPOLOGY_H */ | ||
diff --git a/include/asm-avr32/traps.h b/include/asm-avr32/traps.h new file mode 100644 index 000000000000..6a8fb944f414 --- /dev/null +++ b/include/asm-avr32/traps.h | |||
@@ -0,0 +1,23 @@ | |||
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 | #ifndef __ASM_AVR32_TRAPS_H | ||
9 | #define __ASM_AVR32_TRAPS_H | ||
10 | |||
11 | #include <linux/list.h> | ||
12 | |||
13 | struct undef_hook { | ||
14 | struct list_head node; | ||
15 | u32 insn_mask; | ||
16 | u32 insn_val; | ||
17 | int (*fn)(struct pt_regs *regs, u32 insn); | ||
18 | }; | ||
19 | |||
20 | void register_undef_hook(struct undef_hook *hook); | ||
21 | void unregister_undef_hook(struct undef_hook *hook); | ||
22 | |||
23 | #endif /* __ASM_AVR32_TRAPS_H */ | ||
diff --git a/include/asm-avr32/types.h b/include/asm-avr32/types.h new file mode 100644 index 000000000000..3f47db9675af --- /dev/null +++ b/include/asm-avr32/types.h | |||
@@ -0,0 +1,70 @@ | |||
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 | #ifndef __ASM_AVR32_TYPES_H | ||
9 | #define __ASM_AVR32_TYPES_H | ||
10 | |||
11 | #ifndef __ASSEMBLY__ | ||
12 | |||
13 | typedef unsigned short umode_t; | ||
14 | |||
15 | /* | ||
16 | * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the | ||
17 | * header files exported to user space | ||
18 | */ | ||
19 | typedef __signed__ char __s8; | ||
20 | typedef unsigned char __u8; | ||
21 | |||
22 | typedef __signed__ short __s16; | ||
23 | typedef unsigned short __u16; | ||
24 | |||
25 | typedef __signed__ int __s32; | ||
26 | typedef unsigned int __u32; | ||
27 | |||
28 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | ||
29 | typedef __signed__ long long __s64; | ||
30 | typedef unsigned long long __u64; | ||
31 | #endif | ||
32 | |||
33 | #endif /* __ASSEMBLY__ */ | ||
34 | |||
35 | /* | ||
36 | * These aren't exported outside the kernel to avoid name space clashes | ||
37 | */ | ||
38 | #ifdef __KERNEL__ | ||
39 | |||
40 | #define BITS_PER_LONG 32 | ||
41 | |||
42 | #ifndef __ASSEMBLY__ | ||
43 | |||
44 | typedef signed char s8; | ||
45 | typedef unsigned char u8; | ||
46 | |||
47 | typedef signed short s16; | ||
48 | typedef unsigned short u16; | ||
49 | |||
50 | typedef signed int s32; | ||
51 | typedef unsigned int u32; | ||
52 | |||
53 | typedef signed long long s64; | ||
54 | typedef unsigned long long u64; | ||
55 | |||
56 | /* Dma addresses are 32-bits wide. */ | ||
57 | |||
58 | typedef u32 dma_addr_t; | ||
59 | |||
60 | #ifdef CONFIG_LBD | ||
61 | typedef u64 sector_t; | ||
62 | #define HAVE_SECTOR_T | ||
63 | #endif | ||
64 | |||
65 | #endif /* __ASSEMBLY__ */ | ||
66 | |||
67 | #endif /* __KERNEL__ */ | ||
68 | |||
69 | |||
70 | #endif /* __ASM_AVR32_TYPES_H */ | ||
diff --git a/include/asm-avr32/uaccess.h b/include/asm-avr32/uaccess.h new file mode 100644 index 000000000000..821deb5a9d28 --- /dev/null +++ b/include/asm-avr32/uaccess.h | |||
@@ -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 | #ifndef __ASM_AVR32_UACCESS_H | ||
9 | #define __ASM_AVR32_UACCESS_H | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | |||
14 | #define VERIFY_READ 0 | ||
15 | #define VERIFY_WRITE 1 | ||
16 | |||
17 | typedef struct { | ||
18 | unsigned int is_user_space; | ||
19 | } mm_segment_t; | ||
20 | |||
21 | /* | ||
22 | * The fs value determines whether argument validity checking should be | ||
23 | * performed or not. If get_fs() == USER_DS, checking is performed, with | ||
24 | * get_fs() == KERNEL_DS, checking is bypassed. | ||
25 | * | ||
26 | * For historical reasons (Data Segment Register?), these macros are misnamed. | ||
27 | */ | ||
28 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | ||
29 | #define segment_eq(a,b) ((a).is_user_space == (b).is_user_space) | ||
30 | |||
31 | #define USER_ADDR_LIMIT 0x80000000 | ||
32 | |||
33 | #define KERNEL_DS MAKE_MM_SEG(0) | ||
34 | #define USER_DS MAKE_MM_SEG(1) | ||
35 | |||
36 | #define get_ds() (KERNEL_DS) | ||
37 | |||
38 | static inline mm_segment_t get_fs(void) | ||
39 | { | ||
40 | return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE)); | ||
41 | } | ||
42 | |||
43 | static inline void set_fs(mm_segment_t s) | ||
44 | { | ||
45 | if (s.is_user_space) | ||
46 | set_thread_flag(TIF_USERSPACE); | ||
47 | else | ||
48 | clear_thread_flag(TIF_USERSPACE); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Test whether a block of memory is a valid user space address. | ||
53 | * Returns 0 if the range is valid, nonzero otherwise. | ||
54 | * | ||
55 | * We do the following checks: | ||
56 | * 1. Is the access from kernel space? | ||
57 | * 2. Does (addr + size) set the carry bit? | ||
58 | * 3. Is (addr + size) a negative number (i.e. >= 0x80000000)? | ||
59 | * | ||
60 | * If yes on the first check, access is granted. | ||
61 | * If no on any of the others, access is denied. | ||
62 | */ | ||
63 | #define __range_ok(addr, size) \ | ||
64 | (test_thread_flag(TIF_USERSPACE) \ | ||
65 | && (((unsigned long)(addr) >= 0x80000000) \ | ||
66 | || ((unsigned long)(size) > 0x80000000) \ | ||
67 | || (((unsigned long)(addr) + (unsigned long)(size)) > 0x80000000))) | ||
68 | |||
69 | #define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0)) | ||
70 | |||
71 | static inline int | ||
72 | verify_area(int type, const void __user *addr, unsigned long size) | ||
73 | { | ||
74 | return access_ok(type, addr, size) ? 0 : -EFAULT; | ||
75 | } | ||
76 | |||
77 | /* Generic arbitrary sized copy. Return the number of bytes NOT copied */ | ||
78 | extern __kernel_size_t __copy_user(void *to, const void *from, | ||
79 | __kernel_size_t n); | ||
80 | |||
81 | extern __kernel_size_t copy_to_user(void __user *to, const void *from, | ||
82 | __kernel_size_t n); | ||
83 | extern __kernel_size_t copy_from_user(void *to, const void __user *from, | ||
84 | __kernel_size_t n); | ||
85 | |||
86 | static inline __kernel_size_t __copy_to_user(void __user *to, const void *from, | ||
87 | __kernel_size_t n) | ||
88 | { | ||
89 | return __copy_user((void __force *)to, from, n); | ||
90 | } | ||
91 | static inline __kernel_size_t __copy_from_user(void *to, | ||
92 | const void __user *from, | ||
93 | __kernel_size_t n) | ||
94 | { | ||
95 | return __copy_user(to, (const void __force *)from, n); | ||
96 | } | ||
97 | |||
98 | #define __copy_to_user_inatomic __copy_to_user | ||
99 | #define __copy_from_user_inatomic __copy_from_user | ||
100 | |||
101 | /* | ||
102 | * put_user: - Write a simple value into user space. | ||
103 | * @x: Value to copy to user space. | ||
104 | * @ptr: Destination address, in user space. | ||
105 | * | ||
106 | * Context: User context only. This function may sleep. | ||
107 | * | ||
108 | * This macro copies a single simple value from kernel space to user | ||
109 | * space. It supports simple types like char and int, but not larger | ||
110 | * data types like structures or arrays. | ||
111 | * | ||
112 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
113 | * to the result of dereferencing @ptr. | ||
114 | * | ||
115 | * Returns zero on success, or -EFAULT on error. | ||
116 | */ | ||
117 | #define put_user(x,ptr) \ | ||
118 | __put_user_check((x),(ptr),sizeof(*(ptr))) | ||
119 | |||
120 | /* | ||
121 | * get_user: - Get a simple variable from user space. | ||
122 | * @x: Variable to store result. | ||
123 | * @ptr: Source address, in user space. | ||
124 | * | ||
125 | * Context: User context only. This function may sleep. | ||
126 | * | ||
127 | * This macro copies a single simple variable from user space to kernel | ||
128 | * space. It supports simple types like char and int, but not larger | ||
129 | * data types like structures or arrays. | ||
130 | * | ||
131 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
132 | * dereferencing @ptr must be assignable to @x without a cast. | ||
133 | * | ||
134 | * Returns zero on success, or -EFAULT on error. | ||
135 | * On error, the variable @x is set to zero. | ||
136 | */ | ||
137 | #define get_user(x,ptr) \ | ||
138 | __get_user_check((x),(ptr),sizeof(*(ptr))) | ||
139 | |||
140 | /* | ||
141 | * __put_user: - Write a simple value into user space, with less checking. | ||
142 | * @x: Value to copy to user space. | ||
143 | * @ptr: Destination address, in user space. | ||
144 | * | ||
145 | * Context: User context only. This function may sleep. | ||
146 | * | ||
147 | * This macro copies a single simple value from kernel space to user | ||
148 | * space. It supports simple types like char and int, but not larger | ||
149 | * data types like structures or arrays. | ||
150 | * | ||
151 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
152 | * to the result of dereferencing @ptr. | ||
153 | * | ||
154 | * Caller must check the pointer with access_ok() before calling this | ||
155 | * function. | ||
156 | * | ||
157 | * Returns zero on success, or -EFAULT on error. | ||
158 | */ | ||
159 | #define __put_user(x,ptr) \ | ||
160 | __put_user_nocheck((x),(ptr),sizeof(*(ptr))) | ||
161 | |||
162 | /* | ||
163 | * __get_user: - Get a simple variable from user space, with less checking. | ||
164 | * @x: Variable to store result. | ||
165 | * @ptr: Source address, in user space. | ||
166 | * | ||
167 | * Context: User context only. This function may sleep. | ||
168 | * | ||
169 | * This macro copies a single simple variable from user space to kernel | ||
170 | * space. It supports simple types like char and int, but not larger | ||
171 | * data types like structures or arrays. | ||
172 | * | ||
173 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
174 | * dereferencing @ptr must be assignable to @x without a cast. | ||
175 | * | ||
176 | * Caller must check the pointer with access_ok() before calling this | ||
177 | * function. | ||
178 | * | ||
179 | * Returns zero on success, or -EFAULT on error. | ||
180 | * On error, the variable @x is set to zero. | ||
181 | */ | ||
182 | #define __get_user(x,ptr) \ | ||
183 | __get_user_nocheck((x),(ptr),sizeof(*(ptr))) | ||
184 | |||
185 | extern int __get_user_bad(void); | ||
186 | extern int __put_user_bad(void); | ||
187 | |||
188 | #define __get_user_nocheck(x, ptr, size) \ | ||
189 | ({ \ | ||
190 | typeof(*(ptr)) __gu_val = (typeof(*(ptr)) __force)0; \ | ||
191 | int __gu_err = 0; \ | ||
192 | \ | ||
193 | switch (size) { \ | ||
194 | case 1: __get_user_asm("ub", __gu_val, ptr, __gu_err); break; \ | ||
195 | case 2: __get_user_asm("uh", __gu_val, ptr, __gu_err); break; \ | ||
196 | case 4: __get_user_asm("w", __gu_val, ptr, __gu_err); break; \ | ||
197 | case 8: __get_user_asm("d", __gu_val, ptr, __gu_err); break; \ | ||
198 | default: __gu_err = __get_user_bad(); break; \ | ||
199 | } \ | ||
200 | \ | ||
201 | x = __gu_val; \ | ||
202 | __gu_err; \ | ||
203 | }) | ||
204 | |||
205 | #define __get_user_check(x, ptr, size) \ | ||
206 | ({ \ | ||
207 | typeof(*(ptr)) __gu_val = (typeof(*(ptr)) __force)0; \ | ||
208 | const typeof(*(ptr)) __user * __gu_addr = (ptr); \ | ||
209 | int __gu_err = 0; \ | ||
210 | \ | ||
211 | if (access_ok(VERIFY_READ, __gu_addr, size)) { \ | ||
212 | switch (size) { \ | ||
213 | case 1: \ | ||
214 | __get_user_asm("ub", __gu_val, __gu_addr, \ | ||
215 | __gu_err); \ | ||
216 | break; \ | ||
217 | case 2: \ | ||
218 | __get_user_asm("uh", __gu_val, __gu_addr, \ | ||
219 | __gu_err); \ | ||
220 | break; \ | ||
221 | case 4: \ | ||
222 | __get_user_asm("w", __gu_val, __gu_addr, \ | ||
223 | __gu_err); \ | ||
224 | break; \ | ||
225 | case 8: \ | ||
226 | __get_user_asm("d", __gu_val, __gu_addr, \ | ||
227 | __gu_err); \ | ||
228 | break; \ | ||
229 | default: \ | ||
230 | __gu_err = __get_user_bad(); \ | ||
231 | break; \ | ||
232 | } \ | ||
233 | } else { \ | ||
234 | __gu_err = -EFAULT; \ | ||
235 | } \ | ||
236 | x = __gu_val; \ | ||
237 | __gu_err; \ | ||
238 | }) | ||
239 | |||
240 | #define __get_user_asm(suffix, __gu_val, ptr, __gu_err) \ | ||
241 | asm volatile( \ | ||
242 | "1: ld." suffix " %1, %3 \n" \ | ||
243 | "2: \n" \ | ||
244 | " .section .fixup, \"ax\" \n" \ | ||
245 | "3: mov %0, %4 \n" \ | ||
246 | " rjmp 2b \n" \ | ||
247 | " .previous \n" \ | ||
248 | " .section __ex_table, \"a\" \n" \ | ||
249 | " .long 1b, 3b \n" \ | ||
250 | " .previous \n" \ | ||
251 | : "=r"(__gu_err), "=r"(__gu_val) \ | ||
252 | : "0"(__gu_err), "m"(*(ptr)), "i"(-EFAULT)) | ||
253 | |||
254 | #define __put_user_nocheck(x, ptr, size) \ | ||
255 | ({ \ | ||
256 | typeof(*(ptr)) __pu_val; \ | ||
257 | int __pu_err = 0; \ | ||
258 | \ | ||
259 | __pu_val = (x); \ | ||
260 | switch (size) { \ | ||
261 | case 1: __put_user_asm("b", ptr, __pu_val, __pu_err); break; \ | ||
262 | case 2: __put_user_asm("h", ptr, __pu_val, __pu_err); break; \ | ||
263 | case 4: __put_user_asm("w", ptr, __pu_val, __pu_err); break; \ | ||
264 | case 8: __put_user_asm("d", ptr, __pu_val, __pu_err); break; \ | ||
265 | default: __pu_err = __put_user_bad(); break; \ | ||
266 | } \ | ||
267 | __pu_err; \ | ||
268 | }) | ||
269 | |||
270 | #define __put_user_check(x, ptr, size) \ | ||
271 | ({ \ | ||
272 | typeof(*(ptr)) __pu_val; \ | ||
273 | typeof(*(ptr)) __user *__pu_addr = (ptr); \ | ||
274 | int __pu_err = 0; \ | ||
275 | \ | ||
276 | __pu_val = (x); \ | ||
277 | if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ | ||
278 | switch (size) { \ | ||
279 | case 1: \ | ||
280 | __put_user_asm("b", __pu_addr, __pu_val, \ | ||
281 | __pu_err); \ | ||
282 | break; \ | ||
283 | case 2: \ | ||
284 | __put_user_asm("h", __pu_addr, __pu_val, \ | ||
285 | __pu_err); \ | ||
286 | break; \ | ||
287 | case 4: \ | ||
288 | __put_user_asm("w", __pu_addr, __pu_val, \ | ||
289 | __pu_err); \ | ||
290 | break; \ | ||
291 | case 8: \ | ||
292 | __put_user_asm("d", __pu_addr, __pu_val, \ | ||
293 | __pu_err); \ | ||
294 | break; \ | ||
295 | default: \ | ||
296 | __pu_err = __put_user_bad(); \ | ||
297 | break; \ | ||
298 | } \ | ||
299 | } else { \ | ||
300 | __pu_err = -EFAULT; \ | ||
301 | } \ | ||
302 | __pu_err; \ | ||
303 | }) | ||
304 | |||
305 | #define __put_user_asm(suffix, ptr, __pu_val, __gu_err) \ | ||
306 | asm volatile( \ | ||
307 | "1: st." suffix " %1, %3 \n" \ | ||
308 | "2: \n" \ | ||
309 | " .section .fixup, \"ax\" \n" \ | ||
310 | "3: mov %0, %4 \n" \ | ||
311 | " rjmp 2b \n" \ | ||
312 | " .previous \n" \ | ||
313 | " .section __ex_table, \"a\" \n" \ | ||
314 | " .long 1b, 3b \n" \ | ||
315 | " .previous \n" \ | ||
316 | : "=r"(__gu_err), "=m"(*(ptr)) \ | ||
317 | : "0"(__gu_err), "r"(__pu_val), "i"(-EFAULT)) | ||
318 | |||
319 | extern __kernel_size_t clear_user(void __user *addr, __kernel_size_t size); | ||
320 | extern __kernel_size_t __clear_user(void __user *addr, __kernel_size_t size); | ||
321 | |||
322 | extern long strncpy_from_user(char *dst, const char __user *src, long count); | ||
323 | extern long __strncpy_from_user(char *dst, const char __user *src, long count); | ||
324 | |||
325 | extern long strnlen_user(const char __user *__s, long __n); | ||
326 | extern long __strnlen_user(const char __user *__s, long __n); | ||
327 | |||
328 | #define strlen_user(s) strnlen_user(s, ~0UL >> 1) | ||
329 | |||
330 | struct exception_table_entry | ||
331 | { | ||
332 | unsigned long insn, fixup; | ||
333 | }; | ||
334 | |||
335 | #endif /* __ASM_AVR32_UACCESS_H */ | ||
diff --git a/include/asm-avr32/ucontext.h b/include/asm-avr32/ucontext.h new file mode 100644 index 000000000000..ac7259c2a799 --- /dev/null +++ b/include/asm-avr32/ucontext.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __ASM_AVR32_UCONTEXT_H | ||
2 | #define __ASM_AVR32_UCONTEXT_H | ||
3 | |||
4 | struct ucontext { | ||
5 | unsigned long uc_flags; | ||
6 | struct ucontext * uc_link; | ||
7 | stack_t uc_stack; | ||
8 | struct sigcontext uc_mcontext; | ||
9 | sigset_t uc_sigmask; | ||
10 | }; | ||
11 | |||
12 | #endif /* __ASM_AVR32_UCONTEXT_H */ | ||
diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h new file mode 100644 index 000000000000..3042723fcbfd --- /dev/null +++ b/include/asm-avr32/unaligned.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __ASM_AVR32_UNALIGNED_H | ||
2 | #define __ASM_AVR32_UNALIGNED_H | ||
3 | |||
4 | /* | ||
5 | * AVR32 can handle some unaligned accesses, depending on the | ||
6 | * implementation. The AVR32 AP implementation can handle unaligned | ||
7 | * words, but halfwords must be halfword-aligned, and doublewords must | ||
8 | * be word-aligned. | ||
9 | * | ||
10 | * TODO: Make all this CPU-specific and optimize. | ||
11 | */ | ||
12 | |||
13 | #include <linux/string.h> | ||
14 | |||
15 | /* Use memmove here, so gcc does not insert a __builtin_memcpy. */ | ||
16 | |||
17 | #define get_unaligned(ptr) \ | ||
18 | ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) | ||
19 | |||
20 | #define put_unaligned(val, ptr) \ | ||
21 | ({ __typeof__(*(ptr)) __tmp = (val); \ | ||
22 | memmove((ptr), &__tmp, sizeof(*(ptr))); \ | ||
23 | (void)0; }) | ||
24 | |||
25 | #endif /* __ASM_AVR32_UNALIGNED_H */ | ||
diff --git a/include/asm-avr32/unistd.h b/include/asm-avr32/unistd.h new file mode 100644 index 000000000000..1f528f92690d --- /dev/null +++ b/include/asm-avr32/unistd.h | |||
@@ -0,0 +1,387 @@ | |||
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 | #ifndef __ASM_AVR32_UNISTD_H | ||
9 | #define __ASM_AVR32_UNISTD_H | ||
10 | |||
11 | /* | ||
12 | * This file contains the system call numbers. | ||
13 | */ | ||
14 | |||
15 | #define __NR_restart_syscall 0 | ||
16 | #define __NR_exit 1 | ||
17 | #define __NR_fork 2 | ||
18 | #define __NR_read 3 | ||
19 | #define __NR_write 4 | ||
20 | #define __NR_open 5 | ||
21 | #define __NR_close 6 | ||
22 | #define __NR_umask 7 | ||
23 | #define __NR_creat 8 | ||
24 | #define __NR_link 9 | ||
25 | #define __NR_unlink 10 | ||
26 | #define __NR_execve 11 | ||
27 | #define __NR_chdir 12 | ||
28 | #define __NR_time 13 | ||
29 | #define __NR_mknod 14 | ||
30 | #define __NR_chmod 15 | ||
31 | #define __NR_chown 16 | ||
32 | #define __NR_lchown 17 | ||
33 | #define __NR_lseek 18 | ||
34 | #define __NR__llseek 19 | ||
35 | #define __NR_getpid 20 | ||
36 | #define __NR_mount 21 | ||
37 | #define __NR_umount2 22 | ||
38 | #define __NR_setuid 23 | ||
39 | #define __NR_getuid 24 | ||
40 | #define __NR_stime 25 | ||
41 | #define __NR_ptrace 26 | ||
42 | #define __NR_alarm 27 | ||
43 | #define __NR_pause 28 | ||
44 | #define __NR_utime 29 | ||
45 | #define __NR_stat 30 | ||
46 | #define __NR_fstat 31 | ||
47 | #define __NR_lstat 32 | ||
48 | #define __NR_access 33 | ||
49 | #define __NR_chroot 34 | ||
50 | #define __NR_sync 35 | ||
51 | #define __NR_fsync 36 | ||
52 | #define __NR_kill 37 | ||
53 | #define __NR_rename 38 | ||
54 | #define __NR_mkdir 39 | ||
55 | #define __NR_rmdir 40 | ||
56 | #define __NR_dup 41 | ||
57 | #define __NR_pipe 42 | ||
58 | #define __NR_times 43 | ||
59 | #define __NR_clone 44 | ||
60 | #define __NR_brk 45 | ||
61 | #define __NR_setgid 46 | ||
62 | #define __NR_getgid 47 | ||
63 | #define __NR_getcwd 48 | ||
64 | #define __NR_geteuid 49 | ||
65 | #define __NR_getegid 50 | ||
66 | #define __NR_acct 51 | ||
67 | #define __NR_setfsuid 52 | ||
68 | #define __NR_setfsgid 53 | ||
69 | #define __NR_ioctl 54 | ||
70 | #define __NR_fcntl 55 | ||
71 | #define __NR_setpgid 56 | ||
72 | #define __NR_mremap 57 | ||
73 | #define __NR_setresuid 58 | ||
74 | #define __NR_getresuid 59 | ||
75 | #define __NR_setreuid 60 | ||
76 | #define __NR_setregid 61 | ||
77 | #define __NR_ustat 62 | ||
78 | #define __NR_dup2 63 | ||
79 | #define __NR_getppid 64 | ||
80 | #define __NR_getpgrp 65 | ||
81 | #define __NR_setsid 66 | ||
82 | #define __NR_rt_sigaction 67 | ||
83 | #define __NR_rt_sigreturn 68 | ||
84 | #define __NR_rt_sigprocmask 69 | ||
85 | #define __NR_rt_sigpending 70 | ||
86 | #define __NR_rt_sigtimedwait 71 | ||
87 | #define __NR_rt_sigqueueinfo 72 | ||
88 | #define __NR_rt_sigsuspend 73 | ||
89 | #define __NR_sethostname 74 | ||
90 | #define __NR_setrlimit 75 | ||
91 | #define __NR_getrlimit 76 /* SuS compliant getrlimit */ | ||
92 | #define __NR_getrusage 77 | ||
93 | #define __NR_gettimeofday 78 | ||
94 | #define __NR_settimeofday 79 | ||
95 | #define __NR_getgroups 80 | ||
96 | #define __NR_setgroups 81 | ||
97 | #define __NR_select 82 | ||
98 | #define __NR_symlink 83 | ||
99 | #define __NR_fchdir 84 | ||
100 | #define __NR_readlink 85 | ||
101 | #define __NR_pread 86 | ||
102 | #define __NR_pwrite 87 | ||
103 | #define __NR_swapon 88 | ||
104 | #define __NR_reboot 89 | ||
105 | #define __NR_mmap2 90 | ||
106 | #define __NR_munmap 91 | ||
107 | #define __NR_truncate 92 | ||
108 | #define __NR_ftruncate 93 | ||
109 | #define __NR_fchmod 94 | ||
110 | #define __NR_fchown 95 | ||
111 | #define __NR_getpriority 96 | ||
112 | #define __NR_setpriority 97 | ||
113 | #define __NR_wait4 98 | ||
114 | #define __NR_statfs 99 | ||
115 | #define __NR_fstatfs 100 | ||
116 | #define __NR_vhangup 101 | ||
117 | #define __NR_sigaltstack 102 | ||
118 | #define __NR_syslog 103 | ||
119 | #define __NR_setitimer 104 | ||
120 | #define __NR_getitimer 105 | ||
121 | #define __NR_swapoff 106 | ||
122 | #define __NR_sysinfo 107 | ||
123 | #define __NR_ipc 108 | ||
124 | #define __NR_sendfile 109 | ||
125 | #define __NR_setdomainname 110 | ||
126 | #define __NR_uname 111 | ||
127 | #define __NR_adjtimex 112 | ||
128 | #define __NR_mprotect 113 | ||
129 | #define __NR_vfork 114 | ||
130 | #define __NR_init_module 115 | ||
131 | #define __NR_delete_module 116 | ||
132 | #define __NR_quotactl 117 | ||
133 | #define __NR_getpgid 118 | ||
134 | #define __NR_bdflush 119 | ||
135 | #define __NR_sysfs 120 | ||
136 | #define __NR_personality 121 | ||
137 | #define __NR_afs_syscall 122 /* Syscall for Andrew File System */ | ||
138 | #define __NR_getdents 123 | ||
139 | #define __NR_flock 124 | ||
140 | #define __NR_msync 125 | ||
141 | #define __NR_readv 126 | ||
142 | #define __NR_writev 127 | ||
143 | #define __NR_getsid 128 | ||
144 | #define __NR_fdatasync 129 | ||
145 | #define __NR__sysctl 130 | ||
146 | #define __NR_mlock 131 | ||
147 | #define __NR_munlock 132 | ||
148 | #define __NR_mlockall 133 | ||
149 | #define __NR_munlockall 134 | ||
150 | #define __NR_sched_setparam 135 | ||
151 | #define __NR_sched_getparam 136 | ||
152 | #define __NR_sched_setscheduler 137 | ||
153 | #define __NR_sched_getscheduler 138 | ||
154 | #define __NR_sched_yield 139 | ||
155 | #define __NR_sched_get_priority_max 140 | ||
156 | #define __NR_sched_get_priority_min 141 | ||
157 | #define __NR_sched_rr_get_interval 142 | ||
158 | #define __NR_nanosleep 143 | ||
159 | #define __NR_poll 144 | ||
160 | #define __NR_nfsservctl 145 | ||
161 | #define __NR_setresgid 146 | ||
162 | #define __NR_getresgid 147 | ||
163 | #define __NR_prctl 148 | ||
164 | #define __NR_socket 149 | ||
165 | #define __NR_bind 150 | ||
166 | #define __NR_connect 151 | ||
167 | #define __NR_listen 152 | ||
168 | #define __NR_accept 153 | ||
169 | #define __NR_getsockname 154 | ||
170 | #define __NR_getpeername 155 | ||
171 | #define __NR_socketpair 156 | ||
172 | #define __NR_send 157 | ||
173 | #define __NR_recv 158 | ||
174 | #define __NR_sendto 159 | ||
175 | #define __NR_recvfrom 160 | ||
176 | #define __NR_shutdown 161 | ||
177 | #define __NR_setsockopt 162 | ||
178 | #define __NR_getsockopt 163 | ||
179 | #define __NR_sendmsg 164 | ||
180 | #define __NR_recvmsg 165 | ||
181 | #define __NR_truncate64 166 | ||
182 | #define __NR_ftruncate64 167 | ||
183 | #define __NR_stat64 168 | ||
184 | #define __NR_lstat64 169 | ||
185 | #define __NR_fstat64 170 | ||
186 | #define __NR_pivot_root 171 | ||
187 | #define __NR_mincore 172 | ||
188 | #define __NR_madvise 173 | ||
189 | #define __NR_getdents64 174 | ||
190 | #define __NR_fcntl64 175 | ||
191 | #define __NR_gettid 176 | ||
192 | #define __NR_readahead 177 | ||
193 | #define __NR_setxattr 178 | ||
194 | #define __NR_lsetxattr 179 | ||
195 | #define __NR_fsetxattr 180 | ||
196 | #define __NR_getxattr 181 | ||
197 | #define __NR_lgetxattr 182 | ||
198 | #define __NR_fgetxattr 183 | ||
199 | #define __NR_listxattr 184 | ||
200 | #define __NR_llistxattr 185 | ||
201 | #define __NR_flistxattr 186 | ||
202 | #define __NR_removexattr 187 | ||
203 | #define __NR_lremovexattr 188 | ||
204 | #define __NR_fremovexattr 189 | ||
205 | #define __NR_tkill 190 | ||
206 | #define __NR_sendfile64 191 | ||
207 | #define __NR_futex 192 | ||
208 | #define __NR_sched_setaffinity 193 | ||
209 | #define __NR_sched_getaffinity 194 | ||
210 | #define __NR_capget 195 | ||
211 | #define __NR_capset 196 | ||
212 | #define __NR_io_setup 197 | ||
213 | #define __NR_io_destroy 198 | ||
214 | #define __NR_io_getevents 199 | ||
215 | #define __NR_io_submit 200 | ||
216 | #define __NR_io_cancel 201 | ||
217 | #define __NR_fadvise64 202 | ||
218 | #define __NR_exit_group 203 | ||
219 | #define __NR_lookup_dcookie 204 | ||
220 | #define __NR_epoll_create 205 | ||
221 | #define __NR_epoll_ctl 206 | ||
222 | #define __NR_epoll_wait 207 | ||
223 | #define __NR_remap_file_pages 208 | ||
224 | #define __NR_set_tid_address 209 | ||
225 | |||
226 | #define __NR_timer_create 210 | ||
227 | #define __NR_timer_settime 211 | ||
228 | #define __NR_timer_gettime 212 | ||
229 | #define __NR_timer_getoverrun 213 | ||
230 | #define __NR_timer_delete 214 | ||
231 | #define __NR_clock_settime 215 | ||
232 | #define __NR_clock_gettime 216 | ||
233 | #define __NR_clock_getres 217 | ||
234 | #define __NR_clock_nanosleep 218 | ||
235 | #define __NR_statfs64 219 | ||
236 | #define __NR_fstatfs64 220 | ||
237 | #define __NR_tgkill 221 | ||
238 | /* 222 reserved for tux */ | ||
239 | #define __NR_utimes 223 | ||
240 | #define __NR_fadvise64_64 224 | ||
241 | |||
242 | #define __NR_cacheflush 225 | ||
243 | |||
244 | #define __NR_vserver 226 | ||
245 | #define __NR_mq_open 227 | ||
246 | #define __NR_mq_unlink 228 | ||
247 | #define __NR_mq_timedsend 229 | ||
248 | #define __NR_mq_timedreceive 230 | ||
249 | #define __NR_mq_notify 231 | ||
250 | #define __NR_mq_getsetattr 232 | ||
251 | #define __NR_kexec_load 233 | ||
252 | #define __NR_waitid 234 | ||
253 | #define __NR_add_key 235 | ||
254 | #define __NR_request_key 236 | ||
255 | #define __NR_keyctl 237 | ||
256 | #define __NR_ioprio_set 238 | ||
257 | #define __NR_ioprio_get 239 | ||
258 | #define __NR_inotify_init 240 | ||
259 | #define __NR_inotify_add_watch 241 | ||
260 | #define __NR_inotify_rm_watch 242 | ||
261 | #define __NR_openat 243 | ||
262 | #define __NR_mkdirat 244 | ||
263 | #define __NR_mknodat 245 | ||
264 | #define __NR_fchownat 246 | ||
265 | #define __NR_futimesat 247 | ||
266 | #define __NR_fstatat64 248 | ||
267 | #define __NR_unlinkat 249 | ||
268 | #define __NR_renameat 250 | ||
269 | #define __NR_linkat 251 | ||
270 | #define __NR_symlinkat 252 | ||
271 | #define __NR_readlinkat 253 | ||
272 | #define __NR_fchmodat 254 | ||
273 | #define __NR_faccessat 255 | ||
274 | #define __NR_pselect6 256 | ||
275 | #define __NR_ppoll 257 | ||
276 | #define __NR_unshare 258 | ||
277 | #define __NR_set_robust_list 259 | ||
278 | #define __NR_get_robust_list 260 | ||
279 | #define __NR_splice 261 | ||
280 | #define __NR_sync_file_range 262 | ||
281 | #define __NR_tee 263 | ||
282 | #define __NR_vmsplice 264 | ||
283 | |||
284 | #define NR_syscalls 265 | ||
285 | |||
286 | |||
287 | /* | ||
288 | * AVR32 calling convention for system calls: | ||
289 | * - System call number in r8 | ||
290 | * - Parameters in r12 and downwards to r9 as well as r6 and r5. | ||
291 | * - Return value in r12 | ||
292 | */ | ||
293 | |||
294 | /* | ||
295 | * user-visible error numbers are in the range -1 - -124: see | ||
296 | * <asm-generic/errno.h> | ||
297 | */ | ||
298 | |||
299 | #define __syscall_return(type, res) do { \ | ||
300 | if ((unsigned long)(res) >= (unsigned long)(-125)) { \ | ||
301 | errno = -(res); \ | ||
302 | res = -1; \ | ||
303 | } \ | ||
304 | return (type) (res); \ | ||
305 | } while (0) | ||
306 | |||
307 | #ifdef __KERNEL__ | ||
308 | #define __ARCH_WANT_IPC_PARSE_VERSION | ||
309 | #define __ARCH_WANT_STAT64 | ||
310 | #define __ARCH_WANT_SYS_ALARM | ||
311 | #define __ARCH_WANT_SYS_GETHOSTNAME | ||
312 | #define __ARCH_WANT_SYS_PAUSE | ||
313 | #define __ARCH_WANT_SYS_TIME | ||
314 | #define __ARCH_WANT_SYS_UTIME | ||
315 | #define __ARCH_WANT_SYS_WAITPID | ||
316 | #define __ARCH_WANT_SYS_FADVISE64 | ||
317 | #define __ARCH_WANT_SYS_GETPGRP | ||
318 | #define __ARCH_WANT_SYS_LLSEEK | ||
319 | #define __ARCH_WANT_SYS_GETPGRP | ||
320 | #define __ARCH_WANT_SYS_RT_SIGACTION | ||
321 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
322 | #endif | ||
323 | |||
324 | #if defined(__KERNEL_SYSCALLS__) || defined(__CHECKER__) | ||
325 | |||
326 | #include <linux/types.h> | ||
327 | #include <linux/linkage.h> | ||
328 | #include <asm/signal.h> | ||
329 | |||
330 | struct pt_regs; | ||
331 | |||
332 | /* | ||
333 | * we need this inline - forking from kernel space will result | ||
334 | * in NO COPY ON WRITE (!!!), until an execve is executed. This | ||
335 | * is no problem, but for the stack. This is handled by not letting | ||
336 | * main() use the stack at all after fork(). Thus, no function | ||
337 | * calls - which means inline code for fork too, as otherwise we | ||
338 | * would use the stack upon exit from 'fork()'. | ||
339 | * | ||
340 | * Actually only pause and fork are needed inline, so that there | ||
341 | * won't be any messing with the stack from main(), but we define | ||
342 | * some others too. | ||
343 | */ | ||
344 | static inline int execve(const char *file, char **argv, char **envp) | ||
345 | { | ||
346 | register long scno asm("r8") = __NR_execve; | ||
347 | register long sc1 asm("r12") = (long)file; | ||
348 | register long sc2 asm("r11") = (long)argv; | ||
349 | register long sc3 asm("r10") = (long)envp; | ||
350 | int res; | ||
351 | |||
352 | asm volatile("scall" | ||
353 | : "=r"(sc1) | ||
354 | : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3) | ||
355 | : "lr", "memory"); | ||
356 | res = sc1; | ||
357 | __syscall_return(int, res); | ||
358 | } | ||
359 | |||
360 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); | ||
361 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
362 | struct pt_regs *regs); | ||
363 | asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); | ||
364 | asmlinkage int sys_pipe(unsigned long __user *filedes); | ||
365 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | ||
366 | unsigned long prot, unsigned long flags, | ||
367 | unsigned long fd, off_t offset); | ||
368 | asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len); | ||
369 | asmlinkage int sys_fork(struct pt_regs *regs); | ||
370 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
371 | unsigned long parent_tidptr, | ||
372 | unsigned long child_tidptr, struct pt_regs *regs); | ||
373 | asmlinkage int sys_vfork(struct pt_regs *regs); | ||
374 | asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv, | ||
375 | char __user *__user *uenvp, struct pt_regs *regs); | ||
376 | |||
377 | #endif | ||
378 | |||
379 | /* | ||
380 | * "Conditional" syscalls | ||
381 | * | ||
382 | * What we want is __attribute__((weak,alias("sys_ni_syscall"))), | ||
383 | * but it doesn't work on all toolchains, so we just do it by hand | ||
384 | */ | ||
385 | #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); | ||
386 | |||
387 | #endif /* __ASM_AVR32_UNISTD_H */ | ||
diff --git a/include/asm-avr32/user.h b/include/asm-avr32/user.h new file mode 100644 index 000000000000..060fb3acee49 --- /dev/null +++ b/include/asm-avr32/user.h | |||
@@ -0,0 +1,65 @@ | |||
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 | * Note: We may not need these definitions for AVR32, as we don't | ||
9 | * support a.out. | ||
10 | */ | ||
11 | #ifndef __ASM_AVR32_USER_H | ||
12 | #define __ASM_AVR32_USER_H | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <asm/ptrace.h> | ||
16 | #include <asm/page.h> | ||
17 | |||
18 | /* | ||
19 | * Core file format: The core file is written in such a way that gdb | ||
20 | * can understand it and provide useful information to the user (under | ||
21 | * linux we use the `trad-core' bfd). The file contents are as follows: | ||
22 | * | ||
23 | * upage: 1 page consisting of a user struct that tells gdb | ||
24 | * what is present in the file. Directly after this is a | ||
25 | * copy of the task_struct, which is currently not used by gdb, | ||
26 | * but it may come in handy at some point. All of the registers | ||
27 | * are stored as part of the upage. The upage should always be | ||
28 | * only one page long. | ||
29 | * data: The data segment follows next. We use current->end_text to | ||
30 | * current->brk to pick up all of the user variables, plus any memory | ||
31 | * that may have been sbrk'ed. No attempt is made to determine if a | ||
32 | * page is demand-zero or if a page is totally unused, we just cover | ||
33 | * the entire range. All of the addresses are rounded in such a way | ||
34 | * that an integral number of pages is written. | ||
35 | * stack: We need the stack information in order to get a meaningful | ||
36 | * backtrace. We need to write the data from usp to | ||
37 | * current->start_stack, so we round each of these in order to be able | ||
38 | * to write an integer number of pages. | ||
39 | */ | ||
40 | |||
41 | struct user_fpu_struct { | ||
42 | /* We have no FPU (yet) */ | ||
43 | }; | ||
44 | |||
45 | struct user { | ||
46 | struct pt_regs regs; /* entire machine state */ | ||
47 | size_t u_tsize; /* text size (pages) */ | ||
48 | size_t u_dsize; /* data size (pages) */ | ||
49 | size_t u_ssize; /* stack size (pages) */ | ||
50 | unsigned long start_code; /* text starting address */ | ||
51 | unsigned long start_data; /* data starting address */ | ||
52 | unsigned long start_stack; /* stack starting address */ | ||
53 | long int signal; /* signal causing core dump */ | ||
54 | struct regs * u_ar0; /* help gdb find registers */ | ||
55 | unsigned long magic; /* identifies a core file */ | ||
56 | char u_comm[32]; /* user command name */ | ||
57 | }; | ||
58 | |||
59 | #define NBPG PAGE_SIZE | ||
60 | #define UPAGES 1 | ||
61 | #define HOST_TEXT_START_ADDR (u.start_code) | ||
62 | #define HOST_DATA_START_ADDR (u.start_data) | ||
63 | #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) | ||
64 | |||
65 | #endif /* __ASM_AVR32_USER_H */ | ||
diff --git a/include/linux/elf-em.h b/include/linux/elf-em.h index 6a5796c81c90..666e0a5f00fc 100644 --- a/include/linux/elf-em.h +++ b/include/linux/elf-em.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define EM_M32R 88 /* Renesas M32R */ | 31 | #define EM_M32R 88 /* Renesas M32R */ |
32 | #define EM_H8_300 46 /* Renesas H8/300,300H,H8S */ | 32 | #define EM_H8_300 46 /* Renesas H8/300,300H,H8S */ |
33 | #define EM_FRV 0x5441 /* Fujitsu FR-V */ | 33 | #define EM_FRV 0x5441 /* Fujitsu FR-V */ |
34 | #define EM_AVR32 0x18ad /* Atmel AVR32 */ | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * This is an interim value that we will use until the committee comes | 37 | * This is an interim value that we will use until the committee comes |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 554ee688a9f8..3f21cc79a134 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -277,7 +277,7 @@ config DEBUG_HIGHMEM | |||
277 | config DEBUG_BUGVERBOSE | 277 | config DEBUG_BUGVERBOSE |
278 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED | 278 | bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED |
279 | depends on BUG | 279 | depends on BUG |
280 | depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV | 280 | depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV |
281 | default !EMBEDDED | 281 | default !EMBEDDED |
282 | help | 282 | help |
283 | Say Y here to make BUG() panics output the file name and line number | 283 | Say Y here to make BUG() panics output the file name and line number |
@@ -315,7 +315,7 @@ config DEBUG_VM | |||
315 | 315 | ||
316 | config FRAME_POINTER | 316 | config FRAME_POINTER |
317 | bool "Compile the kernel with frame pointers" | 317 | bool "Compile the kernel with frame pointers" |
318 | depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390) | 318 | depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32) |
319 | default y if DEBUG_INFO && UML | 319 | default y if DEBUG_INFO && UML |
320 | help | 320 | help |
321 | If you say Y here the resulting kernel image will be slightly larger | 321 | If you say Y here the resulting kernel image will be slightly larger |