mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 21:21:47 +00:00
Xtensa patchset for v3.8-rc0
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQ0UyjAAoJEI9vqH3mFV2sBBQP/jYZURx5YSHlV8r/36Mjvsfx W4zmSsHCHjd7NTWtGF8/ICQ7ZL7Bylx8wRXowEWB94UhsNiWtqXJ6T4sESTWykge cI6hhyHw2vswm3BR9tvh6Lg5VZEZZN1eVEcqzj8vxc/i8acO1vYi3QKgAjmrQq9J 1YReYYXnC1+VSLl79io3hqiTMv/QDqnywzeOEHbh4mbGrSfjnEOvTsF5rHvYdutV xdVuHbWE5VzqgF2Pktlj/lW+sDw8jgY+fBSiRXNI7yoRba0TqGe2W4aLHqwM4734 vLEjfP0kfT/haMEz2HRYJJHMOJgJ8UAwVJFXhsYjTq9QqI+9NGNiq7f9F/gtWPSZ l+bfpMJkkeRzk3TI/lIni+hzURSO4uzZl84/KMlwWY5KJedCSAqaoLsdal48OT+a 8b8N25fZ59KCpGP4txKSmLI6BEbYIYJ0ZBKMjOx8x8O1zQD7/uV2eTr4rSIGqQRY N1x0Qw3R6ERIwMKE7EAB6ofFBvVYAiRR3E3pzgxIiXYurQ7n7Gj2OZbkSLaI1uOK SrIAdSRImqfma2eU9unWOuMrPl5eZJrEazvzqx8+pDduzf1ffG1fvCXdFYGSZUlX 2yz6MVgQ6hVXnhyDtxaCxuc5VHHoE1l+05VUK9rsqIfophZRMn9tCLeJkkjxiJ5s rbIwHdTmDSTWiO7pscgW =fxNt -----END PGP SIGNATURE----- Merge tag 'xtensa-20121218' of git://github.com/czankel/xtensa-linux Pull Xtensa patchset from Chris Zankel: "This contains support of device trees, many fixes, and code clean-ups" * tag 'xtensa-20121218' of git://github.com/czankel/xtensa-linux: (33 commits) xtensa: don't try to build DTB when OF is disabled xtensa: set the correct ethernet address for xtfpga xtensa: clean up files to make them code-style compliant xtensa: provide endianness macro for sparse xtensa: fix RASID SR initialization xtensa: initialize CPENABLE SR when core has one xtensa: reset all timers on initialization Use for_each_compatible_node() macro. xtensa: add XTFPGA DTS xtensa: add support for the XTFPGA boards xtensa: add device trees support xtensa: add IRQ domains support xtensa: add U-Boot image support (uImage). xtensa: clean up boot make rules xtensa: fix mb and wmb definitions xtensa: add s32c1i-based spinlock implementations xtensa: add s32c1i-based bitops implementations xtensa: add s32c1i-based atomic ops implementations xtensa: add s32c1i sanity check xtensa: add trap_set_handler function ...
This commit is contained in:
commit
2f0bf92513
44
Documentation/xtensa/atomctl.txt
Normal file
44
Documentation/xtensa/atomctl.txt
Normal file
@ -0,0 +1,44 @@
|
||||
We Have Atomic Operation Control (ATOMCTL) Register.
|
||||
This register determines the effect of using a S32C1I instruction
|
||||
with various combinations of:
|
||||
|
||||
1. With and without an Coherent Cache Controller which
|
||||
can do Atomic Transactions to the memory internally.
|
||||
|
||||
2. With and without An Intelligent Memory Controller which
|
||||
can do Atomic Transactions itself.
|
||||
|
||||
The Core comes up with a default value of for the three types of cache ops:
|
||||
|
||||
0x28: (WB: Internal, WT: Internal, BY:Exception)
|
||||
|
||||
On the FPGA Cards we typically simulate an Intelligent Memory controller
|
||||
which can implement RCW transactions. For FPGA cards with an External
|
||||
Memory controller we let it to the atomic operations internally while
|
||||
doing a Cached (WB) transaction and use the Memory RCW for un-cached
|
||||
operations.
|
||||
|
||||
For systems without an coherent cache controller, non-MX, we always
|
||||
use the memory controllers RCW, thought non-MX controlers likely
|
||||
support the Internal Operation.
|
||||
|
||||
CUSTOMER-WARNING:
|
||||
Virtually all customers buy their memory controllers from vendors that
|
||||
don't support atomic RCW memory transactions and will likely want to
|
||||
configure this register to not use RCW.
|
||||
|
||||
Developers might find using RCW in Bypass mode convenient when testing
|
||||
with the cache being bypassed; for example studying cache alias problems.
|
||||
|
||||
See Section 4.3.12.4 of ISA; Bits:
|
||||
|
||||
WB WT BY
|
||||
5 4 | 3 2 | 1 0
|
||||
2 Bit
|
||||
Field
|
||||
Values WB - Write Back WT - Write Thru BY - Bypass
|
||||
--------- --------------- ----------------- ----------------
|
||||
0 Exception Exception Exception
|
||||
1 RCW Transaction RCW Transaction RCW Transaction
|
||||
2 Internal Operation Exception Reserved
|
||||
3 Reserved Reserved Reserved
|
@ -17,6 +17,7 @@ config XTENSA
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select CLONE_BACKWARDS
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Xtensa processors are 32-bit RISC machines designed by Tensilica
|
||||
primarily for embedded systems. These processors are both
|
||||
@ -150,6 +151,15 @@ config XTENSA_PLATFORM_S6105
|
||||
select SERIAL_CONSOLE
|
||||
select NO_IOPORT
|
||||
|
||||
config XTENSA_PLATFORM_XTFPGA
|
||||
bool "XTFPGA"
|
||||
select SERIAL_CONSOLE
|
||||
select ETHOC
|
||||
select XTENSA_CALIBRATE_CCOUNT
|
||||
help
|
||||
XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605).
|
||||
This hardware is capable of running a full Linux distribution.
|
||||
|
||||
endchoice
|
||||
|
||||
|
||||
@ -177,6 +187,17 @@ config CMDLINE
|
||||
time by entering them here. As a minimum, you should specify the
|
||||
memory size and the root device (e.g., mem=64M root=/dev/nfs).
|
||||
|
||||
config USE_OF
|
||||
bool "Flattened Device Tree support"
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
help
|
||||
Include support for flattened device tree machine descriptions.
|
||||
|
||||
config BUILTIN_DTB
|
||||
string "DTB to build into the kernel image"
|
||||
depends on OF
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
source "drivers/pcmcia/Kconfig"
|
||||
|
@ -2,6 +2,26 @@ menu "Kernel hacking"
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config LD_NO_RELAX
|
||||
bool "Disable linker relaxation"
|
||||
default n
|
||||
help
|
||||
Enable this function to disable link-time optimizations.
|
||||
The default linker behavior is to combine identical literal
|
||||
values to reduce code size and remove unnecessary overhead from
|
||||
assembler-generated 'longcall' sequences.
|
||||
Enabling this option improves the link time but increases the
|
||||
code size, and possibly execution time.
|
||||
|
||||
config S32C1I_SELFTEST
|
||||
bool "Perform S32C1I instruction self-test at boot"
|
||||
default y
|
||||
help
|
||||
Enable this option to test S32C1I instruction behavior at boot.
|
||||
Correct operation of this instruction requires some cooperation from hardware
|
||||
external to the processor (such as bus bridge, bus fabric, or memory controller).
|
||||
It is easy to make wrong hardware configuration, this test should catch it early.
|
||||
|
||||
Say 'N' on stable hardware.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ endif
|
||||
platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000
|
||||
platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
|
||||
platform-$(CONFIG_XTENSA_PLATFORM_S6105) := s6105
|
||||
platform-$(CONFIG_XTENSA_PLATFORM_XTFPGA) := xtfpga
|
||||
|
||||
PLATFORM = $(platform-y)
|
||||
export PLATFORM
|
||||
@ -49,6 +50,17 @@ KBUILD_CFLAGS += -pipe -mlongcalls
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-option,-mforce-no-pic,)
|
||||
|
||||
ifneq ($(CONFIG_LD_NO_RELAX),)
|
||||
LDFLAGS := --no-relax
|
||||
endif
|
||||
|
||||
ifeq ($(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1)
|
||||
CHECKFLAGS += -D__XTENSA_EB__
|
||||
endif
|
||||
ifeq ($(shell echo -e __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1)
|
||||
CHECKFLAGS += -D__XTENSA_EL__
|
||||
endif
|
||||
|
||||
vardirs := $(patsubst %,arch/xtensa/variants/%/,$(variant-y))
|
||||
plfdirs := $(patsubst %,arch/xtensa/platforms/%/,$(platform-y))
|
||||
|
||||
@ -75,6 +87,10 @@ core-y += $(buildvar) $(buildplf)
|
||||
|
||||
libs-y += arch/xtensa/lib/ $(LIBGCC)
|
||||
|
||||
ifneq ($(CONFIG_BUILTIN_DTB),"")
|
||||
core-$(CONFIG_OF) += arch/xtensa/boot/
|
||||
endif
|
||||
|
||||
boot := arch/xtensa/boot
|
||||
|
||||
all: zImage
|
||||
@ -84,7 +100,9 @@ bzImage : zImage
|
||||
zImage: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $@
|
||||
|
||||
%.dtb:
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
define archhelp
|
||||
@echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
|
||||
endef
|
||||
|
||||
|
@ -22,12 +22,35 @@ subdir-y := lib
|
||||
# Subdirs for the boot loader(s)
|
||||
|
||||
bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf
|
||||
bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf
|
||||
bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf boot-uboot
|
||||
bootdir-$(CONFIG_XTENSA_PLATFORM_XTFPGA) += boot-redboot boot-elf boot-uboot
|
||||
|
||||
|
||||
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
|
||||
ifneq ($(CONFIG_BUILTIN_DTB),"")
|
||||
obj-$(CONFIG_OF) += $(BUILTIN_DTB)
|
||||
endif
|
||||
|
||||
# Rule to build device tree blobs
|
||||
$(obj)/%.dtb: $(src)/dts/%.dts FORCE
|
||||
$(call if_changed_dep,dtc)
|
||||
|
||||
clean-files := *.dtb.S
|
||||
|
||||
zImage Image: $(bootdir-y)
|
||||
|
||||
$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
|
||||
$(addprefix $(obj)/,$(host-progs))
|
||||
$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
|
||||
|
||||
OBJCOPYFLAGS = --strip-all -R .comment -R .note.gnu.build-id -O binary
|
||||
|
||||
vmlinux.bin: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
vmlinux.bin.gz: vmlinux.bin FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
boot-elf: vmlinux.bin
|
||||
boot-redboot: vmlinux.bin.gz
|
||||
boot-uboot: vmlinux.bin.gz
|
||||
|
@ -4,9 +4,6 @@
|
||||
# for more details.
|
||||
#
|
||||
|
||||
GZIP = gzip
|
||||
GZIP_FLAGS = -v9fc
|
||||
|
||||
ifeq ($(BIG_ENDIAN),1)
|
||||
OBJCOPY_ARGS := -O elf32-xtensa-be
|
||||
else
|
||||
@ -20,18 +17,17 @@ boot-y := bootstrap.o
|
||||
|
||||
OBJS := $(addprefix $(obj)/,$(boot-y))
|
||||
|
||||
vmlinux.tmp: vmlinux
|
||||
$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
|
||||
$^ $@
|
||||
|
||||
Image: vmlinux.tmp $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds
|
||||
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
|
||||
--add-section image=vmlinux.tmp \
|
||||
$(obj)/Image.o: vmlinux.bin $(OBJS)
|
||||
$(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
|
||||
--add-section image=vmlinux.bin \
|
||||
--set-section-flags image=contents,alloc,load,load,data \
|
||||
$(OBJS) $@.tmp
|
||||
$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
|
||||
-T arch/$(ARCH)/boot/boot-elf/boot.lds \
|
||||
-o arch/$(ARCH)/boot/$@.elf $@.tmp
|
||||
$(OBJS) $@
|
||||
|
||||
zImage: Image
|
||||
$(obj)/../Image.elf: $(obj)/Image.o $(obj)/boot.lds
|
||||
$(Q)$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
|
||||
-T $(obj)/boot.lds \
|
||||
--build-id=none \
|
||||
-o $@ $(obj)/Image.o
|
||||
$(Q)$(kecho) ' Kernel: $@ is ready'
|
||||
|
||||
zImage: $(obj)/../Image.elf
|
||||
|
@ -4,8 +4,6 @@
|
||||
# for more details.
|
||||
#
|
||||
|
||||
GZIP = gzip
|
||||
GZIP_FLAGS = -v9fc
|
||||
ifeq ($(BIG_ENDIAN),1)
|
||||
OBJCOPY_ARGS := -O elf32-xtensa-be
|
||||
else
|
||||
@ -21,17 +19,17 @@ LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a
|
||||
|
||||
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
|
||||
|
||||
vmlinux.tmp: vmlinux
|
||||
$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
|
||||
$^ $@
|
||||
|
||||
vmlinux.tmp.gz: vmlinux.tmp
|
||||
$(GZIP) $(GZIP_FLAGS) $^ > $@
|
||||
|
||||
zImage: vmlinux.tmp.gz $(OBJS) $(LIBS)
|
||||
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
|
||||
--add-section image=vmlinux.tmp.gz \
|
||||
$(obj)/zImage.o: vmlinux.bin.gz $(OBJS)
|
||||
$(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
|
||||
--add-section image=vmlinux.bin.gz \
|
||||
--set-section-flags image=contents,alloc,load,load,data \
|
||||
$(OBJS) $@.tmp
|
||||
$(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
|
||||
$(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/$@.redboot
|
||||
$(OBJS) $@
|
||||
|
||||
$(obj)/zImage.elf: $(obj)/zImage.o $(LIBS)
|
||||
$(Q)$(LD) $(LD_ARGS) -o $@ $^ -L/xtensa-elf/lib $(LIBGCC)
|
||||
|
||||
$(obj)/../zImage.redboot: $(obj)/zImage.elf
|
||||
$(Q)$(OBJCOPY) -S -O binary $< $@
|
||||
$(Q)$(kecho) ' Kernel: $@ is ready'
|
||||
|
||||
zImage: $(obj)/../zImage.redboot
|
||||
|
14
arch/xtensa/boot/boot-uboot/Makefile
Normal file
14
arch/xtensa/boot/boot-uboot/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU General Public
|
||||
# License. See the file "COPYING" in the main directory of this archive
|
||||
# for more details.
|
||||
#
|
||||
|
||||
UIMAGE_LOADADDR = 0xd0001000
|
||||
UIMAGE_COMPRESSION = gzip
|
||||
|
||||
$(obj)/../uImage: vmlinux.bin.gz FORCE
|
||||
$(call if_changed,uimage)
|
||||
$(Q)$(kecho) ' Kernel: $@ is ready'
|
||||
|
||||
zImage: $(obj)/../uImage
|
11
arch/xtensa/boot/dts/lx60.dts
Normal file
11
arch/xtensa/boot/dts/lx60.dts
Normal file
@ -0,0 +1,11 @@
|
||||
/dts-v1/;
|
||||
/include/ "xtfpga.dtsi"
|
||||
/include/ "xtfpga-flash-4m.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "xtensa,lx60";
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x04000000>;
|
||||
};
|
||||
};
|
11
arch/xtensa/boot/dts/ml605.dts
Normal file
11
arch/xtensa/boot/dts/ml605.dts
Normal file
@ -0,0 +1,11 @@
|
||||
/dts-v1/;
|
||||
/include/ "xtfpga.dtsi"
|
||||
/include/ "xtfpga-flash-16m.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "xtensa,ml605";
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x08000000>;
|
||||
};
|
||||
};
|
26
arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
Normal file
26
arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
Normal file
@ -0,0 +1,26 @@
|
||||
/ {
|
||||
flash: flash@f8000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0xf8000000 0x01000000>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
partition@0x0 {
|
||||
label = "boot loader area";
|
||||
reg = <0x00000000 0x00400000>;
|
||||
};
|
||||
partition@0x400000 {
|
||||
label = "kernel image";
|
||||
reg = <0x00400000 0x00600000>;
|
||||
};
|
||||
partition@0xa00000 {
|
||||
label = "data";
|
||||
reg = <0x00a00000 0x005e0000>;
|
||||
};
|
||||
partition@0xfe0000 {
|
||||
label = "boot environment";
|
||||
reg = <0x00fe0000 0x00020000>;
|
||||
};
|
||||
};
|
||||
};
|
18
arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
Normal file
18
arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
Normal file
@ -0,0 +1,18 @@
|
||||
/ {
|
||||
flash: flash@f8000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0xf8000000 0x00400000>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
partition@0x0 {
|
||||
label = "boot loader area";
|
||||
reg = <0x00000000 0x003f0000>;
|
||||
};
|
||||
partition@0x3f0000 {
|
||||
label = "boot environment";
|
||||
reg = <0x003f0000 0x00010000>;
|
||||
};
|
||||
};
|
||||
};
|
56
arch/xtensa/boot/dts/xtfpga.dtsi
Normal file
56
arch/xtensa/boot/dts/xtfpga.dtsi
Normal file
@ -0,0 +1,56 @@
|
||||
/ {
|
||||
compatible = "xtensa,xtfpga";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&pic>;
|
||||
|
||||
chosen {
|
||||
bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x06000000>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
compatible = "xtensa,cpu";
|
||||
reg = <0>;
|
||||
/* Filled in by platform_setup from FPGA register
|
||||
* clock-frequency = <100000000>;
|
||||
*/
|
||||
};
|
||||
};
|
||||
|
||||
pic: pic {
|
||||
compatible = "xtensa,pic";
|
||||
/* one cell: internal irq number,
|
||||
* two cells: second cell == 0: internal irq number
|
||||
* second cell == 1: external irq number
|
||||
*/
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
serial0: serial@fd050020 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550a";
|
||||
no-loopback-test;
|
||||
reg = <0xfd050020 0x20>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <0 1>; /* external irq 0 */
|
||||
/* Filled in by platform_setup from FPGA register
|
||||
* clock-frequency = <100000000>;
|
||||
*/
|
||||
};
|
||||
|
||||
enet0: ethoc@fd030000 {
|
||||
compatible = "opencores,ethoc";
|
||||
reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
|
||||
interrupts = <1 1>; /* external irq 1 */
|
||||
local-mac-address = [00 50 c2 13 6f 00];
|
||||
};
|
||||
};
|
@ -66,19 +66,35 @@
|
||||
*/
|
||||
static inline void atomic_add(int i, atomic_t * v)
|
||||
{
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15, "__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"add %0, %0, %1 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" add %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (i), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15, "__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" add %0, %0, %1\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,19 +106,35 @@ static inline void atomic_add(int i, atomic_t * v)
|
||||
*/
|
||||
static inline void atomic_sub(int i, atomic_t *v)
|
||||
{
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15, "__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"sub %0, %0, %1 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" sub %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (i), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15, "__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" sub %0, %0, %1\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -111,40 +143,78 @@ static inline void atomic_sub(int i, atomic_t *v)
|
||||
|
||||
static inline int atomic_add_return(int i, atomic_t * v)
|
||||
{
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15,"__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"add %0, %0, %1 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" add %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
" add %0, %0, %2\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (i), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return vval;
|
||||
return result;
|
||||
#else
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15,"__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" add %0, %0, %1\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
|
||||
return vval;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int atomic_sub_return(int i, atomic_t * v)
|
||||
{
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15,"__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"sub %0, %0, %1 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" sub %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
" sub %0, %0, %2\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (i), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return vval;
|
||||
return result;
|
||||
#else
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15,"__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" sub %0, %0, %1\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval)
|
||||
: "a" (i), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
|
||||
return vval;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,38 +321,70 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
|
||||
|
||||
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
|
||||
{
|
||||
unsigned int all_f = -1;
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15,"__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"xor %1, %4, %3 \n\t"
|
||||
"and %0, %0, %4 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval), "=a" (mask)
|
||||
: "a" (v), "a" (all_f), "1" (mask)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" and %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (~mask), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
unsigned int all_f = -1;
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15,"__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" xor %1, %4, %3\n"
|
||||
" and %0, %0, %4\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval), "=a" (mask)
|
||||
: "a" (v), "a" (all_f), "1" (mask)
|
||||
: "a15", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
|
||||
{
|
||||
unsigned int vval;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp;
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"rsil a15,"__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %2, 0 \n\t"
|
||||
"or %0, %0, %1 \n\t"
|
||||
"s32i %0, %2, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n"
|
||||
: "=&a" (vval)
|
||||
: "a" (mask), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" or %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (mask), "a" (v)
|
||||
: "memory"
|
||||
);
|
||||
#else
|
||||
unsigned int vval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" rsil a15,"__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %2, 0\n"
|
||||
" or %0, %0, %1\n"
|
||||
" s32i %0, %2, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (vval)
|
||||
: "a" (mask), "a" (v)
|
||||
: "a15", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Atomic operations are already serializing */
|
||||
@ -294,4 +396,3 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _XTENSA_ATOMIC_H */
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2005 Tensilica Inc.
|
||||
* Copyright (C) 2001 - 2012 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_SYSTEM_H
|
||||
@ -12,8 +12,8 @@
|
||||
#define smp_read_barrier_depends() do { } while(0)
|
||||
#define read_barrier_depends() do { } while(0)
|
||||
|
||||
#define mb() barrier()
|
||||
#define rmb() mb()
|
||||
#define mb() ({ __asm__ __volatile__("memw" : : : "memory"); })
|
||||
#define rmb() barrier()
|
||||
#define wmb() mb()
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -29,7 +29,6 @@
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
|
||||
#include <asm-generic/bitops/atomic.h>
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
|
||||
#if XCHAL_HAVE_NSA
|
||||
@ -104,6 +103,132 @@ static inline unsigned long __fls(unsigned long word)
|
||||
#endif
|
||||
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
|
||||
static inline void set_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" or %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (mask), "a" (p)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" and %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (~mask), "a" (p)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void change_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" xor %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (mask), "a" (p)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_and_set_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" or %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (mask), "a" (p)
|
||||
: "memory");
|
||||
|
||||
return tmp & mask;
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" and %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (~mask), "a" (p)
|
||||
: "memory");
|
||||
|
||||
return tmp & mask;
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_and_change_bit(unsigned int bit, volatile unsigned long *p)
|
||||
{
|
||||
unsigned long tmp, value;
|
||||
unsigned long mask = 1UL << (bit & 31);
|
||||
|
||||
p += bit >> 5;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %3, 0\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" xor %0, %1, %2\n"
|
||||
" s32c1i %0, %3, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp), "=&a" (value)
|
||||
: "a" (mask), "a" (p)
|
||||
: "memory");
|
||||
|
||||
return tmp & mask;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <asm-generic/bitops/atomic.h>
|
||||
|
||||
#endif /* XCHAL_HAVE_S32C1I */
|
||||
|
||||
#include <asm-generic/bitops/find.h>
|
||||
#include <asm-generic/bitops/le.h>
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */
|
||||
#define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */
|
||||
#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */
|
||||
#define BP_TAG_FDT 0x1006 /* flat device tree addr */
|
||||
|
||||
#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */
|
||||
#define BP_TAG_LAST 0x7E0B /* last tag */
|
||||
@ -31,15 +32,15 @@
|
||||
/* All records are aligned to 4 bytes */
|
||||
|
||||
typedef struct bp_tag {
|
||||
unsigned short id; /* tag id */
|
||||
unsigned short size; /* size of this record excluding the structure*/
|
||||
unsigned long data[0]; /* data */
|
||||
unsigned short id; /* tag id */
|
||||
unsigned short size; /* size of this record excluding the structure*/
|
||||
unsigned long data[0]; /* data */
|
||||
} bp_tag_t;
|
||||
|
||||
typedef struct meminfo {
|
||||
unsigned long type;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
unsigned long type;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
} meminfo_t;
|
||||
|
||||
#define SYSMEM_BANKS_MAX 5
|
||||
@ -48,14 +49,11 @@ typedef struct meminfo {
|
||||
#define MEMORY_TYPE_NONE 0x2000
|
||||
|
||||
typedef struct sysmem_info {
|
||||
int nr_banks;
|
||||
meminfo_t bank[SYSMEM_BANKS_MAX];
|
||||
int nr_banks;
|
||||
meminfo_t bank[SYSMEM_BANKS_MAX];
|
||||
} sysmem_info_t;
|
||||
|
||||
extern sysmem_info_t sysmem;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -174,4 +174,3 @@
|
||||
__loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
|
||||
|
||||
.endm
|
||||
|
||||
|
@ -104,7 +104,8 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
||||
extern void flush_dcache_page(struct page*);
|
||||
extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
|
||||
extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long);
|
||||
extern void flush_cache_page(struct vm_area_struct*,
|
||||
unsigned long, unsigned long);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -36,8 +36,9 @@ asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
|
||||
* better 64-bit) boundary
|
||||
*/
|
||||
|
||||
asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, int len, __wsum sum,
|
||||
int *src_err_ptr, int *dst_err_ptr);
|
||||
asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
|
||||
int len, __wsum sum,
|
||||
int *src_err_ptr, int *dst_err_ptr);
|
||||
|
||||
/*
|
||||
* Note: when you get a NULL pointer exception here this means someone
|
||||
@ -54,7 +55,7 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst,
|
||||
|
||||
static inline
|
||||
__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
|
||||
int len, __wsum sum, int *err_ptr)
|
||||
int len, __wsum sum, int *err_ptr)
|
||||
{
|
||||
return csum_partial_copy_generic((__force const void *)src, dst,
|
||||
len, sum, err_ptr, NULL);
|
||||
@ -112,7 +113,8 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||
/* Since the input registers which are loaded with iph and ihl
|
||||
are modified, we must also specify them as outputs, or gcc
|
||||
will assume they contain their original values. */
|
||||
: "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr)
|
||||
: "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp),
|
||||
"=&r" (endaddr)
|
||||
: "1" (iph), "2" (ihl)
|
||||
: "memory");
|
||||
|
||||
@ -168,7 +170,7 @@ static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
|
||||
|
||||
static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
|
||||
{
|
||||
return csum_fold (csum_partial(buff, len, 0));
|
||||
return csum_fold (csum_partial(buff, len, 0));
|
||||
}
|
||||
|
||||
#define _HAVE_ARCH_IPV6_CSUM
|
||||
@ -238,11 +240,12 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||
* Copy and checksum to user
|
||||
*/
|
||||
#define HAVE_CSUM_COPY_USER
|
||||
static __inline__ __wsum csum_and_copy_to_user(const void *src, void __user *dst,
|
||||
int len, __wsum sum, int *err_ptr)
|
||||
static __inline__ __wsum csum_and_copy_to_user(const void *src,
|
||||
void __user *dst, int len,
|
||||
__wsum sum, int *err_ptr)
|
||||
{
|
||||
if (access_ok(VERIFY_WRITE, dst, len))
|
||||
return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
|
||||
return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr);
|
||||
|
||||
if (len)
|
||||
*err_ptr = -EFAULT;
|
||||
|
@ -22,17 +22,30 @@
|
||||
static inline unsigned long
|
||||
__cmpxchg_u32(volatile int *p, int old, int new)
|
||||
{
|
||||
__asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %1, 0 \n\t"
|
||||
"bne %0, %2, 1f \n\t"
|
||||
"s32i %3, %1, 0 \n\t"
|
||||
"1: \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n\t"
|
||||
: "=&a" (old)
|
||||
: "a" (p), "a" (old), "r" (new)
|
||||
: "a15", "memory");
|
||||
return old;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
__asm__ __volatile__(
|
||||
" wsr %2, scompare1\n"
|
||||
" s32c1i %0, %1, 0\n"
|
||||
: "+a" (new)
|
||||
: "a" (p), "a" (old)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return new;
|
||||
#else
|
||||
__asm__ __volatile__(
|
||||
" rsil a15, "__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %1, 0\n"
|
||||
" bne %0, %2, 1f\n"
|
||||
" s32i %3, %1, 0\n"
|
||||
"1:\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (old)
|
||||
: "a" (p), "a" (old), "r" (new)
|
||||
: "a15", "memory");
|
||||
return old;
|
||||
#endif
|
||||
}
|
||||
/* This function doesn't exist, so you'll get a linker error
|
||||
* if something tries to do an invalid cmpxchg(). */
|
||||
@ -93,19 +106,36 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
|
||||
|
||||
static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
|
||||
{
|
||||
unsigned long tmp;
|
||||
__asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
|
||||
"l32i %0, %1, 0 \n\t"
|
||||
"s32i %2, %1, 0 \n\t"
|
||||
"wsr a15, ps \n\t"
|
||||
"rsync \n\t"
|
||||
: "=&a" (tmp)
|
||||
: "a" (m), "a" (val)
|
||||
: "a15", "memory");
|
||||
return tmp;
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
unsigned long tmp, result;
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %2, 0\n"
|
||||
" mov %0, %3\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" s32c1i %0, %2, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (m), "a" (val)
|
||||
: "memory"
|
||||
);
|
||||
return result;
|
||||
#else
|
||||
unsigned long tmp;
|
||||
__asm__ __volatile__(
|
||||
" rsil a15, "__stringify(LOCKLEVEL)"\n"
|
||||
" l32i %0, %1, 0\n"
|
||||
" s32i %2, %1, 0\n"
|
||||
" wsr a15, ps\n"
|
||||
" rsync\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (m), "a" (val)
|
||||
: "a15", "memory");
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
|
||||
#define xchg(ptr,x) \
|
||||
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
|
||||
|
||||
/*
|
||||
* This only works if the compiler isn't horribly bad at optimizing.
|
||||
|
@ -30,7 +30,7 @@ static inline struct task_struct *get_current(void)
|
||||
|
||||
#define GET_CURRENT(reg,sp) \
|
||||
GET_THREAD_INFO(reg,sp); \
|
||||
l32i reg, reg, TI_TASK \
|
||||
l32i reg, reg, TI_TASK \
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,9 +19,9 @@ extern unsigned long loops_per_jiffy;
|
||||
|
||||
static inline void __delay(unsigned long loops)
|
||||
{
|
||||
/* 2 cycles per loop. */
|
||||
__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
|
||||
: "=r" (loops) : "0" (loops));
|
||||
/* 2 cycles per loop. */
|
||||
__asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
|
||||
: "=r" (loops) : "0" (loops));
|
||||
}
|
||||
|
||||
static __inline__ u32 xtensa_get_ccount(void)
|
||||
@ -46,4 +46,3 @@ static __inline__ void udelay (unsigned long usecs)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
|
||||
|
||||
/*
|
||||
* DMA-consistent mapping functions.
|
||||
*/
|
||||
@ -98,8 +100,8 @@ dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
|
||||
size_t size, enum dma_data_direction direction)
|
||||
{
|
||||
consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
|
||||
}
|
||||
|
@ -168,11 +168,11 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *);
|
||||
*/
|
||||
|
||||
#define ELF_PLAT_INIT(_r, load_addr) \
|
||||
do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \
|
||||
_r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \
|
||||
_r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \
|
||||
_r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \
|
||||
} while (0)
|
||||
do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \
|
||||
_r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \
|
||||
_r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \
|
||||
_r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
xtregs_opt_t opt;
|
||||
|
@ -14,4 +14,3 @@
|
||||
extern void flush_cache_kmaps(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
55
arch/xtensa/include/asm/initialize_mmu.h
Normal file
55
arch/xtensa/include/asm/initialize_mmu.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* arch/xtensa/include/asm/initialize_mmu.h
|
||||
*
|
||||
* Initializes MMU:
|
||||
*
|
||||
* For the new V3 MMU we remap the TLB from virtual == physical
|
||||
* to the standard Linux mapping used in earlier MMU's.
|
||||
*
|
||||
* The the MMU we also support a new configuration register that
|
||||
* specifies how the S32C1I instruction operates with the cache
|
||||
* controller.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of
|
||||
* this archive for more details.
|
||||
*
|
||||
* Copyright (C) 2008 - 2012 Tensilica, Inc.
|
||||
*
|
||||
* Marc Gauthier <marc@tensilica.com>
|
||||
* Pete Delaney <piet@tensilica.com>
|
||||
*/
|
||||
|
||||
#ifndef _XTENSA_INITIALIZE_MMU_H
|
||||
#define _XTENSA_INITIALIZE_MMU_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#define XTENSA_HWVERSION_RC_2009_0 230000
|
||||
|
||||
.macro initialize_mmu
|
||||
|
||||
#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
|
||||
/*
|
||||
* We Have Atomic Operation Control (ATOMCTL) Register; Initialize it.
|
||||
* For details see Documentation/xtensa/atomctl.txt
|
||||
*/
|
||||
#if XCHAL_DCACHE_IS_COHERENT
|
||||
movi a3, 0x25 /* For SMP/MX -- internal for writeback,
|
||||
* RCW otherwise
|
||||
*/
|
||||
#else
|
||||
movi a3, 0x29 /* non-MX -- Most cores use Std Memory
|
||||
* Controlers which usually can't use RCW
|
||||
*/
|
||||
#endif
|
||||
wsr a3, atomctl
|
||||
#endif /* XCHAL_HAVE_S32C1I &&
|
||||
* (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
|
||||
*/
|
||||
|
||||
.endm
|
||||
|
||||
#endif /*__ASSEMBLY__*/
|
||||
|
||||
#endif /* _XTENSA_INITIALIZE_MMU_H */
|
@ -107,7 +107,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||
|
||||
|
||||
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
unsigned long asid = asid_cache;
|
||||
|
||||
|
@ -2,7 +2,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
static inline int init_new_context(struct task_struct *tsk,struct mm_struct *mm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,19 +29,19 @@
|
||||
* PAGE_SHIFT determines the page size
|
||||
*/
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
|
||||
#define MAX_MEM_PFN XCHAL_KSEG_SIZE
|
||||
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
|
||||
#define MAX_MEM_PFN XCHAL_KSEG_SIZE
|
||||
#else
|
||||
#define PAGE_OFFSET 0
|
||||
#define MAX_MEM_PFN (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE)
|
||||
#define PAGE_OFFSET 0
|
||||
#define MAX_MEM_PFN (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE)
|
||||
#endif
|
||||
|
||||
#define PGTABLE_START 0x80000000
|
||||
#define PGTABLE_START 0x80000000
|
||||
|
||||
/*
|
||||
* Cache aliasing:
|
||||
@ -161,7 +161,9 @@ extern void copy_user_page(void*, void*, unsigned long, struct page*);
|
||||
|
||||
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
|
||||
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
|
||||
#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
|
||||
#define pfn_valid(pfn) \
|
||||
((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
|
||||
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
# error CONFIG_DISCONTIGMEM not supported
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ struct pci_space {
|
||||
struct pci_controller {
|
||||
int index; /* used for pci_controller_num */
|
||||
struct pci_controller *next;
|
||||
struct pci_bus *bus;
|
||||
struct pci_bus *bus;
|
||||
void *arch_data;
|
||||
|
||||
int first_busno;
|
||||
|
@ -53,7 +53,7 @@ struct pci_dev;
|
||||
|
||||
/* Map a range of PCI memory or I/O space for a device into user space */
|
||||
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
|
||||
#define HAVE_PCI_MMAP 1
|
||||
|
@ -42,7 +42,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
|
||||
extern struct kmem_cache *pgtable_cache;
|
||||
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
unsigned long address)
|
||||
{
|
||||
return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT);
|
||||
|
@ -284,7 +284,7 @@ struct vm_area_struct;
|
||||
|
||||
static inline int
|
||||
ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
pte_t *ptep)
|
||||
{
|
||||
pte_t pte = *ptep;
|
||||
if (!pte_young(pte))
|
||||
@ -304,8 +304,8 @@ ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
static inline void
|
||||
ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte = *ptep;
|
||||
update_pte(ptep, pte_wrprotect(pte));
|
||||
pte_t pte = *ptep;
|
||||
update_pte(ptep, pte_wrprotect(pte));
|
||||
}
|
||||
|
||||
/* to find an entry in a kernel page-table-directory */
|
||||
@ -399,7 +399,7 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
|
||||
*/
|
||||
|
||||
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
|
||||
remap_pfn_range(vma, from, pfn, size, prot)
|
||||
remap_pfn_range(vma, from, pfn, size, prot)
|
||||
|
||||
typedef pte_t *pte_addr_t;
|
||||
|
||||
|
@ -75,4 +75,3 @@ extern int platform_pcibios_fixup (void);
|
||||
extern void platform_calibrate_ccount (void);
|
||||
|
||||
#endif /* _XTENSA_PLATFORM_H */
|
||||
|
||||
|
@ -89,7 +89,7 @@
|
||||
#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
struct thread_struct {
|
||||
@ -145,10 +145,10 @@ struct thread_struct {
|
||||
* set_thread_state in signal.c depends on it.
|
||||
*/
|
||||
#define USER_PS_VALUE ((1 << PS_WOE_BIT) | \
|
||||
(1 << PS_CALLINC_SHIFT) | \
|
||||
(USER_RING << PS_RING_SHIFT) | \
|
||||
(1 << PS_UM_BIT) | \
|
||||
(1 << PS_EXCM_BIT))
|
||||
(1 << PS_CALLINC_SHIFT) | \
|
||||
(USER_RING << PS_RING_SHIFT) | \
|
||||
(1 << PS_UM_BIT) | \
|
||||
(1 << PS_EXCM_BIT))
|
||||
|
||||
/* Clearing a0 terminates the backtrace. */
|
||||
#define start_thread(regs, new_pc, new_sp) \
|
||||
|
6
arch/xtensa/include/asm/prom.h
Normal file
6
arch/xtensa/include/asm/prom.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _XTENSA_ASM_PROM_H
|
||||
#define _XTENSA_ASM_PROM_H
|
||||
|
||||
#define HAVE_ARCH_DEVTREE_FIXUPS
|
||||
|
||||
#endif /* _XTENSA_ASM_PROM_H */
|
@ -37,7 +37,7 @@ struct pt_regs {
|
||||
unsigned long windowstart; /* 52 */
|
||||
unsigned long syscall; /* 56 */
|
||||
unsigned long icountlevel; /* 60 */
|
||||
int reserved[1]; /* 64 */
|
||||
unsigned long scompare1; /* 64 */
|
||||
|
||||
/* Additional configurable registers that are used by the compiler. */
|
||||
xtregs_opt_t xtregs_opt;
|
||||
@ -55,7 +55,7 @@ struct pt_regs {
|
||||
|
||||
# define arch_has_single_step() (1)
|
||||
# define task_pt_regs(tsk) ((struct pt_regs*) \
|
||||
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
|
||||
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
|
||||
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
|
||||
# define instruction_pointer(regs) ((regs)->pc)
|
||||
|
||||
|
@ -52,6 +52,10 @@
|
||||
#define EXCCAUSE_SPECULATION 7
|
||||
#define EXCCAUSE_PRIVILEGED 8
|
||||
#define EXCCAUSE_UNALIGNED 9
|
||||
#define EXCCAUSE_INSTR_DATA_ERROR 12
|
||||
#define EXCCAUSE_LOAD_STORE_DATA_ERROR 13
|
||||
#define EXCCAUSE_INSTR_ADDR_ERROR 14
|
||||
#define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15
|
||||
#define EXCCAUSE_ITLB_MISS 16
|
||||
#define EXCCAUSE_ITLB_MULTIHIT 17
|
||||
#define EXCCAUSE_ITLB_PRIVILEGE 18
|
||||
@ -105,4 +109,3 @@
|
||||
#define DEBUGCAUSE_ICOUNT_BIT 0 /* ICOUNT would incr. to zero */
|
||||
|
||||
#endif /* _XTENSA_SPECREG_H */
|
||||
|
||||
|
@ -11,6 +11,192 @@
|
||||
#ifndef _XTENSA_SPINLOCK_H
|
||||
#define _XTENSA_SPINLOCK_H
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
/*
|
||||
* spinlock
|
||||
*
|
||||
* There is at most one owner of a spinlock. There are not different
|
||||
* types of spinlock owners like there are for rwlocks (see below).
|
||||
*
|
||||
* When trying to obtain a spinlock, the function "spins" forever, or busy-
|
||||
* waits, until the lock is obtained. When spinning, presumably some other
|
||||
* owner will soon give up the spinlock making it available to others. Use
|
||||
* the trylock functions to avoid spinning forever.
|
||||
*
|
||||
* possible values:
|
||||
*
|
||||
* 0 nobody owns the spinlock
|
||||
* 1 somebody owns the spinlock
|
||||
*/
|
||||
|
||||
#define __raw_spin_is_locked(x) ((x)->slock != 0)
|
||||
#define __raw_spin_unlock_wait(lock) \
|
||||
do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
|
||||
|
||||
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
|
||||
|
||||
static inline void __raw_spin_lock(raw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" wsr %0, scompare1\n"
|
||||
"1: movi %0, 1\n"
|
||||
" s32c1i %0, %1, 0\n"
|
||||
" bnez %0, 1b\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&lock->slock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* Returns 1 if the lock is obtained, 0 otherwise. */
|
||||
|
||||
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" wsr %0, scompare1\n"
|
||||
" movi %0, 1\n"
|
||||
" s32c1i %0, %1, 0\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&lock->slock)
|
||||
: "memory");
|
||||
|
||||
return tmp == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" s32ri %0, %1, 0\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&lock->slock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* rwlock
|
||||
*
|
||||
* Read-write locks are really a more flexible spinlock. They allow
|
||||
* multiple readers but only one writer. Write ownership is exclusive
|
||||
* (i.e., all other readers and writers are blocked from ownership while
|
||||
* there is a write owner). These rwlocks are unfair to writers. Writers
|
||||
* can be starved for an indefinite time by readers.
|
||||
*
|
||||
* possible values:
|
||||
*
|
||||
* 0 nobody owns the rwlock
|
||||
* >0 one or more readers own the rwlock
|
||||
* (the positive value is the actual number of readers)
|
||||
* 0x80000000 one writer owns the rwlock, no other writers, no readers
|
||||
*/
|
||||
|
||||
#define __raw_write_can_lock(x) ((x)->lock == 0)
|
||||
|
||||
static inline void __raw_write_lock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" wsr %0, scompare1\n"
|
||||
"1: movi %0, 1\n"
|
||||
" slli %0, %0, 31\n"
|
||||
" s32c1i %0, %1, 0\n"
|
||||
" bnez %0, 1b\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* Returns 1 if the lock is obtained, 0 otherwise. */
|
||||
|
||||
static inline int __raw_write_trylock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" wsr %0, scompare1\n"
|
||||
" movi %0, 1\n"
|
||||
" slli %0, %0, 31\n"
|
||||
" s32c1i %0, %1, 0\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
|
||||
return tmp == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline void __raw_write_unlock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" s32ri %0, %1, 0\n"
|
||||
: "=&a" (tmp)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void __raw_read_lock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned long result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %2, 0\n"
|
||||
" bltz %1, 1b\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" addi %0, %1, 1\n"
|
||||
" s32c1i %0, %2, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* Returns 1 if the lock is obtained, 0 otherwise. */
|
||||
|
||||
static inline int __raw_read_trylock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long result;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" l32i %1, %2, 0\n"
|
||||
" addi %0, %1, 1\n"
|
||||
" bltz %0, 1f\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" s32c1i %0, %2, 0\n"
|
||||
" sub %0, %0, %1\n"
|
||||
"1:\n"
|
||||
: "=&a" (result), "=&a" (tmp)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
static inline void __raw_read_unlock(raw_rwlock_t *rw)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: l32i %1, %2, 0\n"
|
||||
" addi %0, %1, -1\n"
|
||||
" wsr %1, scompare1\n"
|
||||
" s32c1i %0, %2, 0\n"
|
||||
" bne %0, %1, 1b\n"
|
||||
: "=&a" (tmp1), "=&a" (tmp2)
|
||||
: "a" (&rw->lock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#endif /* _XTENSA_SPINLOCK_H */
|
||||
|
@ -25,9 +25,10 @@ asmlinkage long xtensa_fadvise64_64(int, int,
|
||||
/* Should probably move to linux/syscalls.h */
|
||||
struct pollfd;
|
||||
asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
|
||||
fd_set __user *exp, struct timespec __user *tsp, void __user *sig);
|
||||
fd_set __user *exp, struct timespec __user *tsp,
|
||||
void __user *sig);
|
||||
asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
|
||||
struct timespec __user *tsp, const sigset_t __user *sigmask,
|
||||
size_t sigsetsize);
|
||||
asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
|
||||
size_t sigsetsize);
|
||||
struct timespec __user *tsp,
|
||||
const sigset_t __user *sigmask,
|
||||
size_t sigsetsize);
|
||||
asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);
|
||||
|
23
arch/xtensa/include/asm/traps.h
Normal file
23
arch/xtensa/include/asm/traps.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* arch/xtensa/include/asm/traps.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2012 Tensilica Inc.
|
||||
*/
|
||||
#ifndef _XTENSA_TRAPS_H
|
||||
#define _XTENSA_TRAPS_H
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
/*
|
||||
* handler must be either of the following:
|
||||
* void (*)(struct pt_regs *regs);
|
||||
* void (*)(struct pt_regs *regs, unsigned long exccause);
|
||||
*/
|
||||
extern void * __init trap_set_handler(int cause, void *handler);
|
||||
extern void do_unhandled(struct pt_regs *regs, unsigned long exccause);
|
||||
|
||||
#endif /* _XTENSA_TRAPS_H */
|
@ -180,7 +180,8 @@
|
||||
#define segment_eq(a,b) ((a).seg == (b).seg)
|
||||
|
||||
#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
|
||||
#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
|
||||
#define __user_ok(addr,size) \
|
||||
(((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
|
||||
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
|
||||
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
|
||||
|
||||
@ -234,10 +235,10 @@ do { \
|
||||
int __cb; \
|
||||
retval = 0; \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \
|
||||
case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \
|
||||
case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \
|
||||
case 8: { \
|
||||
case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \
|
||||
case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \
|
||||
case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \
|
||||
case 8: { \
|
||||
__typeof__(*ptr) __v64 = x; \
|
||||
retval = __copy_to_user(ptr,&__v64,8); \
|
||||
break; \
|
||||
@ -291,7 +292,7 @@ do { \
|
||||
* __check_align_* macros still work.
|
||||
*/
|
||||
#define __put_user_asm(x, addr, err, align, insn, cb) \
|
||||
__asm__ __volatile__( \
|
||||
__asm__ __volatile__( \
|
||||
__check_align_##align \
|
||||
"1: "insn" %2, %3, 0 \n" \
|
||||
"2: \n" \
|
||||
@ -301,8 +302,8 @@ do { \
|
||||
" .long 2b \n" \
|
||||
"5: \n" \
|
||||
" l32r %1, 4b \n" \
|
||||
" movi %0, %4 \n" \
|
||||
" jx %1 \n" \
|
||||
" movi %0, %4 \n" \
|
||||
" jx %1 \n" \
|
||||
" .previous \n" \
|
||||
" .section __ex_table,\"a\" \n" \
|
||||
" .long 1b, 5b \n" \
|
||||
@ -334,13 +335,13 @@ extern long __get_user_bad(void);
|
||||
do { \
|
||||
int __cb; \
|
||||
retval = 0; \
|
||||
switch (size) { \
|
||||
case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \
|
||||
case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \
|
||||
case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \
|
||||
case 8: retval = __copy_from_user(&x,ptr,8); break; \
|
||||
default: (x) = __get_user_bad(); \
|
||||
} \
|
||||
switch (size) { \
|
||||
case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \
|
||||
case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \
|
||||
case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \
|
||||
case 8: retval = __copy_from_user(&x,ptr,8); break; \
|
||||
default: (x) = __get_user_bad(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
@ -349,7 +350,7 @@ do { \
|
||||
* __check_align_* macros still work.
|
||||
*/
|
||||
#define __get_user_asm(x, addr, err, align, insn, cb) \
|
||||
__asm__ __volatile__( \
|
||||
__asm__ __volatile__( \
|
||||
__check_align_##align \
|
||||
"1: "insn" %2, %3, 0 \n" \
|
||||
"2: \n" \
|
||||
@ -360,8 +361,8 @@ do { \
|
||||
"5: \n" \
|
||||
" l32r %1, 4b \n" \
|
||||
" movi %2, 0 \n" \
|
||||
" movi %0, %4 \n" \
|
||||
" jx %1 \n" \
|
||||
" movi %0, %4 \n" \
|
||||
" jx %1 \n" \
|
||||
" .previous \n" \
|
||||
" .section __ex_table,\"a\" \n" \
|
||||
" .long 1b, 5b \n" \
|
||||
@ -421,8 +422,10 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
|
||||
|
||||
#define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n))
|
||||
#define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n))
|
||||
#define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n))
|
||||
#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
|
||||
#define __copy_to_user(to,from,n) \
|
||||
__generic_copy_to_user_nocheck((to),(from),(n))
|
||||
#define __copy_from_user(to,from,n) \
|
||||
__generic_copy_from_user_nocheck((to),(from),(n))
|
||||
#define __copy_to_user_inatomic __copy_to_user
|
||||
#define __copy_from_user_inatomic __copy_from_user
|
||||
|
||||
|
@ -23,13 +23,13 @@ obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
|
||||
#
|
||||
# Replicate rules in scripts/Makefile.build
|
||||
|
||||
sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \
|
||||
-e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \
|
||||
sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \
|
||||
-e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \
|
||||
-e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g'
|
||||
|
||||
quiet_cmd__cpp_lds_S = LDS $@
|
||||
cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \
|
||||
| sed $(sed-y) >$@
|
||||
cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \
|
||||
| sed $(sed-y) >$@
|
||||
|
||||
$(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE
|
||||
$(call if_changed_dep,_cpp_lds_S)
|
||||
|
@ -442,7 +442,7 @@ ENTRY(fast_unaligned)
|
||||
mov a1, a2
|
||||
|
||||
rsr a0, ps
|
||||
bbsi.l a2, PS_UM_BIT, 1f # jump if user mode
|
||||
bbsi.l a2, PS_UM_BIT, 1f # jump if user mode
|
||||
|
||||
movi a0, _kernel_exception
|
||||
jx a0
|
||||
@ -450,6 +450,6 @@ ENTRY(fast_unaligned)
|
||||
1: movi a0, _user_exception
|
||||
jx a0
|
||||
|
||||
ENDPROC(fast_unaligned)
|
||||
|
||||
#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
|
||||
|
||||
|
@ -41,6 +41,7 @@ int main(void)
|
||||
DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
|
||||
DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel));
|
||||
DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
|
||||
DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1));
|
||||
DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
|
||||
DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
|
||||
DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1]));
|
||||
@ -91,7 +92,8 @@ int main(void)
|
||||
#endif
|
||||
DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user));
|
||||
DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t));
|
||||
DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
|
||||
DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, \
|
||||
thread.current_ds));
|
||||
|
||||
/* struct mm_struct */
|
||||
DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
|
||||
@ -108,4 +110,3 @@ int main(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -43,10 +43,13 @@
|
||||
/* IO protection is currently unsupported. */
|
||||
|
||||
ENTRY(fast_io_protect)
|
||||
|
||||
wsr a0, excsave1
|
||||
movi a0, unrecoverable_exception
|
||||
callx0 a0
|
||||
|
||||
ENDPROC(fast_io_protect)
|
||||
|
||||
#if XTENSA_HAVE_COPROCESSORS
|
||||
|
||||
/*
|
||||
@ -139,6 +142,7 @@ ENTRY(fast_io_protect)
|
||||
*/
|
||||
|
||||
ENTRY(coprocessor_save)
|
||||
|
||||
entry a1, 32
|
||||
s32i a0, a1, 0
|
||||
movi a0, .Lsave_cp_regs_jump_table
|
||||
@ -150,7 +154,10 @@ ENTRY(coprocessor_save)
|
||||
1: l32i a0, a1, 0
|
||||
retw
|
||||
|
||||
ENDPROC(coprocessor_save)
|
||||
|
||||
ENTRY(coprocessor_load)
|
||||
|
||||
entry a1, 32
|
||||
s32i a0, a1, 0
|
||||
movi a0, .Lload_cp_regs_jump_table
|
||||
@ -162,8 +169,10 @@ ENTRY(coprocessor_load)
|
||||
1: l32i a0, a1, 0
|
||||
retw
|
||||
|
||||
ENDPROC(coprocessor_load)
|
||||
|
||||
/*
|
||||
* coprocessor_flush(struct task_info*, index)
|
||||
* coprocessor_flush(struct task_info*, index)
|
||||
* a2 a3
|
||||
* coprocessor_restore(struct task_info*, index)
|
||||
* a2 a3
|
||||
@ -178,6 +187,7 @@ ENTRY(coprocessor_load)
|
||||
|
||||
|
||||
ENTRY(coprocessor_flush)
|
||||
|
||||
entry a1, 32
|
||||
s32i a0, a1, 0
|
||||
movi a0, .Lsave_cp_regs_jump_table
|
||||
@ -191,6 +201,8 @@ ENTRY(coprocessor_flush)
|
||||
1: l32i a0, a1, 0
|
||||
retw
|
||||
|
||||
ENDPROC(coprocessor_flush)
|
||||
|
||||
ENTRY(coprocessor_restore)
|
||||
entry a1, 32
|
||||
s32i a0, a1, 0
|
||||
@ -205,6 +217,8 @@ ENTRY(coprocessor_restore)
|
||||
1: l32i a0, a1, 0
|
||||
retw
|
||||
|
||||
ENDPROC(coprocessor_restore)
|
||||
|
||||
/*
|
||||
* Entry condition:
|
||||
*
|
||||
@ -220,10 +234,12 @@ ENTRY(coprocessor_restore)
|
||||
*/
|
||||
|
||||
ENTRY(fast_coprocessor_double)
|
||||
|
||||
wsr a0, excsave1
|
||||
movi a0, unrecoverable_exception
|
||||
callx0 a0
|
||||
|
||||
ENDPROC(fast_coprocessor_double)
|
||||
|
||||
ENTRY(fast_coprocessor)
|
||||
|
||||
@ -327,9 +343,14 @@ ENTRY(fast_coprocessor)
|
||||
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_coprocessor)
|
||||
|
||||
.data
|
||||
|
||||
ENTRY(coprocessor_owner)
|
||||
|
||||
.fill XCHAL_CP_MAX, 4, 0
|
||||
|
||||
#endif /* XTENSA_HAVE_COPROCESSORS */
|
||||
END(coprocessor_owner)
|
||||
|
||||
#endif /* XTENSA_HAVE_COPROCESSORS */
|
||||
|
@ -219,6 +219,7 @@ _user_exception:
|
||||
|
||||
j common_exception
|
||||
|
||||
ENDPROC(user_exception)
|
||||
|
||||
/*
|
||||
* First-level exit handler for kernel exceptions
|
||||
@ -371,6 +372,13 @@ common_exception:
|
||||
s32i a2, a1, PT_LBEG
|
||||
s32i a3, a1, PT_LEND
|
||||
|
||||
/* Save SCOMPARE1 */
|
||||
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
rsr a2, scompare1
|
||||
s32i a2, a1, PT_SCOMPARE1
|
||||
#endif
|
||||
|
||||
/* Save optional registers. */
|
||||
|
||||
save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
|
||||
@ -432,6 +440,12 @@ common_exception_return:
|
||||
|
||||
load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
|
||||
|
||||
/* Restore SCOMPARE1 */
|
||||
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
l32i a2, a1, PT_SCOMPARE1
|
||||
wsr a2, scompare1
|
||||
#endif
|
||||
wsr a3, ps /* disable interrupts */
|
||||
|
||||
_bbci.l a3, PS_UM_BIT, kernel_exception_exit
|
||||
@ -641,6 +655,8 @@ common_exception_exit:
|
||||
l32i a1, a1, PT_AREG1
|
||||
rfde
|
||||
|
||||
ENDPROC(kernel_exception)
|
||||
|
||||
/*
|
||||
* Debug exception handler.
|
||||
*
|
||||
@ -701,6 +717,7 @@ ENTRY(debug_exception)
|
||||
/* Debug exception while in exception mode. */
|
||||
1: j 1b // FIXME!!
|
||||
|
||||
ENDPROC(debug_exception)
|
||||
|
||||
/*
|
||||
* We get here in case of an unrecoverable exception.
|
||||
@ -751,6 +768,7 @@ ENTRY(unrecoverable_exception)
|
||||
|
||||
1: j 1b
|
||||
|
||||
ENDPROC(unrecoverable_exception)
|
||||
|
||||
/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
|
||||
|
||||
@ -856,7 +874,7 @@ ENTRY(fast_alloca)
|
||||
|
||||
_bnei a0, 1, 1f # no 'movsp a1, ax': jump
|
||||
|
||||
/* Move the save area. This implies the use of the L32E
|
||||
/* Move the save area. This implies the use of the L32E
|
||||
* and S32E instructions, because this move must be done with
|
||||
* the user's PS.RING privilege levels, not with ring 0
|
||||
* (kernel's) privileges currently active with PS.EXCM
|
||||
@ -929,6 +947,7 @@ ENTRY(fast_alloca)
|
||||
l32i a2, a2, PT_AREG2
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_alloca)
|
||||
|
||||
/*
|
||||
* fast system calls.
|
||||
@ -966,6 +985,8 @@ ENTRY(fast_syscall_kernel)
|
||||
|
||||
j kernel_exception
|
||||
|
||||
ENDPROC(fast_syscall_kernel)
|
||||
|
||||
ENTRY(fast_syscall_user)
|
||||
|
||||
/* Skip syscall. */
|
||||
@ -983,19 +1004,21 @@ ENTRY(fast_syscall_user)
|
||||
|
||||
j user_exception
|
||||
|
||||
ENDPROC(fast_syscall_user)
|
||||
|
||||
ENTRY(fast_syscall_unrecoverable)
|
||||
|
||||
/* Restore all states. */
|
||||
/* Restore all states. */
|
||||
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
xsr a2, depc # restore a2, depc
|
||||
rsr a3, excsave1
|
||||
|
||||
wsr a0, excsave1
|
||||
movi a0, unrecoverable_exception
|
||||
callx0 a0
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
xsr a2, depc # restore a2, depc
|
||||
rsr a3, excsave1
|
||||
|
||||
wsr a0, excsave1
|
||||
movi a0, unrecoverable_exception
|
||||
callx0 a0
|
||||
|
||||
ENDPROC(fast_syscall_unrecoverable)
|
||||
|
||||
/*
|
||||
* sysxtensa syscall handler
|
||||
@ -1101,7 +1124,7 @@ CATCH
|
||||
movi a2, -EINVAL
|
||||
rfe
|
||||
|
||||
|
||||
ENDPROC(fast_syscall_xtensa)
|
||||
|
||||
|
||||
/* fast_syscall_spill_registers.
|
||||
@ -1160,6 +1183,8 @@ ENTRY(fast_syscall_spill_registers)
|
||||
movi a2, 0
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_syscall_spill_registers)
|
||||
|
||||
/* Fixup handler.
|
||||
*
|
||||
* We get here if the spill routine causes an exception, e.g. tlb miss.
|
||||
@ -1228,9 +1253,9 @@ fast_syscall_spill_registers_fixup:
|
||||
|
||||
movi a3, exc_table
|
||||
rsr a0, exccause
|
||||
addx4 a0, a0, a3 # find entry in table
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER # load handler
|
||||
jx a0
|
||||
addx4 a0, a0, a3 # find entry in table
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER # load handler
|
||||
jx a0
|
||||
|
||||
fast_syscall_spill_registers_fixup_return:
|
||||
|
||||
@ -1432,7 +1457,7 @@ ENTRY(_spill_registers)
|
||||
rsr a0, ps
|
||||
_bbci.l a0, PS_UM_BIT, 1f
|
||||
|
||||
/* User space: Setup a dummy frame and kill application.
|
||||
/* User space: Setup a dummy frame and kill application.
|
||||
* Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
|
||||
*/
|
||||
|
||||
@ -1464,6 +1489,8 @@ ENTRY(_spill_registers)
|
||||
callx0 a0 # should not return
|
||||
1: j 1b
|
||||
|
||||
ENDPROC(_spill_registers)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
/*
|
||||
* We should never get here. Bail out!
|
||||
@ -1475,6 +1502,8 @@ ENTRY(fast_second_level_miss_double_kernel)
|
||||
callx0 a0 # should not return
|
||||
1: j 1b
|
||||
|
||||
ENDPROC(fast_second_level_miss_double_kernel)
|
||||
|
||||
/* First-level entry handler for user, kernel, and double 2nd-level
|
||||
* TLB miss exceptions. Note that for now, user and kernel miss
|
||||
* exceptions share the same entry point and are handled identically.
|
||||
@ -1682,6 +1711,7 @@ ENTRY(fast_second_level_miss)
|
||||
j _kernel_exception
|
||||
1: j _user_exception
|
||||
|
||||
ENDPROC(fast_second_level_miss)
|
||||
|
||||
/*
|
||||
* StoreProhibitedException
|
||||
@ -1777,6 +1807,9 @@ ENTRY(fast_store_prohibited)
|
||||
bbsi.l a2, PS_UM_BIT, 1f
|
||||
j _kernel_exception
|
||||
1: j _user_exception
|
||||
|
||||
ENDPROC(fast_store_prohibited)
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
/*
|
||||
@ -1787,6 +1820,7 @@ ENTRY(fast_store_prohibited)
|
||||
*/
|
||||
|
||||
ENTRY(system_call)
|
||||
|
||||
entry a1, 32
|
||||
|
||||
/* regs->syscall = regs->areg[2] */
|
||||
@ -1831,6 +1865,8 @@ ENTRY(system_call)
|
||||
callx4 a4
|
||||
retw
|
||||
|
||||
ENDPROC(system_call)
|
||||
|
||||
|
||||
/*
|
||||
* Task switch.
|
||||
@ -1899,6 +1935,7 @@ ENTRY(_switch_to)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(_switch_to)
|
||||
|
||||
ENTRY(ret_from_fork)
|
||||
|
||||
@ -1914,6 +1951,8 @@ ENTRY(ret_from_fork)
|
||||
|
||||
j common_exception_return
|
||||
|
||||
ENDPROC(ret_from_fork)
|
||||
|
||||
/*
|
||||
* Kernel thread creation helper
|
||||
* On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/cacheasm.h>
|
||||
#include <asm/initialize_mmu.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/linkage.h>
|
||||
@ -47,16 +48,19 @@
|
||||
*/
|
||||
|
||||
__HEAD
|
||||
.globl _start
|
||||
_start: _j 2f
|
||||
ENTRY(_start)
|
||||
|
||||
_j 2f
|
||||
.align 4
|
||||
1: .word _startup
|
||||
2: l32r a0, 1b
|
||||
jx a0
|
||||
|
||||
ENDPROC(_start)
|
||||
|
||||
.section .init.text, "ax"
|
||||
.align 4
|
||||
_startup:
|
||||
|
||||
ENTRY(_startup)
|
||||
|
||||
/* Disable interrupts and exceptions. */
|
||||
|
||||
@ -107,7 +111,7 @@ _startup:
|
||||
/* Disable all timers. */
|
||||
|
||||
.set _index, 0
|
||||
.rept XCHAL_NUM_TIMERS - 1
|
||||
.rept XCHAL_NUM_TIMERS
|
||||
wsr a0, SREG_CCOMPARE + _index
|
||||
.set _index, _index + 1
|
||||
.endr
|
||||
@ -120,7 +124,7 @@ _startup:
|
||||
|
||||
/* Disable coprocessors. */
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
#if XCHAL_HAVE_CP
|
||||
wsr a0, cpenable
|
||||
#endif
|
||||
|
||||
@ -152,6 +156,8 @@ _startup:
|
||||
|
||||
isync
|
||||
|
||||
initialize_mmu
|
||||
|
||||
/* Unpack data sections
|
||||
*
|
||||
* The linker script used to build the Linux kernel image
|
||||
@ -230,6 +236,7 @@ _startup:
|
||||
should_never_return:
|
||||
j should_never_return
|
||||
|
||||
ENDPROC(_startup)
|
||||
|
||||
/*
|
||||
* BSS section
|
||||
@ -239,6 +246,8 @@ __PAGE_ALIGNED_BSS
|
||||
#ifdef CONFIG_MMU
|
||||
ENTRY(swapper_pg_dir)
|
||||
.fill PAGE_SIZE, 1, 0
|
||||
END(swapper_pg_dir)
|
||||
#endif
|
||||
ENTRY(empty_zero_page)
|
||||
.fill PAGE_SIZE, 1, 0
|
||||
END(empty_zero_page)
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/platform.h>
|
||||
@ -26,19 +28,22 @@ static unsigned int cached_irq_mask;
|
||||
|
||||
atomic_t irq_err_count;
|
||||
|
||||
static struct irq_domain *root_domain;
|
||||
|
||||
/*
|
||||
* do_IRQ handles all normal device IRQ's (the special
|
||||
* SMP cross-CPU interrupts have their own specific
|
||||
* handlers).
|
||||
*/
|
||||
|
||||
asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
|
||||
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
int irq = irq_find_mapping(root_domain, hwirq);
|
||||
|
||||
if (irq >= NR_IRQS) {
|
||||
if (hwirq >= NR_IRQS) {
|
||||
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
|
||||
__func__, irq);
|
||||
__func__, hwirq);
|
||||
}
|
||||
|
||||
irq_enter();
|
||||
@ -71,40 +76,39 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
||||
|
||||
static void xtensa_irq_mask(struct irq_data *d)
|
||||
{
|
||||
cached_irq_mask &= ~(1 << d->irq);
|
||||
cached_irq_mask &= ~(1 << d->hwirq);
|
||||
set_sr (cached_irq_mask, intenable);
|
||||
}
|
||||
|
||||
static void xtensa_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
cached_irq_mask |= 1 << d->irq;
|
||||
cached_irq_mask |= 1 << d->hwirq;
|
||||
set_sr (cached_irq_mask, intenable);
|
||||
}
|
||||
|
||||
static void xtensa_irq_enable(struct irq_data *d)
|
||||
{
|
||||
variant_irq_enable(d->irq);
|
||||
variant_irq_enable(d->hwirq);
|
||||
xtensa_irq_unmask(d);
|
||||
}
|
||||
|
||||
static void xtensa_irq_disable(struct irq_data *d)
|
||||
{
|
||||
xtensa_irq_mask(d);
|
||||
variant_irq_disable(d->irq);
|
||||
variant_irq_disable(d->hwirq);
|
||||
}
|
||||
|
||||
static void xtensa_irq_ack(struct irq_data *d)
|
||||
{
|
||||
set_sr(1 << d->irq, intclear);
|
||||
set_sr(1 << d->hwirq, intclear);
|
||||
}
|
||||
|
||||
static int xtensa_irq_retrigger(struct irq_data *d)
|
||||
{
|
||||
set_sr (1 << d->irq, INTSET);
|
||||
set_sr(1 << d->hwirq, intset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip xtensa_irq_chip = {
|
||||
.name = "xtensa",
|
||||
.irq_enable = xtensa_irq_enable,
|
||||
@ -115,37 +119,99 @@ static struct irq_chip xtensa_irq_chip = {
|
||||
.irq_retrigger = xtensa_irq_retrigger,
|
||||
};
|
||||
|
||||
static int xtensa_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
u32 mask = 1 << hw;
|
||||
|
||||
if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) {
|
||||
irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
|
||||
handle_simple_irq, "level");
|
||||
irq_set_status_flags(irq, IRQ_LEVEL);
|
||||
} else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) {
|
||||
irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
|
||||
handle_edge_irq, "edge");
|
||||
irq_clear_status_flags(irq, IRQ_LEVEL);
|
||||
} else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) {
|
||||
irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
|
||||
handle_level_irq, "level");
|
||||
irq_set_status_flags(irq, IRQ_LEVEL);
|
||||
} else if (mask & XCHAL_INTTYPE_MASK_TIMER) {
|
||||
irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
|
||||
handle_edge_irq, "edge");
|
||||
irq_clear_status_flags(irq, IRQ_LEVEL);
|
||||
} else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
|
||||
/* XCHAL_INTTYPE_MASK_NMI */
|
||||
|
||||
irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
|
||||
handle_level_irq, "level");
|
||||
irq_set_status_flags(irq, IRQ_LEVEL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned map_ext_irq(unsigned ext_irq)
|
||||
{
|
||||
unsigned mask = XCHAL_INTTYPE_MASK_EXTERN_EDGE |
|
||||
XCHAL_INTTYPE_MASK_EXTERN_LEVEL;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; mask; ++i, mask >>= 1) {
|
||||
if ((mask & 1) && ext_irq-- == 0)
|
||||
return i;
|
||||
}
|
||||
return XCHAL_NUM_INTERRUPTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device Tree IRQ specifier translation function which works with one or
|
||||
* two cell bindings. First cell value maps directly to the hwirq number.
|
||||
* Second cell if present specifies whether hwirq number is external (1) or
|
||||
* internal (0).
|
||||
*/
|
||||
int xtensa_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||
const u32 *intspec, unsigned int intsize,
|
||||
unsigned long *out_hwirq, unsigned int *out_type)
|
||||
{
|
||||
if (WARN_ON(intsize < 1 || intsize > 2))
|
||||
return -EINVAL;
|
||||
if (intsize == 2 && intspec[1] == 1) {
|
||||
unsigned int_irq = map_ext_irq(intspec[0]);
|
||||
if (int_irq < XCHAL_NUM_INTERRUPTS)
|
||||
*out_hwirq = int_irq;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
*out_hwirq = intspec[0];
|
||||
}
|
||||
*out_type = IRQ_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops xtensa_irq_domain_ops = {
|
||||
.xlate = xtensa_irq_domain_xlate,
|
||||
.map = xtensa_irq_map,
|
||||
};
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < XTENSA_NR_IRQS; index++) {
|
||||
int mask = 1 << index;
|
||||
|
||||
if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
|
||||
irq_set_chip_and_handler(index, &xtensa_irq_chip,
|
||||
handle_simple_irq);
|
||||
|
||||
else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
|
||||
irq_set_chip_and_handler(index, &xtensa_irq_chip,
|
||||
handle_edge_irq);
|
||||
|
||||
else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
|
||||
irq_set_chip_and_handler(index, &xtensa_irq_chip,
|
||||
handle_level_irq);
|
||||
|
||||
else if (mask & XCHAL_INTTYPE_MASK_TIMER)
|
||||
irq_set_chip_and_handler(index, &xtensa_irq_chip,
|
||||
handle_edge_irq);
|
||||
|
||||
else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */
|
||||
/* XCHAL_INTTYPE_MASK_NMI */
|
||||
|
||||
irq_set_chip_and_handler(index, &xtensa_irq_chip,
|
||||
handle_level_irq);
|
||||
}
|
||||
struct device_node *intc = NULL;
|
||||
|
||||
cached_irq_mask = 0;
|
||||
set_sr(~0, intclear);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/* The interrupt controller device node is mandatory */
|
||||
intc = of_find_compatible_node(NULL, NULL, "xtensa,pic");
|
||||
BUG_ON(!intc);
|
||||
|
||||
root_domain = irq_domain_add_linear(intc, NR_IRQS,
|
||||
&xtensa_irq_domain_ops, NULL);
|
||||
#else
|
||||
root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
|
||||
&xtensa_irq_domain_ops, NULL);
|
||||
#endif
|
||||
irq_set_default_host(root_domain);
|
||||
|
||||
variant_init_irq();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
||||
struct module *mod)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
|
||||
Elf32_Sym *sym;
|
||||
unsigned char *location;
|
||||
uint32_t value;
|
||||
|
@ -44,4 +44,3 @@ _F(void, calibrate_ccount, (void),
|
||||
ccount_per_jiffy = 10 * (1000000UL/HZ);
|
||||
});
|
||||
#endif
|
||||
|
||||
|
@ -108,7 +108,7 @@ void coprocessor_flush_all(struct thread_info *ti)
|
||||
|
||||
void cpu_idle(void)
|
||||
{
|
||||
local_irq_enable();
|
||||
local_irq_enable();
|
||||
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
|
@ -154,7 +154,7 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
|
||||
coprocessor_flush_all(ti);
|
||||
coprocessor_release_all(ti);
|
||||
|
||||
ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0,
|
||||
ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0,
|
||||
sizeof(xtregs_coprocessor_t));
|
||||
#endif
|
||||
ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt,
|
||||
@ -343,4 +343,3 @@ void do_syscall_trace_leave(struct pt_regs *regs)
|
||||
&& (current->ptrace & PT_PTRACED))
|
||||
do_syscall_trace();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
|
||||
# include <linux/console.h>
|
||||
#endif
|
||||
@ -42,6 +47,7 @@
|
||||
#include <asm/page.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/param.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#include <platform/hardware.h>
|
||||
|
||||
@ -64,6 +70,11 @@ int initrd_is_mapped = 0;
|
||||
extern int initrd_below_start_ok;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
extern u32 __dtb_start[];
|
||||
void *dtb_start = __dtb_start;
|
||||
#endif
|
||||
|
||||
unsigned char aux_device_present;
|
||||
extern unsigned long loops_per_jiffy;
|
||||
|
||||
@ -83,6 +94,8 @@ extern void init_mmu(void);
|
||||
static inline void init_mmu(void) { }
|
||||
#endif
|
||||
|
||||
extern int mem_reserve(unsigned long, unsigned long, int);
|
||||
extern void bootmem_init(void);
|
||||
extern void zones_init(void);
|
||||
|
||||
/*
|
||||
@ -104,26 +117,31 @@ typedef struct tagtable {
|
||||
|
||||
/* parse current tag */
|
||||
|
||||
static int __init add_sysmem_bank(unsigned long type, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
|
||||
printk(KERN_WARNING
|
||||
"Ignoring memory bank 0x%08lx size %ldKB\n",
|
||||
start, end - start);
|
||||
return -EINVAL;
|
||||
}
|
||||
sysmem.bank[sysmem.nr_banks].type = type;
|
||||
sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start);
|
||||
sysmem.bank[sysmem.nr_banks].end = end & PAGE_MASK;
|
||||
sysmem.nr_banks++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init parse_tag_mem(const bp_tag_t *tag)
|
||||
{
|
||||
meminfo_t *mi = (meminfo_t*)(tag->data);
|
||||
meminfo_t *mi = (meminfo_t *)(tag->data);
|
||||
|
||||
if (mi->type != MEMORY_TYPE_CONVENTIONAL)
|
||||
return -1;
|
||||
|
||||
if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
|
||||
printk(KERN_WARNING
|
||||
"Ignoring memory bank 0x%08lx size %ldKB\n",
|
||||
(unsigned long)mi->start,
|
||||
(unsigned long)mi->end - (unsigned long)mi->start);
|
||||
return -EINVAL;
|
||||
}
|
||||
sysmem.bank[sysmem.nr_banks].type = mi->type;
|
||||
sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
|
||||
sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_MASK;
|
||||
sysmem.nr_banks++;
|
||||
|
||||
return 0;
|
||||
return add_sysmem_bank(mi->type, mi->start, mi->end);
|
||||
}
|
||||
|
||||
__tagtable(BP_TAG_MEMORY, parse_tag_mem);
|
||||
@ -142,12 +160,31 @@ static int __init parse_tag_initrd(const bp_tag_t* tag)
|
||||
|
||||
__tagtable(BP_TAG_INITRD, parse_tag_initrd);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static int __init parse_tag_fdt(const bp_tag_t *tag)
|
||||
{
|
||||
dtb_start = (void *)(tag->data[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__tagtable(BP_TAG_FDT, parse_tag_fdt);
|
||||
|
||||
void __init early_init_dt_setup_initrd_arch(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
initrd_start = (void *)__va(start);
|
||||
initrd_end = (void *)__va(end);
|
||||
initrd_below_start_ok = 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
static int __init parse_tag_cmdline(const bp_tag_t* tag)
|
||||
{
|
||||
strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
|
||||
command_line[COMMAND_LINE_SIZE - 1] = '\0';
|
||||
strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -185,6 +222,58 @@ static int __init parse_bootparam(const bp_tag_t* tag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||
{
|
||||
size &= PAGE_MASK;
|
||||
add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size);
|
||||
}
|
||||
|
||||
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
||||
{
|
||||
return __alloc_bootmem(size, align, 0);
|
||||
}
|
||||
|
||||
void __init early_init_devtree(void *params)
|
||||
{
|
||||
/* Setup flat device-tree pointer */
|
||||
initial_boot_params = params;
|
||||
|
||||
/* Retrieve various informations from the /chosen node of the
|
||||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
*/
|
||||
if (!command_line[0])
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, command_line);
|
||||
|
||||
/* Scan memory nodes and rebuild MEMBLOCKs */
|
||||
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
if (sysmem.nr_banks == 0)
|
||||
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||
}
|
||||
|
||||
static void __init copy_devtree(void)
|
||||
{
|
||||
void *alloc = early_init_dt_alloc_memory_arch(
|
||||
be32_to_cpu(initial_boot_params->totalsize), 0);
|
||||
if (alloc) {
|
||||
memcpy(alloc, initial_boot_params,
|
||||
be32_to_cpu(initial_boot_params->totalsize));
|
||||
initial_boot_params = alloc;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init xtensa_device_probe(void)
|
||||
{
|
||||
of_platform_populate(NULL, NULL, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(xtensa_device_probe);
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
/*
|
||||
* Initialize architecture. (Early stage)
|
||||
*/
|
||||
@ -193,14 +282,14 @@ void __init init_arch(bp_tag_t *bp_start)
|
||||
{
|
||||
sysmem.nr_banks = 0;
|
||||
|
||||
#ifdef CONFIG_CMDLINE_BOOL
|
||||
strcpy(command_line, default_command_line);
|
||||
#endif
|
||||
|
||||
/* Parse boot parameters */
|
||||
|
||||
if (bp_start)
|
||||
parse_bootparam(bp_start);
|
||||
if (bp_start)
|
||||
parse_bootparam(bp_start);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
early_init_devtree(dtb_start);
|
||||
#endif
|
||||
|
||||
if (sysmem.nr_banks == 0) {
|
||||
sysmem.nr_banks = 1;
|
||||
@ -209,6 +298,11 @@ void __init init_arch(bp_tag_t *bp_start)
|
||||
+ PLATFORM_DEFAULT_MEM_SIZE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMDLINE_BOOL
|
||||
if (!command_line[0])
|
||||
strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE);
|
||||
#endif
|
||||
|
||||
/* Early hook for platforms */
|
||||
|
||||
platform_init(bp_start);
|
||||
@ -235,15 +329,130 @@ extern char _UserExceptionVector_text_end;
|
||||
extern char _DoubleExceptionVector_literal_start;
|
||||
extern char _DoubleExceptionVector_text_end;
|
||||
|
||||
|
||||
#ifdef CONFIG_S32C1I_SELFTEST
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
|
||||
static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
|
||||
|
||||
/*
|
||||
* Basic atomic compare-and-swap, that records PC of S32C1I for probing.
|
||||
*
|
||||
* If *v == cmp, set *v = set. Return previous *v.
|
||||
*/
|
||||
static inline int probed_compare_swap(int *v, int cmp, int set)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %1, 1f\n"
|
||||
" s32i %1, %4, 0\n"
|
||||
" wsr %2, scompare1\n"
|
||||
"1: s32c1i %0, %3, 0\n"
|
||||
: "=a" (set), "=&a" (tmp)
|
||||
: "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set)
|
||||
: "memory"
|
||||
);
|
||||
return set;
|
||||
}
|
||||
|
||||
/* Handle probed exception */
|
||||
|
||||
void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause)
|
||||
{
|
||||
if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */
|
||||
regs->pc += 3; /* skip the s32c1i instruction */
|
||||
rcw_exc = exccause;
|
||||
} else {
|
||||
do_unhandled(regs, exccause);
|
||||
}
|
||||
}
|
||||
|
||||
/* Simple test of S32C1I (soc bringup assist) */
|
||||
|
||||
void __init check_s32c1i(void)
|
||||
{
|
||||
int n, cause1, cause2;
|
||||
void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
|
||||
|
||||
rcw_probe_pc = 0;
|
||||
handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
|
||||
do_probed_exception);
|
||||
handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
|
||||
do_probed_exception);
|
||||
handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
|
||||
do_probed_exception);
|
||||
|
||||
/* First try an S32C1I that does not store: */
|
||||
rcw_exc = 0;
|
||||
rcw_word = 1;
|
||||
n = probed_compare_swap(&rcw_word, 0, 2);
|
||||
cause1 = rcw_exc;
|
||||
|
||||
/* took exception? */
|
||||
if (cause1 != 0) {
|
||||
/* unclean exception? */
|
||||
if (n != 2 || rcw_word != 1)
|
||||
panic("S32C1I exception error");
|
||||
} else if (rcw_word != 1 || n != 1) {
|
||||
panic("S32C1I compare error");
|
||||
}
|
||||
|
||||
/* Then an S32C1I that stores: */
|
||||
rcw_exc = 0;
|
||||
rcw_word = 0x1234567;
|
||||
n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
|
||||
cause2 = rcw_exc;
|
||||
|
||||
if (cause2 != 0) {
|
||||
/* unclean exception? */
|
||||
if (n != 0xabcde || rcw_word != 0x1234567)
|
||||
panic("S32C1I exception error (b)");
|
||||
} else if (rcw_word != 0xabcde || n != 0x1234567) {
|
||||
panic("S32C1I store error");
|
||||
}
|
||||
|
||||
/* Verify consistency of exceptions: */
|
||||
if (cause1 || cause2) {
|
||||
pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
|
||||
/* If emulation of S32C1I upon bus error gets implemented,
|
||||
we can get rid of this panic for single core (not SMP) */
|
||||
panic("S32C1I exceptions not currently supported");
|
||||
}
|
||||
if (cause1 != cause2)
|
||||
panic("inconsistent S32C1I exceptions");
|
||||
|
||||
trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
|
||||
trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
|
||||
trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
|
||||
}
|
||||
|
||||
#else /* XCHAL_HAVE_S32C1I */
|
||||
|
||||
/* This condition should not occur with a commercially deployed processor.
|
||||
Display reminder for early engr test or demo chips / FPGA bitstreams */
|
||||
void __init check_s32c1i(void)
|
||||
{
|
||||
pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
|
||||
}
|
||||
|
||||
#endif /* XCHAL_HAVE_S32C1I */
|
||||
#else /* CONFIG_S32C1I_SELFTEST */
|
||||
|
||||
void __init check_s32c1i(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_S32C1I_SELFTEST */
|
||||
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
extern int mem_reserve(unsigned long, unsigned long, int);
|
||||
extern void bootmem_init(void);
|
||||
|
||||
memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = command_line;
|
||||
|
||||
check_s32c1i();
|
||||
|
||||
/* Reserve some memory regions */
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
@ -251,7 +460,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
initrd_is_mapped = mem_reserve(__pa(initrd_start),
|
||||
__pa(initrd_end), 0);
|
||||
initrd_below_start_ok = 1;
|
||||
} else {
|
||||
} else {
|
||||
initrd_start = 0;
|
||||
}
|
||||
#endif
|
||||
@ -275,8 +484,12 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
bootmem_init();
|
||||
|
||||
platform_setup(cmdline_p);
|
||||
#ifdef CONFIG_OF
|
||||
copy_devtree();
|
||||
unflatten_device_tree();
|
||||
#endif
|
||||
|
||||
platform_setup(cmdline_p);
|
||||
|
||||
paging_init();
|
||||
zones_init();
|
||||
@ -326,7 +539,7 @@ c_show(struct seq_file *f, void *slot)
|
||||
"core ID\t\t: " XCHAL_CORE_ID "\n"
|
||||
"build ID\t: 0x%x\n"
|
||||
"byte order\t: %s\n"
|
||||
"cpu MHz\t\t: %lu.%02lu\n"
|
||||
"cpu MHz\t\t: %lu.%02lu\n"
|
||||
"bogomips\t: %lu.%02lu\n",
|
||||
XCHAL_BUILD_UNIQUE_ID,
|
||||
XCHAL_HAVE_BE ? "big" : "little",
|
||||
@ -380,6 +593,9 @@ c_show(struct seq_file *f, void *slot)
|
||||
#endif
|
||||
#if XCHAL_HAVE_FP
|
||||
"fpu "
|
||||
#endif
|
||||
#if XCHAL_HAVE_S32C1I
|
||||
"s32c1i "
|
||||
#endif
|
||||
"\n");
|
||||
|
||||
@ -412,7 +628,7 @@ c_show(struct seq_file *f, void *slot)
|
||||
"icache size\t: %d\n"
|
||||
"icache flags\t: "
|
||||
#if XCHAL_ICACHE_LINE_LOCKABLE
|
||||
"lock"
|
||||
"lock "
|
||||
#endif
|
||||
"\n"
|
||||
"dcache line size: %d\n"
|
||||
@ -420,10 +636,10 @@ c_show(struct seq_file *f, void *slot)
|
||||
"dcache size\t: %d\n"
|
||||
"dcache flags\t: "
|
||||
#if XCHAL_DCACHE_IS_WRITEBACK
|
||||
"writeback"
|
||||
"writeback "
|
||||
#endif
|
||||
#if XCHAL_DCACHE_LINE_LOCKABLE
|
||||
"lock"
|
||||
"lock "
|
||||
#endif
|
||||
"\n",
|
||||
XCHAL_ICACHE_LINESIZE,
|
||||
@ -465,4 +681,3 @@ const struct seq_operations cpuinfo_op =
|
||||
};
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
|
@ -212,7 +212,7 @@ restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The signal handler may have used coprocessors in which
|
||||
/* The signal handler may have used coprocessors in which
|
||||
* case they are still enabled. We disable them to force a
|
||||
* reloading of the original task's CP state by the lazy
|
||||
* context-switching mechanisms of CP exception handling.
|
||||
@ -396,7 +396,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
start_thread(regs, (unsigned long) ka->sa.sa_handler,
|
||||
start_thread(regs, (unsigned long) ka->sa.sa_handler,
|
||||
(unsigned long) frame);
|
||||
|
||||
/* Set up a stack frame for a call4
|
||||
@ -424,9 +424,9 @@ give_sigsegv:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
|
||||
asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
|
||||
stack_t __user *uoss,
|
||||
long a2, long a3, long a4, long a5,
|
||||
long a2, long a3, long a4, long a5,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return do_sigaltstack(uss, uoss, regs->areg[1]);
|
||||
|
@ -52,4 +52,3 @@ asmlinkage long xtensa_fadvise64_64(int fd, int advice,
|
||||
{
|
||||
return sys_fadvise64_64(fd, offset, len, advice);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/timex.h>
|
||||
#include <asm/platform.h>
|
||||
@ -31,7 +32,7 @@ unsigned long ccount_per_jiffy; /* per 1/HZ */
|
||||
unsigned long nsec_per_ccount; /* nsec per ccount increment */
|
||||
#endif
|
||||
|
||||
static cycle_t ccount_read(void)
|
||||
static cycle_t ccount_read(struct clocksource *cs)
|
||||
{
|
||||
return (cycle_t)get_ccount();
|
||||
}
|
||||
@ -52,6 +53,7 @@ static struct irqaction timer_irqaction = {
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
unsigned int irq;
|
||||
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
|
||||
printk("Calibrating CPU frequency ");
|
||||
platform_calibrate_ccount();
|
||||
@ -62,7 +64,8 @@ void __init time_init(void)
|
||||
|
||||
/* Initialize the linux timer interrupt. */
|
||||
|
||||
setup_irq(LINUX_TIMER_INT, &timer_irqaction);
|
||||
irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
|
||||
setup_irq(irq, &timer_irqaction);
|
||||
set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
|
||||
}
|
||||
|
||||
|
@ -293,6 +293,17 @@ do_debug(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
|
||||
/* Set exception C handler - for temporary use when probing exceptions */
|
||||
|
||||
void * __init trap_set_handler(int cause, void *handler)
|
||||
{
|
||||
unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause];
|
||||
void *previous = (void *)*entry;
|
||||
*entry = (unsigned long)handler;
|
||||
return previous;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize dispatch tables.
|
||||
*
|
||||
@ -397,7 +408,8 @@ static inline void spill_registers(void)
|
||||
"wsr a13, sar\n\t"
|
||||
"wsr a14, ps\n\t"
|
||||
:: "a" (&a0), "a" (&ps)
|
||||
: "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
|
||||
: "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15",
|
||||
"memory");
|
||||
}
|
||||
|
||||
void show_trace(struct task_struct *task, unsigned long *sp)
|
||||
@ -452,7 +464,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
|
||||
|
||||
if (!sp)
|
||||
sp = stack_pointer(task);
|
||||
stack = sp;
|
||||
stack = sp;
|
||||
|
||||
printk("\nStack: ");
|
||||
|
||||
@ -523,5 +535,3 @@ void die(const char * str, struct pt_regs * regs, long err)
|
||||
|
||||
do_exit(err);
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,6 +79,8 @@ ENTRY(_UserExceptionVector)
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER # load handler
|
||||
jx a0
|
||||
|
||||
ENDPROC(_UserExceptionVector)
|
||||
|
||||
/*
|
||||
* Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)
|
||||
*
|
||||
@ -103,6 +105,7 @@ ENTRY(_KernelExceptionVector)
|
||||
l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
|
||||
jx a0
|
||||
|
||||
ENDPROC(_KernelExceptionVector)
|
||||
|
||||
/*
|
||||
* Double exception vector (Exceptions with PS.EXCM == 1)
|
||||
@ -225,7 +228,13 @@ ENTRY(_DoubleExceptionVector)
|
||||
/* Window overflow/underflow exception. Get stack pointer. */
|
||||
|
||||
mov a3, a2
|
||||
movi a2, exc_table
|
||||
/* This explicit literal and the following references to it are made
|
||||
* in order to fit DoubleExceptionVector.literals into the available
|
||||
* 16-byte gap before DoubleExceptionVector.text in the absence of
|
||||
* link time relaxation. See kernel/vmlinux.lds.S
|
||||
*/
|
||||
.literal .Lexc_table, exc_table
|
||||
l32r a2, .Lexc_table
|
||||
l32i a2, a2, EXC_TABLE_KSTK
|
||||
|
||||
/* Check for overflow/underflow exception, jump if overflow. */
|
||||
@ -255,7 +264,7 @@ ENTRY(_DoubleExceptionVector)
|
||||
s32i a0, a2, PT_AREG0
|
||||
|
||||
wsr a3, excsave1 # save a3
|
||||
movi a3, exc_table
|
||||
l32r a3, .Lexc_table
|
||||
|
||||
rsr a0, exccause
|
||||
s32i a0, a2, PT_DEPC # mark it as a regular exception
|
||||
@ -267,7 +276,7 @@ ENTRY(_DoubleExceptionVector)
|
||||
|
||||
/* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */
|
||||
|
||||
movi a3, exc_table
|
||||
l32r a3, .Lexc_table
|
||||
s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable
|
||||
|
||||
/* Enter critical section. */
|
||||
@ -296,7 +305,7 @@ ENTRY(_DoubleExceptionVector)
|
||||
|
||||
/* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
|
||||
|
||||
movi a3, exc_table
|
||||
l32r a3, .Lexc_table
|
||||
rsr a0, exccause
|
||||
addx4 a0, a0, a3
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER
|
||||
@ -338,6 +347,7 @@ ENTRY(_DoubleExceptionVector)
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
ENDPROC(_DoubleExceptionVector)
|
||||
|
||||
/*
|
||||
* Debug interrupt vector
|
||||
@ -349,9 +359,11 @@ ENTRY(_DoubleExceptionVector)
|
||||
.section .DebugInterruptVector.text, "ax"
|
||||
|
||||
ENTRY(_DebugInterruptVector)
|
||||
|
||||
xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
|
||||
jx a0
|
||||
|
||||
ENDPROC(_DebugInterruptVector)
|
||||
|
||||
|
||||
/* Window overflow and underflow handlers.
|
||||
@ -363,38 +375,43 @@ ENTRY(_DebugInterruptVector)
|
||||
* we try to access any page that would cause a page fault early.
|
||||
*/
|
||||
|
||||
#define ENTRY_ALIGN64(name) \
|
||||
.globl name; \
|
||||
.align 64; \
|
||||
name:
|
||||
|
||||
.section .WindowVectors.text, "ax"
|
||||
|
||||
|
||||
/* 4-Register Window Overflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowOverflow4
|
||||
_WindowOverflow4:
|
||||
ENTRY_ALIGN64(_WindowOverflow4)
|
||||
|
||||
s32e a0, a5, -16
|
||||
s32e a1, a5, -12
|
||||
s32e a2, a5, -8
|
||||
s32e a3, a5, -4
|
||||
rfwo
|
||||
|
||||
ENDPROC(_WindowOverflow4)
|
||||
|
||||
|
||||
/* 4-Register Window Underflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowUnderflow4
|
||||
_WindowUnderflow4:
|
||||
ENTRY_ALIGN64(_WindowUnderflow4)
|
||||
|
||||
l32e a0, a5, -16
|
||||
l32e a1, a5, -12
|
||||
l32e a2, a5, -8
|
||||
l32e a3, a5, -4
|
||||
rfwu
|
||||
|
||||
ENDPROC(_WindowUnderflow4)
|
||||
|
||||
/* 8-Register Window Overflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowOverflow8
|
||||
_WindowOverflow8:
|
||||
ENTRY_ALIGN64(_WindowOverflow8)
|
||||
|
||||
s32e a0, a9, -16
|
||||
l32e a0, a1, -12
|
||||
s32e a2, a9, -8
|
||||
@ -406,11 +423,12 @@ _WindowOverflow8:
|
||||
s32e a7, a0, -20
|
||||
rfwo
|
||||
|
||||
ENDPROC(_WindowOverflow8)
|
||||
|
||||
/* 8-Register Window Underflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowUnderflow8
|
||||
_WindowUnderflow8:
|
||||
ENTRY_ALIGN64(_WindowUnderflow8)
|
||||
|
||||
l32e a1, a9, -12
|
||||
l32e a0, a9, -16
|
||||
l32e a7, a1, -12
|
||||
@ -422,12 +440,12 @@ _WindowUnderflow8:
|
||||
l32e a7, a7, -20
|
||||
rfwu
|
||||
|
||||
ENDPROC(_WindowUnderflow8)
|
||||
|
||||
/* 12-Register Window Overflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowOverflow12
|
||||
_WindowOverflow12:
|
||||
ENTRY_ALIGN64(_WindowOverflow12)
|
||||
|
||||
s32e a0, a13, -16
|
||||
l32e a0, a1, -12
|
||||
s32e a1, a13, -12
|
||||
@ -443,11 +461,12 @@ _WindowOverflow12:
|
||||
s32e a11, a0, -20
|
||||
rfwo
|
||||
|
||||
ENDPROC(_WindowOverflow12)
|
||||
|
||||
/* 12-Register Window Underflow Vector (Handler) */
|
||||
|
||||
.align 64
|
||||
.global _WindowUnderflow12
|
||||
_WindowUnderflow12:
|
||||
ENTRY_ALIGN64(_WindowUnderflow12)
|
||||
|
||||
l32e a1, a13, -12
|
||||
l32e a0, a13, -16
|
||||
l32e a11, a1, -12
|
||||
@ -463,6 +482,6 @@ _WindowUnderflow12:
|
||||
l32e a11, a11, -20
|
||||
rfwu
|
||||
|
||||
ENDPROC(_WindowUnderflow12)
|
||||
|
||||
.text
|
||||
|
||||
|
||||
|
@ -41,10 +41,11 @@
|
||||
|
||||
.text
|
||||
ENTRY(csum_partial)
|
||||
/*
|
||||
* Experiments with Ethernet and SLIP connections show that buf
|
||||
* is aligned on either a 2-byte or 4-byte boundary.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Experiments with Ethernet and SLIP connections show that buf
|
||||
* is aligned on either a 2-byte or 4-byte boundary.
|
||||
*/
|
||||
entry sp, 32
|
||||
extui a5, a2, 0, 2
|
||||
bnez a5, 8f /* branch if 2-byte aligned */
|
||||
@ -170,7 +171,7 @@ ENTRY(csum_partial)
|
||||
3:
|
||||
j 5b /* branch to handle the remaining byte */
|
||||
|
||||
|
||||
ENDPROC(csum_partial)
|
||||
|
||||
/*
|
||||
* Copy from ds while checksumming, otherwise like csum_partial
|
||||
@ -211,6 +212,7 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
|
||||
*/
|
||||
|
||||
ENTRY(csum_partial_copy_generic)
|
||||
|
||||
entry sp, 32
|
||||
mov a12, a3
|
||||
mov a11, a4
|
||||
@ -367,6 +369,8 @@ DST( s8i a8, a3, 1 )
|
||||
6:
|
||||
j 4b /* process the possible trailing odd byte */
|
||||
|
||||
ENDPROC(csum_partial_copy_generic)
|
||||
|
||||
|
||||
# Exception handler:
|
||||
.section .fixup, "ax"
|
||||
@ -406,4 +410,3 @@ DST( s8i a8, a3, 1 )
|
||||
retw
|
||||
|
||||
.previous
|
||||
|
||||
|
@ -210,8 +210,10 @@ memcpy:
|
||||
_beqz a4, .Ldone # avoid loading anything for zero-length copies
|
||||
# copy 16 bytes per iteration for word-aligned dst and unaligned src
|
||||
ssa8 a3 # set shift amount from byte offset
|
||||
#define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS (simulator) with the
|
||||
lint or ferret client, or 0 to save a few cycles */
|
||||
|
||||
/* set to 1 when running on ISS (simulator) with the
|
||||
lint or ferret client, or 0 to save a few cycles */
|
||||
#define SIM_CHECKS_ALIGNMENT 1
|
||||
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
|
||||
and a11, a3, a8 # save unalignment offset for below
|
||||
sub a3, a3, a11 # align a3
|
||||
|
@ -241,8 +241,8 @@ int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
|
||||
unsigned char header_type;
|
||||
struct pci_dev *dev = &pciauto_dev;
|
||||
|
||||
pciauto_dev.bus = &pciauto_bus;
|
||||
pciauto_dev.sysdata = pci_ctrl;
|
||||
pciauto_dev.bus = &pciauto_bus;
|
||||
pciauto_dev.sysdata = pci_ctrl;
|
||||
pciauto_bus.ops = pci_ctrl->ops;
|
||||
|
||||
/*
|
||||
@ -345,8 +345,3 @@ int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
|
||||
}
|
||||
return sub_bus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -166,7 +166,7 @@ __strncpy_user:
|
||||
retw
|
||||
.Lz1: # byte 1 is zero
|
||||
#ifdef __XTENSA_EB__
|
||||
extui a9, a9, 16, 16
|
||||
extui a9, a9, 16, 16
|
||||
#endif /* __XTENSA_EB__ */
|
||||
EX(s16i, a9, a11, 0, fixup_s)
|
||||
addi a11, a11, 1 # advance dst pointer
|
||||
@ -174,7 +174,7 @@ __strncpy_user:
|
||||
retw
|
||||
.Lz2: # byte 2 is zero
|
||||
#ifdef __XTENSA_EB__
|
||||
extui a9, a9, 16, 16
|
||||
extui a9, a9, 16, 16
|
||||
#endif /* __XTENSA_EB__ */
|
||||
EX(s16i, a9, a11, 0, fixup_s)
|
||||
movi a9, 0
|
||||
|
@ -145,4 +145,3 @@ __strnlen_user:
|
||||
lenfixup:
|
||||
movi a2, 0
|
||||
retw
|
||||
|
||||
|
@ -318,4 +318,3 @@ l_fixup:
|
||||
/* Ignore memset return value in a6. */
|
||||
/* a2 still contains bytes not copied. */
|
||||
retw
|
||||
|
||||
|
@ -118,7 +118,7 @@ void flush_dcache_page(struct page *page)
|
||||
* For now, flush the whole cache. FIXME??
|
||||
*/
|
||||
|
||||
void flush_cache_range(struct vm_area_struct* vma,
|
||||
void flush_cache_range(struct vm_area_struct* vma,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
__flush_invalidate_dcache_all();
|
||||
@ -133,7 +133,7 @@ void flush_cache_range(struct vm_area_struct* vma,
|
||||
*/
|
||||
|
||||
void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
|
||||
unsigned long pfn)
|
||||
unsigned long pfn)
|
||||
{
|
||||
/* Note that we have to use the 'alias' address to avoid multi-hit */
|
||||
|
||||
@ -166,14 +166,14 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
|
||||
|
||||
if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
|
||||
|
||||
unsigned long vaddr = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
|
||||
unsigned long paddr = (unsigned long) page_address(page);
|
||||
unsigned long phys = page_to_phys(page);
|
||||
unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
|
||||
|
||||
__flush_invalidate_dcache_page(paddr);
|
||||
|
||||
__flush_invalidate_dcache_page_alias(vaddr, phys);
|
||||
__invalidate_icache_page_alias(vaddr, phys);
|
||||
__flush_invalidate_dcache_page_alias(tmp, phys);
|
||||
__invalidate_icache_page_alias(tmp, phys);
|
||||
|
||||
clear_bit(PG_arch_1, &page->flags);
|
||||
}
|
||||
@ -195,7 +195,7 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
|
||||
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
unsigned long vaddr, void *dst, const void *src,
|
||||
unsigned long len)
|
||||
{
|
||||
@ -205,8 +205,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
/* Flush and invalidate user page if aliased. */
|
||||
|
||||
if (alias) {
|
||||
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(temp, phys);
|
||||
unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(t, phys);
|
||||
}
|
||||
|
||||
/* Copy data */
|
||||
@ -219,12 +219,11 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
*/
|
||||
|
||||
if (alias) {
|
||||
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
|
||||
__flush_invalidate_dcache_range((unsigned long) dst, len);
|
||||
if ((vma->vm_flags & VM_EXEC) != 0) {
|
||||
__invalidate_icache_page_alias(temp, phys);
|
||||
}
|
||||
if ((vma->vm_flags & VM_EXEC) != 0)
|
||||
__invalidate_icache_page_alias(t, phys);
|
||||
|
||||
} else if ((vma->vm_flags & VM_EXEC) != 0) {
|
||||
__flush_dcache_range((unsigned long)dst,len);
|
||||
@ -245,8 +244,8 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
*/
|
||||
|
||||
if (alias) {
|
||||
unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(temp, phys);
|
||||
unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(t, phys);
|
||||
}
|
||||
|
||||
memcpy(dst, src, len);
|
||||
|
@ -254,4 +254,3 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
|
||||
die("Oops", regs, sig);
|
||||
do_exit(sig);
|
||||
}
|
||||
|
||||
|
@ -75,15 +75,15 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
|
||||
sysmem.nr_banks++;
|
||||
}
|
||||
sysmem.bank[i].end = start;
|
||||
|
||||
} else if (end < sysmem.bank[i].end) {
|
||||
sysmem.bank[i].start = end;
|
||||
|
||||
} else {
|
||||
if (end < sysmem.bank[i].end)
|
||||
sysmem.bank[i].start = end;
|
||||
else {
|
||||
/* remove entry */
|
||||
sysmem.nr_banks--;
|
||||
sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
|
||||
sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end;
|
||||
}
|
||||
/* remove entry */
|
||||
sysmem.nr_banks--;
|
||||
sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
|
||||
sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
ENTRY(clear_page)
|
||||
|
||||
entry a1, 16
|
||||
|
||||
movi a3, 0
|
||||
@ -45,6 +46,8 @@ ENTRY(clear_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(clear_page)
|
||||
|
||||
/*
|
||||
* copy_page and copy_user_page are the same for non-cache-aliased configs.
|
||||
*
|
||||
@ -53,6 +56,7 @@ ENTRY(clear_page)
|
||||
*/
|
||||
|
||||
ENTRY(copy_page)
|
||||
|
||||
entry a1, 16
|
||||
|
||||
__loopi a2, a4, PAGE_SIZE, 32
|
||||
@ -84,6 +88,8 @@ ENTRY(copy_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(copy_page)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
/*
|
||||
* If we have to deal with cache aliasing, we use temporary memory mappings
|
||||
@ -109,6 +115,7 @@ ENTRY(__tlbtemp_mapping_start)
|
||||
*/
|
||||
|
||||
ENTRY(clear_user_page)
|
||||
|
||||
entry a1, 32
|
||||
|
||||
/* Mark page dirty and determine alias. */
|
||||
@ -164,6 +171,8 @@ ENTRY(clear_user_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(clear_user_page)
|
||||
|
||||
/*
|
||||
* copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
|
||||
* a2 a3 a4 a5
|
||||
@ -171,7 +180,7 @@ ENTRY(clear_user_page)
|
||||
|
||||
ENTRY(copy_user_page)
|
||||
|
||||
entry a1, 32
|
||||
entry a1, 32
|
||||
|
||||
/* Mark page dirty and determine alias for destination. */
|
||||
|
||||
@ -262,6 +271,8 @@ ENTRY(copy_user_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(copy_user_page)
|
||||
|
||||
#endif
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
@ -272,6 +283,7 @@ ENTRY(copy_user_page)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_invalidate_dcache_page_alias)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
movi a7, 0 # required for exception handler
|
||||
@ -287,6 +299,7 @@ ENTRY(__flush_invalidate_dcache_page_alias)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_invalidate_dcache_page_alias)
|
||||
#endif
|
||||
|
||||
ENTRY(__tlbtemp_mapping_itlb)
|
||||
@ -294,6 +307,7 @@ ENTRY(__tlbtemp_mapping_itlb)
|
||||
#if (ICACHE_WAY_SIZE > PAGE_SIZE)
|
||||
|
||||
ENTRY(__invalidate_icache_page_alias)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE)
|
||||
@ -307,11 +321,14 @@ ENTRY(__invalidate_icache_page_alias)
|
||||
isync
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_icache_page_alias)
|
||||
|
||||
#endif
|
||||
|
||||
/* End of special treatment in tlb miss exception */
|
||||
|
||||
ENTRY(__tlbtemp_mapping_end)
|
||||
|
||||
#endif /* CONFIG_MMU
|
||||
|
||||
/*
|
||||
@ -319,6 +336,7 @@ ENTRY(__tlbtemp_mapping_end)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_icache_page)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_icache_page a2 a3
|
||||
@ -326,11 +344,14 @@ ENTRY(__invalidate_icache_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_icache_page)
|
||||
|
||||
/*
|
||||
* void __invalidate_dcache_page(ulong start)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_dcache_page)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_dcache_page a2 a3
|
||||
@ -338,11 +359,14 @@ ENTRY(__invalidate_dcache_page)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_dcache_page)
|
||||
|
||||
/*
|
||||
* void __flush_invalidate_dcache_page(ulong start)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_invalidate_dcache_page)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___flush_invalidate_dcache_page a2 a3
|
||||
@ -350,11 +374,14 @@ ENTRY(__flush_invalidate_dcache_page)
|
||||
dsync
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_invalidate_dcache_page)
|
||||
|
||||
/*
|
||||
* void __flush_dcache_page(ulong start)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_dcache_page)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___flush_dcache_page a2 a3
|
||||
@ -362,11 +389,14 @@ ENTRY(__flush_dcache_page)
|
||||
dsync
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_dcache_page)
|
||||
|
||||
/*
|
||||
* void __invalidate_icache_range(ulong start, ulong size)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_icache_range)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_icache_range a2 a3 a4
|
||||
@ -374,11 +404,14 @@ ENTRY(__invalidate_icache_range)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_icache_range)
|
||||
|
||||
/*
|
||||
* void __flush_invalidate_dcache_range(ulong start, ulong size)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_invalidate_dcache_range)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___flush_invalidate_dcache_range a2 a3 a4
|
||||
@ -386,11 +419,14 @@ ENTRY(__flush_invalidate_dcache_range)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_invalidate_dcache_range)
|
||||
|
||||
/*
|
||||
* void _flush_dcache_range(ulong start, ulong size)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_dcache_range)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___flush_dcache_range a2 a3 a4
|
||||
@ -398,22 +434,28 @@ ENTRY(__flush_dcache_range)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_dcache_range)
|
||||
|
||||
/*
|
||||
* void _invalidate_dcache_range(ulong start, ulong size)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_dcache_range)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_dcache_range a2 a3 a4
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_dcache_range)
|
||||
|
||||
/*
|
||||
* void _invalidate_icache_all(void)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_icache_all)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_icache_all a2 a3
|
||||
@ -421,11 +463,14 @@ ENTRY(__invalidate_icache_all)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_icache_all)
|
||||
|
||||
/*
|
||||
* void _flush_invalidate_dcache_all(void)
|
||||
*/
|
||||
|
||||
ENTRY(__flush_invalidate_dcache_all)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___flush_invalidate_dcache_all a2 a3
|
||||
@ -433,11 +478,14 @@ ENTRY(__flush_invalidate_dcache_all)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__flush_invalidate_dcache_all)
|
||||
|
||||
/*
|
||||
* void _invalidate_dcache_all(void)
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_dcache_all)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
___invalidate_dcache_all a2 a3
|
||||
@ -445,3 +493,4 @@ ENTRY(__invalidate_dcache_all)
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_dcache_all)
|
||||
|
@ -37,7 +37,7 @@ void __init init_mmu(void)
|
||||
|
||||
/* Set rasid register to a known value. */
|
||||
|
||||
set_rasid_register(ASID_USER_FIRST);
|
||||
set_rasid_register(ASID_INSERT(ASID_USER_FIRST));
|
||||
|
||||
/* Set PTEVADDR special register to the start of the page
|
||||
* table, which is in kernel mappable space (ie. not
|
||||
|
@ -63,7 +63,7 @@ void flush_tlb_all (void)
|
||||
void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
if (mm == current->active_mm) {
|
||||
int flags;
|
||||
unsigned long flags;
|
||||
local_save_flags(flags);
|
||||
__get_new_mmu_context(mm);
|
||||
__load_mmu_context(mm);
|
||||
@ -82,7 +82,7 @@ void flush_tlb_mm(struct mm_struct *mm)
|
||||
#endif
|
||||
|
||||
void flush_tlb_range (struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end)
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
unsigned long flags;
|
||||
@ -100,7 +100,7 @@ void flush_tlb_range (struct vm_area_struct *vma,
|
||||
int oldpid = get_rasid_register();
|
||||
set_rasid_register (ASID_INSERT(mm->context));
|
||||
start &= PAGE_MASK;
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
while(start < end) {
|
||||
invalidate_itlb_mapping(start);
|
||||
invalidate_dtlb_mapping(start);
|
||||
@ -130,7 +130,7 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
|
||||
|
||||
local_save_flags(flags);
|
||||
|
||||
oldpid = get_rasid_register();
|
||||
oldpid = get_rasid_register();
|
||||
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
invalidate_itlb_mapping(page);
|
||||
@ -140,4 +140,3 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2012 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_XTENSA_ISS_SERIAL_H
|
||||
#define __ASM_XTENSA_ISS_SERIAL_H
|
||||
|
||||
/* Have no meaning on ISS, but needed for 8250_early.c */
|
||||
#define BASE_BAUD 0
|
||||
|
||||
#endif /* __ASM_XTENSA_ISS_SERIAL_H */
|
@ -74,13 +74,12 @@ static inline int __simc(int a, int b, int c, int d, int e, int f)
|
||||
"mov %1, a3\n"
|
||||
: "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1)
|
||||
: "r"(c1), "r"(d1), "r"(e1), "r"(f1)
|
||||
: );
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int simc_open(const char *file, int flags, int mode)
|
||||
{
|
||||
wmb();
|
||||
return __simc(SYS_open, (int) file, flags, mode, 0, 0);
|
||||
}
|
||||
|
||||
@ -91,19 +90,16 @@ static inline int simc_close(int fd)
|
||||
|
||||
static inline int simc_ioctl(int fd, int request, void *arg)
|
||||
{
|
||||
wmb();
|
||||
return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
|
||||
}
|
||||
|
||||
static inline int simc_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
rmb();
|
||||
return __simc(SYS_read, fd, (int) buf, count, 0, 0);
|
||||
}
|
||||
|
||||
static inline int simc_write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
wmb();
|
||||
return __simc(SYS_write, fd, (int) buf, count, 0, 0);
|
||||
}
|
||||
|
||||
@ -111,7 +107,6 @@ static inline int simc_poll(int fd)
|
||||
{
|
||||
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
|
||||
|
||||
wmb();
|
||||
return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,
|
||||
0, 0);
|
||||
}
|
||||
|
9
arch/xtensa/platforms/xtfpga/Makefile
Normal file
9
arch/xtensa/platforms/xtfpga/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# Makefile for the Tensilica xtavnet Emulation Board
|
||||
#
|
||||
# Note! Dependencies are done automagically by 'make dep', which also
|
||||
# removes any old dependencies. DON'T put your own dependencies here
|
||||
# unless it's something special (ie not a .c file).
|
||||
#
|
||||
# Note 2! The CFLAGS definitions are in the main makefile...
|
||||
|
||||
obj-y = setup.o lcd.o
|
69
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
Normal file
69
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* arch/xtensa/platform/xtavnet/include/platform/hardware.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2006 Tensilica Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the hardware configuration of the XTAVNET boards.
|
||||
*/
|
||||
|
||||
#ifndef __XTENSA_XTAVNET_HARDWARE_H
|
||||
#define __XTENSA_XTAVNET_HARDWARE_H
|
||||
|
||||
/* By default NO_IRQ is defined to 0 in Linux, but we use the
|
||||
interrupt 0 for UART... */
|
||||
#define NO_IRQ -1
|
||||
|
||||
/* Memory configuration. */
|
||||
|
||||
#define PLATFORM_DEFAULT_MEM_START 0x00000000
|
||||
#define PLATFORM_DEFAULT_MEM_SIZE 0x04000000
|
||||
|
||||
/* Interrupt configuration. */
|
||||
|
||||
#define PLATFORM_NR_IRQS 10
|
||||
|
||||
/* Default assignment of LX60 devices to external interrupts. */
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_SMP
|
||||
#define DUART16552_INTNUM XCHAL_EXTINT3_NUM
|
||||
#define OETH_IRQ XCHAL_EXTINT4_NUM
|
||||
#else
|
||||
#define DUART16552_INTNUM XCHAL_EXTINT0_NUM
|
||||
#define OETH_IRQ XCHAL_EXTINT1_NUM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Device addresses and parameters.
|
||||
*/
|
||||
|
||||
/* UART */
|
||||
#define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020)
|
||||
/* LCD instruction and data addresses. */
|
||||
#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000))
|
||||
#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004))
|
||||
|
||||
/* Misc. */
|
||||
#define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000)
|
||||
/* Clock frequency in Hz (read-only): */
|
||||
#define XTFPGA_CLKFRQ_VADDR (XTFPGA_FPGAREGS_VADDR + 0x04)
|
||||
/* Setting of 8 DIP switches: */
|
||||
#define DIP_SWITCHES_VADDR (XTFPGA_FPGAREGS_VADDR + 0x0C)
|
||||
/* Software reset (write 0xdead): */
|
||||
#define XTFPGA_SWRST_VADDR (XTFPGA_FPGAREGS_VADDR + 0x10)
|
||||
|
||||
/* OpenCores Ethernet controller: */
|
||||
/* regs + RX/TX descriptors */
|
||||
#define OETH_REGS_PADDR (XCHAL_KIO_PADDR + 0x0D030000)
|
||||
#define OETH_REGS_SIZE 0x1000
|
||||
#define OETH_SRAMBUFF_PADDR (XCHAL_KIO_PADDR + 0x0D800000)
|
||||
|
||||
/* 5*rx buffs + 5*tx buffs */
|
||||
#define OETH_SRAMBUFF_SIZE (5 * 0x600 + 5 * 0x600)
|
||||
|
||||
#endif /* __XTENSA_XTAVNET_HARDWARE_H */
|
20
arch/xtensa/platforms/xtfpga/include/platform/lcd.h
Normal file
20
arch/xtensa/platforms/xtfpga/include/platform/lcd.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* arch/xtensa/platform/xtavnet/include/platform/lcd.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001, 2006 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef __XTENSA_XTAVNET_LCD_H
|
||||
#define __XTENSA_XTAVNET_LCD_H
|
||||
|
||||
/* Display string STR at position POS on the LCD. */
|
||||
void lcd_disp_at_pos(char *str, unsigned char pos);
|
||||
|
||||
/* Shift the contents of the LCD display left or right. */
|
||||
void lcd_shiftleft(void);
|
||||
void lcd_shiftright(void);
|
||||
#endif
|
18
arch/xtensa/platforms/xtfpga/include/platform/serial.h
Normal file
18
arch/xtensa/platforms/xtfpga/include/platform/serial.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* arch/xtensa/platform/xtavnet/include/platform/serial.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001, 2006 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_XTENSA_XTAVNET_SERIAL_H
|
||||
#define __ASM_XTENSA_XTAVNET_SERIAL_H
|
||||
|
||||
#include <platform/hardware.h>
|
||||
|
||||
#define BASE_BAUD (*(long *)XTFPGA_CLKFRQ_VADDR / 16)
|
||||
|
||||
#endif /* __ASM_XTENSA_XTAVNET_SERIAL_H */
|
76
arch/xtensa/platforms/xtfpga/lcd.c
Normal file
76
arch/xtensa/platforms/xtfpga/lcd.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Driver for the LCD display on the Tensilica LX60 Board.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001, 2006 Tensilica Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* FIXME: this code is from the examples from the LX60 user guide.
|
||||
*
|
||||
* The lcd_pause function does busy waiting, which is probably not
|
||||
* great. Maybe the code could be changed to use kernel timers, or
|
||||
* change the hardware to not need to wait.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <platform/hardware.h>
|
||||
#include <platform/lcd.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define LCD_PAUSE_ITERATIONS 4000
|
||||
#define LCD_CLEAR 0x1
|
||||
#define LCD_DISPLAY_ON 0xc
|
||||
|
||||
/* 8bit and 2 lines display */
|
||||
#define LCD_DISPLAY_MODE8BIT 0x38
|
||||
#define LCD_DISPLAY_POS 0x80
|
||||
#define LCD_SHIFT_LEFT 0x18
|
||||
#define LCD_SHIFT_RIGHT 0x1c
|
||||
|
||||
static int __init lcd_init(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
mdelay(5);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
udelay(200);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
udelay(50);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_ON;
|
||||
udelay(50);
|
||||
*LCD_INSTR_ADDR = LCD_CLEAR;
|
||||
mdelay(10);
|
||||
lcd_disp_at_pos("XTENSA LINUX", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lcd_disp_at_pos(char *str, unsigned char pos)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
|
||||
udelay(100);
|
||||
while (*str != 0) {
|
||||
*LCD_DATA_ADDR = *str;
|
||||
udelay(200);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_shiftleft(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
void lcd_shiftright(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
arch_initcall(lcd_init);
|
301
arch/xtensa/platforms/xtfpga/setup.c
Normal file
301
arch/xtensa/platforms/xtfpga/setup.c
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
*
|
||||
* arch/xtensa/platform/xtavnet/setup.c
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* Authors: Chris Zankel <chris@zankel.net>
|
||||
* Joe Taylor <joe@tensilica.com>
|
||||
*
|
||||
* Copyright 2001 - 2006 Tensilica Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/timex.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/platform.h>
|
||||
#include <asm/bootparam.h>
|
||||
#include <platform/lcd.h>
|
||||
#include <platform/hardware.h>
|
||||
|
||||
void platform_halt(void)
|
||||
{
|
||||
lcd_disp_at_pos(" HALT ", 0);
|
||||
local_irq_disable();
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
void platform_power_off(void)
|
||||
{
|
||||
lcd_disp_at_pos("POWEROFF", 0);
|
||||
local_irq_disable();
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
void platform_restart(void)
|
||||
{
|
||||
/* Flush and reset the mmu, simulate a processor reset, and
|
||||
* jump to the reset vector. */
|
||||
|
||||
|
||||
__asm__ __volatile__ ("movi a2, 15\n\t"
|
||||
"wsr a2, icountlevel\n\t"
|
||||
"movi a2, 0\n\t"
|
||||
"wsr a2, icount\n\t"
|
||||
"wsr a2, ibreakenable\n\t"
|
||||
"wsr a2, lcount\n\t"
|
||||
"movi a2, 0x1f\n\t"
|
||||
"wsr a2, ps\n\t"
|
||||
"isync\n\t"
|
||||
"jx %0\n\t"
|
||||
:
|
||||
: "a" (XCHAL_RESET_VECTOR_VADDR)
|
||||
: "a2"
|
||||
);
|
||||
|
||||
/* control never gets here */
|
||||
}
|
||||
|
||||
void __init platform_setup(char **cmdline)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static void __init update_clock_frequency(struct device_node *node)
|
||||
{
|
||||
struct property *newfreq;
|
||||
u32 freq;
|
||||
|
||||
if (!of_property_read_u32(node, "clock-frequency", &freq) && freq != 0)
|
||||
return;
|
||||
|
||||
newfreq = kzalloc(sizeof(*newfreq) + sizeof(u32), GFP_KERNEL);
|
||||
if (!newfreq)
|
||||
return;
|
||||
newfreq->value = newfreq + 1;
|
||||
newfreq->length = sizeof(freq);
|
||||
newfreq->name = kstrdup("clock-frequency", GFP_KERNEL);
|
||||
if (!newfreq->name) {
|
||||
kfree(newfreq);
|
||||
return;
|
||||
}
|
||||
|
||||
*(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR);
|
||||
prom_update_property(node, newfreq);
|
||||
}
|
||||
|
||||
#define MAC_LEN 6
|
||||
static void __init update_local_mac(struct device_node *node)
|
||||
{
|
||||
struct property *newmac;
|
||||
const u8* macaddr;
|
||||
int prop_len;
|
||||
|
||||
macaddr = of_get_property(node, "local-mac-address", &prop_len);
|
||||
if (macaddr == NULL || prop_len != MAC_LEN)
|
||||
return;
|
||||
|
||||
newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL);
|
||||
if (newmac == NULL)
|
||||
return;
|
||||
|
||||
newmac->value = newmac + 1;
|
||||
newmac->length = MAC_LEN;
|
||||
newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
|
||||
if (newmac->name == NULL) {
|
||||
kfree(newmac);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(newmac->value, macaddr, MAC_LEN);
|
||||
((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f;
|
||||
prom_update_property(node, newmac);
|
||||
}
|
||||
|
||||
static int __init machine_setup(void)
|
||||
{
|
||||
struct device_node *serial;
|
||||
struct device_node *eth = NULL;
|
||||
|
||||
for_each_compatible_node(serial, NULL, "ns16550a")
|
||||
update_clock_frequency(serial);
|
||||
|
||||
if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc")))
|
||||
update_local_mac(eth);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(machine_setup);
|
||||
|
||||
#endif
|
||||
|
||||
/* early initialization */
|
||||
|
||||
void __init platform_init(bp_tag_t *first)
|
||||
{
|
||||
}
|
||||
|
||||
/* Heartbeat. */
|
||||
|
||||
void platform_heartbeat(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
|
||||
|
||||
void platform_calibrate_ccount(void)
|
||||
{
|
||||
long clk_freq = 0;
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *cpu =
|
||||
of_find_compatible_node(NULL, NULL, "xtensa,cpu");
|
||||
if (cpu) {
|
||||
u32 freq;
|
||||
update_clock_frequency(cpu);
|
||||
if (!of_property_read_u32(cpu, "clock-frequency", &freq))
|
||||
clk_freq = freq;
|
||||
}
|
||||
#endif
|
||||
if (!clk_freq)
|
||||
clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR;
|
||||
|
||||
ccount_per_jiffy = clk_freq / HZ;
|
||||
nsec_per_ccount = 1000000000UL / clk_freq;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_OF
|
||||
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/if.h>
|
||||
#include <net/ethoc.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Ethernet -- OpenCores Ethernet MAC (ethoc driver)
|
||||
*/
|
||||
|
||||
static struct resource ethoc_res[] __initdata = {
|
||||
[0] = { /* register space */
|
||||
.start = OETH_REGS_PADDR,
|
||||
.end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = { /* buffer space */
|
||||
.start = OETH_SRAMBUFF_PADDR,
|
||||
.end = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = { /* IRQ number */
|
||||
.start = OETH_IRQ,
|
||||
.end = OETH_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ethoc_platform_data ethoc_pdata __initdata = {
|
||||
/*
|
||||
* The MAC address for these boards is 00:50:c2:13:6f:xx.
|
||||
* The last byte (here as zero) is read from the DIP switches on the
|
||||
* board.
|
||||
*/
|
||||
.hwaddr = { 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 },
|
||||
.phy_id = -1,
|
||||
};
|
||||
|
||||
static struct platform_device ethoc_device __initdata = {
|
||||
.name = "ethoc",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(ethoc_res),
|
||||
.resource = ethoc_res,
|
||||
.dev = {
|
||||
.platform_data = ðoc_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* UART
|
||||
*/
|
||||
|
||||
static struct resource serial_resource __initdata = {
|
||||
.start = DUART16552_PADDR,
|
||||
.end = DUART16552_PADDR + 0x1f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct plat_serial8250_port serial_platform_data[] __initdata = {
|
||||
[0] = {
|
||||
.mapbase = DUART16552_PADDR,
|
||||
.irq = DUART16552_INTNUM,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
|
||||
UPF_IOREMAP,
|
||||
.iotype = UPIO_MEM32,
|
||||
.regshift = 2,
|
||||
.uartclk = 0, /* set in xtavnet_init() */
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_device xtavnet_uart __initdata = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM,
|
||||
.dev = {
|
||||
.platform_data = serial_platform_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &serial_resource,
|
||||
};
|
||||
|
||||
/* platform devices */
|
||||
static struct platform_device *platform_devices[] __initdata = {
|
||||
ðoc_device,
|
||||
&xtavnet_uart,
|
||||
};
|
||||
|
||||
|
||||
static int __init xtavnet_init(void)
|
||||
{
|
||||
/* Ethernet MAC address. */
|
||||
ethoc_pdata.hwaddr[5] = *(u32 *)DIP_SWITCHES_VADDR;
|
||||
|
||||
/* Clock rate varies among FPGA bitstreams; board specific FPGA register
|
||||
* reports the actual clock rate.
|
||||
*/
|
||||
serial_platform_data[0].uartclk = *(long *)XTFPGA_CLKFRQ_VADDR;
|
||||
|
||||
|
||||
/* register platform devices */
|
||||
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
|
||||
|
||||
/* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user
|
||||
* knows whether they set it correctly on the DIP switches.
|
||||
*/
|
||||
pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register to be done during do_initcalls().
|
||||
*/
|
||||
arch_initcall(xtavnet_init);
|
||||
|
||||
#endif /* CONFIG_OF */
|
@ -164,7 +164,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc)
|
||||
int cirq;
|
||||
|
||||
chip->irq_mask(&desc->irq_data);
|
||||
chip->irq_ack(&desc->irq_data));
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
|
||||
cirq = IRQ_BASE - 1;
|
||||
while (pending) {
|
||||
@ -173,7 +173,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc)
|
||||
pending >>= n;
|
||||
generic_handle_irq(cirq);
|
||||
}
|
||||
chip->irq_unmask(&desc->irq_data));
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];
|
||||
|
Loading…
Reference in New Issue
Block a user