add preliminary LEON support
SVN-Revision: 25139
This commit is contained in:
		
							
								
								
									
										22
									
								
								target/linux/leon/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								target/linux/leon/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2011 OpenWrt.org
 | 
			
		||||
#
 | 
			
		||||
# This is free software, licensed under the GNU General Public License v2.
 | 
			
		||||
# See /LICENSE for more information.
 | 
			
		||||
#
 | 
			
		||||
include $(TOPDIR)/rules.mk
 | 
			
		||||
 | 
			
		||||
ARCH:=sparc
 | 
			
		||||
BOARD:=leon
 | 
			
		||||
BOARDNAME:=LEON
 | 
			
		||||
FEATURES+=fpu tgz
 | 
			
		||||
 | 
			
		||||
CFLAGS:=-Os -pipe -mcpu=v8 -funit-at-a-time
 | 
			
		||||
KERNELNAME:="uImage"
 | 
			
		||||
 | 
			
		||||
LINUX_VERSION:=2.6.36.2
 | 
			
		||||
MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
 | 
			
		||||
 | 
			
		||||
include $(INCLUDE_DIR)/target.mk
 | 
			
		||||
 | 
			
		||||
$(eval $(call BuildTarget))
 | 
			
		||||
							
								
								
									
										138
									
								
								target/linux/leon/config-default
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								target/linux/leon/config-default
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
# CONFIG_64BIT is not set
 | 
			
		||||
CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc32_defconfig"
 | 
			
		||||
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 | 
			
		||||
CONFIG_ARCH_NO_VIRT_TO_BUS=y
 | 
			
		||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
 | 
			
		||||
CONFIG_ARCH_USES_GETTIMEOFFSET=y
 | 
			
		||||
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 | 
			
		||||
# CONFIG_ARPD is not set
 | 
			
		||||
CONFIG_ATA=y
 | 
			
		||||
CONFIG_AUDIT_ARCH=y
 | 
			
		||||
CONFIG_BITS=32
 | 
			
		||||
# CONFIG_BLK_DEV_INITRD is not set
 | 
			
		||||
CONFIG_BLK_DEV_LOOP=y
 | 
			
		||||
CONFIG_BLK_DEV_SD=y
 | 
			
		||||
CONFIG_BOUNCE=y
 | 
			
		||||
# CONFIG_BRIDGE is not set
 | 
			
		||||
# CONFIG_BSD_PROCESS_ACCT is not set
 | 
			
		||||
CONFIG_COMPAT_BRK=y
 | 
			
		||||
CONFIG_CONSOLE_TRANSLATIONS=y
 | 
			
		||||
CONFIG_DEBUG_BUGVERBOSE=y
 | 
			
		||||
CONFIG_DECOMPRESS_LZMA=y
 | 
			
		||||
CONFIG_DNOTIFY=y
 | 
			
		||||
CONFIG_DUMMY_CONSOLE=y
 | 
			
		||||
CONFIG_ELF_CORE=y
 | 
			
		||||
CONFIG_EMULATED_CMPXCHG=y
 | 
			
		||||
CONFIG_ENABLE_MUST_CHECK=y
 | 
			
		||||
CONFIG_FB=y
 | 
			
		||||
# CONFIG_FB_IGA is not set
 | 
			
		||||
# CONFIG_FB_SBUS is not set
 | 
			
		||||
# CONFIG_FB_SM7XX is not set
 | 
			
		||||
# CONFIG_FB_XGI is not set
 | 
			
		||||
# CONFIG_FIRMWARE_EDID is not set
 | 
			
		||||
CONFIG_FIRMWARE_IN_KERNEL=y
 | 
			
		||||
# CONFIG_FONTS is not set
 | 
			
		||||
# CONFIG_FONT_SUN12x22 is not set
 | 
			
		||||
CONFIG_FONT_SUN8x16=y
 | 
			
		||||
CONFIG_FRAMEBUFFER_CONSOLE=y
 | 
			
		||||
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 | 
			
		||||
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 | 
			
		||||
CONFIG_FS_POSIX_ACL=y
 | 
			
		||||
CONFIG_GENERIC_ACL=y
 | 
			
		||||
CONFIG_GENERIC_CMOS_UPDATE=y
 | 
			
		||||
CONFIG_GENERIC_FIND_LAST_BIT=y
 | 
			
		||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
 | 
			
		||||
CONFIG_GENERIC_ISA_DMA=y
 | 
			
		||||
# CONFIG_GRETH is not set
 | 
			
		||||
# CONFIG_HAMRADIO is not set
 | 
			
		||||
CONFIG_HAPPYMEAL=y
 | 
			
		||||
CONFIG_HAS_DMA=y
 | 
			
		||||
CONFIG_HAS_IOMEM=y
 | 
			
		||||
CONFIG_HAS_IOPORT=y
 | 
			
		||||
CONFIG_HAVE_ARCH_TRACEHOOK=y
 | 
			
		||||
CONFIG_HAVE_DMA_API_DEBUG=y
 | 
			
		||||
CONFIG_HAVE_DMA_ATTRS=y
 | 
			
		||||
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 | 
			
		||||
CONFIG_HAVE_IDE=y
 | 
			
		||||
CONFIG_HAVE_OPROFILE=y
 | 
			
		||||
CONFIG_HAVE_PERF_EVENTS=y
 | 
			
		||||
CONFIG_HID=m
 | 
			
		||||
CONFIG_HID_SUPPORT=y
 | 
			
		||||
CONFIG_HIGHMEM=y
 | 
			
		||||
CONFIG_HW_CONSOLE=y
 | 
			
		||||
CONFIG_HZ=250
 | 
			
		||||
# CONFIG_HZ_100 is not set
 | 
			
		||||
CONFIG_HZ_250=y
 | 
			
		||||
CONFIG_INOTIFY_USER=y
 | 
			
		||||
CONFIG_INPUT=y
 | 
			
		||||
CONFIG_INPUT_EVDEV=y
 | 
			
		||||
CONFIG_INPUT_POLLDEV=y
 | 
			
		||||
CONFIG_LEGACY_PTYS=y
 | 
			
		||||
CONFIG_LEGACY_PTY_COUNT=256
 | 
			
		||||
CONFIG_LOCK_KERNEL=y
 | 
			
		||||
# CONFIG_MISC_DEVICES is not set
 | 
			
		||||
# CONFIG_MTD is not set
 | 
			
		||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
 | 
			
		||||
# CONFIG_MYRI_SBUS is not set
 | 
			
		||||
CONFIG_NEED_DMA_MAP_STATE=y
 | 
			
		||||
CONFIG_NEED_SG_DMA_LENGTH=y
 | 
			
		||||
CONFIG_NR_CPUS=4
 | 
			
		||||
CONFIG_OF=y
 | 
			
		||||
CONFIG_OF_DEVICE=y
 | 
			
		||||
CONFIG_PAGEFLAGS_EXTENDED=y
 | 
			
		||||
# CONFIG_PARTITION_ADVANCED is not set
 | 
			
		||||
CONFIG_PATA_CMD64X=y
 | 
			
		||||
CONFIG_PCI=y
 | 
			
		||||
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
 | 
			
		||||
CONFIG_PERF_USE_VMALLOC=y
 | 
			
		||||
CONFIG_PROC_PAGE_MONITOR=y
 | 
			
		||||
CONFIG_RELAY=y
 | 
			
		||||
CONFIG_RTC_CLASS=y
 | 
			
		||||
CONFIG_RTC_DRV_BQ4802=y
 | 
			
		||||
CONFIG_RTC_DRV_M48T59=y
 | 
			
		||||
CONFIG_SATA_PMP=y
 | 
			
		||||
CONFIG_SBUS=y
 | 
			
		||||
CONFIG_SBUSCHAR=y
 | 
			
		||||
# CONFIG_SCHED_HRTICK is not set
 | 
			
		||||
CONFIG_SCSI=y
 | 
			
		||||
# CONFIG_SCSI_LOWLEVEL is not set
 | 
			
		||||
# CONFIG_SCSI_MULTI_LUN is not set
 | 
			
		||||
CONFIG_SERIAL_8250_NR_UARTS=4
 | 
			
		||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 | 
			
		||||
CONFIG_SERIAL_CONSOLE=y
 | 
			
		||||
CONFIG_SERIAL_SUNCORE=y
 | 
			
		||||
CONFIG_SERIAL_SUNSAB=y
 | 
			
		||||
CONFIG_SERIAL_SUNSAB_CONSOLE=y
 | 
			
		||||
CONFIG_SERIAL_SUNSU=y
 | 
			
		||||
CONFIG_SERIAL_SUNSU_CONSOLE=y
 | 
			
		||||
# CONFIG_SERIAL_SUNZILOG is not set
 | 
			
		||||
# CONFIG_SLAB is not set
 | 
			
		||||
CONFIG_SLUB=y
 | 
			
		||||
CONFIG_SMP=y
 | 
			
		||||
CONFIG_SPARC=y
 | 
			
		||||
CONFIG_SPARC32=y
 | 
			
		||||
CONFIG_SPARC32_PCI=y
 | 
			
		||||
CONFIG_SPARC32_SMP=y
 | 
			
		||||
# CONFIG_SPARC64 is not set
 | 
			
		||||
# CONFIG_SPARC_LED is not set
 | 
			
		||||
CONFIG_SPARC_LEON=y
 | 
			
		||||
CONFIG_STOP_MACHINE=y
 | 
			
		||||
# CONFIG_SUNBMAC is not set
 | 
			
		||||
# CONFIG_SUNLANCE is not set
 | 
			
		||||
# CONFIG_SUNQE is not set
 | 
			
		||||
# CONFIG_SUN_JSFLASH is not set
 | 
			
		||||
CONFIG_SUN_OPENPROMFS=y
 | 
			
		||||
CONFIG_SUN_OPENPROMIO=y
 | 
			
		||||
CONFIG_SUN_PARTITION=y
 | 
			
		||||
CONFIG_SUN_PM=y
 | 
			
		||||
# CONFIG_TADPOLE_TS102_UCTRL is not set
 | 
			
		||||
CONFIG_TMPFS_POSIX_ACL=y
 | 
			
		||||
CONFIG_TREE_RCU=y
 | 
			
		||||
CONFIG_UID16=y
 | 
			
		||||
CONFIG_USB_SUPPORT=y
 | 
			
		||||
# CONFIG_VLAN_8021Q is not set
 | 
			
		||||
CONFIG_VM_EVENT_COUNTERS=y
 | 
			
		||||
CONFIG_VT=y
 | 
			
		||||
CONFIG_VT_CONSOLE=y
 | 
			
		||||
CONFIG_VT_HW_CONSOLE_BINDING=y
 | 
			
		||||
# CONFIG_WATCHDOG is not set
 | 
			
		||||
							
								
								
									
										19
									
								
								target/linux/leon/image/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								target/linux/leon/image/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2011 OpenWrt.org
 | 
			
		||||
#
 | 
			
		||||
# This is free software, licensed under the GNU General Public License v2.
 | 
			
		||||
# See /LICENSE for more information.
 | 
			
		||||
#
 | 
			
		||||
include $(TOPDIR)/rules.mk
 | 
			
		||||
include $(INCLUDE_DIR)/image.mk
 | 
			
		||||
 | 
			
		||||
define Image/Prepare
 | 
			
		||||
	cp $(LINUX_DIR)/arch/sparc/boot/uImage $(KDIR)/uImage
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
define Image/BuildKernel
 | 
			
		||||
	mkdir -p $(BIN_DIR)
 | 
			
		||||
	cp $(KDIR)/uImage $(BIN_DIR)/$(IMG_PREFIX)-uImage
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
$(eval $(call BuildImage))
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
From af1da1d5a8701f39cdbae4a0ab8e04b450eef298 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 8 Sep 2010 18:05:38 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: find IRQ and Timer via OF-Tree, instead of hardcoded.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c |   23 ++++++++++++++++++++++-
 | 
			
		||||
 1 files changed, 22 insertions(+), 1 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -105,13 +105,34 @@ static void leon_disable_irq(unsigned in
 | 
			
		||||
 void __init leon_init_timers(irq_handler_t counter_fn)
 | 
			
		||||
 {
 | 
			
		||||
 	int irq;
 | 
			
		||||
+	struct device_node *rootnp, *np;
 | 
			
		||||
+	struct property *pp;
 | 
			
		||||
+	int len;
 | 
			
		||||
 
 | 
			
		||||
 	leondebug_irq_disable = 0;
 | 
			
		||||
 	leon_debug_irqout = 0;
 | 
			
		||||
 	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
 | 
			
		||||
 	dummy_master_l10_counter = 0;
 | 
			
		||||
 
 | 
			
		||||
-	if (leon3_gptimer_regs && leon3_irqctrl_regs) {
 | 
			
		||||
+	/* Find IRQMP IRQ Controller Registers base address otherwise bail out. */
 | 
			
		||||
+	rootnp = of_find_node_by_path("/ambapp0");
 | 
			
		||||
+	if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) {
 | 
			
		||||
+		pp = of_find_property(np, "reg", &len);
 | 
			
		||||
+		if (pp)
 | 
			
		||||
+			leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 | 
			
		||||
+	if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) {
 | 
			
		||||
+		pp = of_find_property(np, "reg", &len);
 | 
			
		||||
+		if (pp)
 | 
			
		||||
+			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value;
 | 
			
		||||
+		pp = of_find_property(np, "interrupts", &len);
 | 
			
		||||
+		if (pp)
 | 
			
		||||
+			leon3_gptimer_irq = *(unsigned int *)pp->value;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
 | 
			
		||||
 				      (((1000000 / 100) - 1)));
 | 
			
		||||
							
								
								
									
										79
									
								
								target/linux/leon/patches/002-sparc_uimage_target.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								target/linux/leon/patches/002-sparc_uimage_target.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
From 234ef25344b567b3b8dad62c0863ebe16377528f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Tue, 14 Sep 2010 11:26:55 +0200
 | 
			
		||||
Subject: [PATCH] SPARC: added U-Boot build target: uImage
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/Makefile      |    3 ++-
 | 
			
		||||
 arch/sparc/boot/Makefile |   35 +++++++++++++++++++++++++++++++++++
 | 
			
		||||
 2 files changed, 37 insertions(+), 1 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/Makefile
 | 
			
		||||
+++ b/arch/sparc/Makefile
 | 
			
		||||
@@ -88,7 +88,7 @@ boot := arch/sparc/boot
 | 
			
		||||
 # Default target
 | 
			
		||||
 all: zImage
 | 
			
		||||
 
 | 
			
		||||
-image zImage tftpboot.img vmlinux.aout: vmlinux
 | 
			
		||||
+image zImage uImage tftpboot.img vmlinux.aout: vmlinux
 | 
			
		||||
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 | 
			
		||||
 
 | 
			
		||||
 archclean:
 | 
			
		||||
@@ -102,6 +102,7 @@ ifeq ($(ARCH),sparc)
 | 
			
		||||
 define archhelp
 | 
			
		||||
   echo  '* image        - kernel image ($(boot)/image)'
 | 
			
		||||
   echo  '* zImage       - stripped kernel image ($(boot)/zImage)'
 | 
			
		||||
+  echo  '  uImage       - U-Boot SPARC32/LEON Image'
 | 
			
		||||
   echo  '  tftpboot.img - image prepared for tftp'
 | 
			
		||||
 endef
 | 
			
		||||
 else
 | 
			
		||||
--- a/arch/sparc/boot/Makefile
 | 
			
		||||
+++ b/arch/sparc/boot/Makefile
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 
 | 
			
		||||
 ROOT_IMG	:= /usr/src/root.img
 | 
			
		||||
 ELFTOAOUT	:= elftoaout
 | 
			
		||||
+MKIMAGE 	:= $(srctree)/scripts/mkuboot.sh
 | 
			
		||||
 
 | 
			
		||||
 hostprogs-y	:= piggyback_32 piggyback_64 btfixupprep
 | 
			
		||||
 targets		:= tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
 | 
			
		||||
@@ -90,5 +91,39 @@ $(obj)/tftpboot.img: $(obj)/image $(obj)
 | 
			
		||||
 $(obj)/vmlinux.aout: vmlinux FORCE
 | 
			
		||||
 	$(call if_changed,elftoaout)
 | 
			
		||||
 	@echo '  kernel: $@ is ready'
 | 
			
		||||
+else
 | 
			
		||||
+
 | 
			
		||||
+# The following lines make a readable image for U-Boot.
 | 
			
		||||
+#  uImage   - Binary file read by U-boot
 | 
			
		||||
+#  uImage.o - object file of uImage for loading with a
 | 
			
		||||
+#             flash programmer understanding ELF.
 | 
			
		||||
+
 | 
			
		||||
+OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment
 | 
			
		||||
+$(obj)/image.bin: $(obj)/image FORCE
 | 
			
		||||
+	$(call if_changed,objcopy)
 | 
			
		||||
+
 | 
			
		||||
+$(obj)/image.gz: $(obj)/image.bin
 | 
			
		||||
+	$(call if_changed,gzip)
 | 
			
		||||
+
 | 
			
		||||
+# Start of Main memory
 | 
			
		||||
+ifndef UIMAGE_LOADADDR
 | 
			
		||||
+UIMAGE_LOADADDR=0x40004000
 | 
			
		||||
 endif
 | 
			
		||||
 
 | 
			
		||||
+# The first sector after the U-Boot image (256k)
 | 
			
		||||
+ifndef UIMAGE_FLASHADDR
 | 
			
		||||
+UIMAGE_FLASHADDR=0x00040000
 | 
			
		||||
+endif
 | 
			
		||||
+
 | 
			
		||||
+quiet_cmd_uimage = UIMAGE  $@
 | 
			
		||||
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \
 | 
			
		||||
+               -C gzip -a $(UIMAGE_LOADADDR) -e 0xf0004000 -n 'Linux-$(KERNELRELEASE)' \
 | 
			
		||||
+               -d $< $@
 | 
			
		||||
+
 | 
			
		||||
+targets += uImage
 | 
			
		||||
+$(obj)/uImage: $(obj)/image.gz
 | 
			
		||||
+	$(call if_changed,uimage)
 | 
			
		||||
+	sparc-linux-ld -Tdata $(UIMAGE_FLASHADDR) -r -b binary arch/sparc/boot/uImage -o arch/sparc/boot/uImage.o
 | 
			
		||||
+	@echo '  Image $@ is ready'
 | 
			
		||||
+
 | 
			
		||||
+endif
 | 
			
		||||
							
								
								
									
										23
									
								
								target/linux/leon/patches/003-smp_cpu_stuck_fix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								target/linux/leon/patches/003-smp_cpu_stuck_fix.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
From 417bc6751fdd3c24df274f25e020ec3decd09280 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Thu, 16 Sep 2010 11:00:46 +0200
 | 
			
		||||
Subject: [PATCH] Fixed SPARC/LEON SMP CPU Stuck problem.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/leon_smp.c |    4 ++--
 | 
			
		||||
 1 files changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/leon_smp.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_smp.c
 | 
			
		||||
@@ -56,8 +56,8 @@ void __init leon_configure_cache_smp(voi
 | 
			
		||||
 static inline unsigned long do_swap(volatile unsigned long *ptr,
 | 
			
		||||
 				    unsigned long val)
 | 
			
		||||
 {
 | 
			
		||||
-	__asm__ __volatile__("swapa [%1] %2, %0\n\t" : "=&r"(val)
 | 
			
		||||
-			     : "r"(ptr), "i"(ASI_LEON_DCACHE_MISS)
 | 
			
		||||
+	__asm__ __volatile__("swapa [%2] %3, %0\n\t" : "=&r"(val)
 | 
			
		||||
+			     : "0"(val), "r"(ptr), "i"(ASI_LEON_DCACHE_MISS)
 | 
			
		||||
 			     : "memory");
 | 
			
		||||
 	return val;
 | 
			
		||||
 }
 | 
			
		||||
							
								
								
									
										119
									
								
								target/linux/leon/patches/004-extended_irq_controller.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								target/linux/leon/patches/004-extended_irq_controller.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Thu, 16 Sep 2010 11:12:41 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/include/asm/irq_32.h |    4 ++++
 | 
			
		||||
 arch/sparc/kernel/irq_32.c      |   32 ++++++++++++++++++++++++++------
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c |    8 +++++++-
 | 
			
		||||
 3 files changed, 37 insertions(+), 7 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/include/asm/irq_32.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/irq_32.h
 | 
			
		||||
@@ -6,7 +6,11 @@
 | 
			
		||||
 #ifndef _SPARC_IRQ_H
 | 
			
		||||
 #define _SPARC_IRQ_H
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+#define NR_IRQS    32
 | 
			
		||||
+#else
 | 
			
		||||
 #define NR_IRQS    16
 | 
			
		||||
+#endif
 | 
			
		||||
 
 | 
			
		||||
 #include <linux/interrupt.h>
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/sparc/kernel/irq_32.c
 | 
			
		||||
+++ b/arch/sparc/kernel/irq_32.c
 | 
			
		||||
@@ -110,6 +110,11 @@ EXPORT_SYMBOL(__raw_local_irq_save);
 | 
			
		||||
 EXPORT_SYMBOL(raw_local_irq_enable);
 | 
			
		||||
 EXPORT_SYMBOL(raw_local_irq_restore);
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+extern unsigned int sparc_leon_eirq;
 | 
			
		||||
+extern int sparc_leon_eirq_get(int eirq, int cpu);
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 /*
 | 
			
		||||
  * Dave Redman (djhr@tadpole.co.uk)
 | 
			
		||||
  *
 | 
			
		||||
@@ -222,10 +227,11 @@ void free_irq(unsigned int irq, void *de
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 	cpu_irq = irq & (NR_IRQS - 1);
 | 
			
		||||
-        if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
 | 
			
		||||
-                printk("Trying to free bogus IRQ %d\n", irq);
 | 
			
		||||
-                return;
 | 
			
		||||
-        }
 | 
			
		||||
+	/* 14 irq levels on the sparc, however some LEON systems have 31 IRQs */
 | 
			
		||||
+	if ((cpu_irq == 15) || (cpu_irq >= NR_IRQS)) {  
 | 
			
		||||
+		printk("Trying to free bogus IRQ %d\n", irq);
 | 
			
		||||
+		return;
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	spin_lock_irqsave(&irq_action_lock, flags);
 | 
			
		||||
 
 | 
			
		||||
@@ -303,7 +309,14 @@ void unexpected_irq(int irq, void *dev_i
 | 
			
		||||
         int i;
 | 
			
		||||
 	struct irqaction * action;
 | 
			
		||||
 	unsigned int cpu_irq;
 | 
			
		||||
-	
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+	/* LEON Extended IRQ requires one extra IRQ Number fetch stage */
 | 
			
		||||
+	if ( sparc_leon_eirq == irq ) {
 | 
			
		||||
+		irq = sparc_leon_eirq_get(irq, smp_processor_id());
 | 
			
		||||
+	}
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 	cpu_irq = irq & (NR_IRQS - 1);
 | 
			
		||||
 	action = sparc_irq[cpu_irq].action;
 | 
			
		||||
 
 | 
			
		||||
@@ -330,6 +343,13 @@ void handler_irq(int irq, struct pt_regs
 | 
			
		||||
 	extern void smp4m_irq_rotate(int cpu);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+	/* LEON Extended IRQ requires one extra IRQ Number fetch stage */
 | 
			
		||||
+	if ( sparc_leon_eirq == irq ) {
 | 
			
		||||
+		irq = sparc_leon_eirq_get(irq, cpu);
 | 
			
		||||
+	}
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 	old_regs = set_irq_regs(regs);
 | 
			
		||||
 	irq_enter();
 | 
			
		||||
 	disable_pil_irq(irq);
 | 
			
		||||
@@ -526,7 +546,7 @@ int request_irq(unsigned int irq,
 | 
			
		||||
 		return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
 | 
			
		||||
 	}
 | 
			
		||||
 	cpu_irq = irq & (NR_IRQS - 1);
 | 
			
		||||
-	if(cpu_irq > 14) {
 | 
			
		||||
+	if(cpu_irq == 15) {
 | 
			
		||||
 		ret = -EINVAL;
 | 
			
		||||
 		goto out;
 | 
			
		||||
 	}
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -104,7 +104,7 @@ static void leon_disable_irq(unsigned in
 | 
			
		||||
 
 | 
			
		||||
 void __init leon_init_timers(irq_handler_t counter_fn)
 | 
			
		||||
 {
 | 
			
		||||
-	int irq;
 | 
			
		||||
+	int irq, eirq;
 | 
			
		||||
 	struct device_node *rootnp, *np;
 | 
			
		||||
 	struct property *pp;
 | 
			
		||||
 	int len;
 | 
			
		||||
@@ -153,6 +153,12 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
 | 
			
		||||
+		eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf;
 | 
			
		||||
+		if ( eirq != 0 ) {
 | 
			
		||||
+			/* Extended IRQ controller available */
 | 
			
		||||
+			sparc_leon_eirq_register(eirq);
 | 
			
		||||
+		}
 | 
			
		||||
 	} else {
 | 
			
		||||
 		printk(KERN_ERR "No Timer/irqctrl found\n");
 | 
			
		||||
 		BUG();
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
From 486a578298b7ab45c3edfdce8d4feaef93c3229b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Thu, 16 Sep 2010 11:15:37 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: to avoid name duplicates in openprom fs when REG is not available the NAME now includes NODE ID when REG not present
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/prom_32.c |   27 +++++++++++++++++++--------
 | 
			
		||||
 1 files changed, 19 insertions(+), 8 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/prom_32.c
 | 
			
		||||
+++ b/arch/sparc/kernel/prom_32.c
 | 
			
		||||
@@ -136,18 +136,29 @@ static void __init ebus_path_component(s
 | 
			
		||||
 /* "name:vendor:device@irq,addrlo" */
 | 
			
		||||
 static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
 | 
			
		||||
 {
 | 
			
		||||
-	struct amba_prom_registers *regs; unsigned int *intr;
 | 
			
		||||
-	unsigned int *device, *vendor;
 | 
			
		||||
+	struct amba_prom_registers *regs;
 | 
			
		||||
+	unsigned int *intr, *device, *vendor, reg0;
 | 
			
		||||
 	struct property *prop;
 | 
			
		||||
+	int interrupt = 0;
 | 
			
		||||
 
 | 
			
		||||
+	/* In order to get a unique ID in the device tree (multiple AMBA devices 
 | 
			
		||||
+	 * may have the same name) the node number is printed
 | 
			
		||||
+	 */
 | 
			
		||||
 	prop = of_find_property(dp, "reg", NULL);
 | 
			
		||||
-	if (!prop)
 | 
			
		||||
-		return;
 | 
			
		||||
-	regs = prop->value;
 | 
			
		||||
+	if (!prop) {
 | 
			
		||||
+		reg0 = (unsigned int)dp->phandle;
 | 
			
		||||
+	} else {
 | 
			
		||||
+		regs = prop->value;
 | 
			
		||||
+		reg0 = regs->phys_addr;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Not all cores have Interrupt */
 | 
			
		||||
 	prop = of_find_property(dp, "interrupts", NULL);
 | 
			
		||||
 	if (!prop)
 | 
			
		||||
-		return;
 | 
			
		||||
-	intr = prop->value;
 | 
			
		||||
+		intr = &interrupt; /* IRQ0 does not exist */
 | 
			
		||||
+	else
 | 
			
		||||
+		intr = prop->value;
 | 
			
		||||
+
 | 
			
		||||
 	prop = of_find_property(dp, "vendor", NULL);
 | 
			
		||||
 	if (!prop)
 | 
			
		||||
 		return;
 | 
			
		||||
@@ -159,7 +170,7 @@ static void __init ambapp_path_component
 | 
			
		||||
 
 | 
			
		||||
 	sprintf(tmp_buf, "%s:%d:%d@%x,%x",
 | 
			
		||||
 		dp->name, *vendor, *device,
 | 
			
		||||
-		*intr, regs->phys_addr);
 | 
			
		||||
+		*intr, reg0);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
 | 
			
		||||
							
								
								
									
										85
									
								
								target/linux/leon/patches/006-amp_support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								target/linux/leon/patches/006-amp_support.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
From 25a68b8cd8ea1553f8b56278418d6c1ecc12e247 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 22 Sep 2010 10:19:34 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: added support for AMP systems with IRQAMP IRQ Controller.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/include/asm/leon.h      |   12 ++++++++++++
 | 
			
		||||
 arch/sparc/include/asm/leon_amba.h |    6 +++---
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c    |   14 ++++++++++++++
 | 
			
		||||
 3 files changed, 29 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/include/asm/leon.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/leon.h
 | 
			
		||||
@@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_c
 | 
			
		||||
 			  "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static inline unsigned long sparc_leon3_asr17(void)
 | 
			
		||||
+{
 | 
			
		||||
+	u32 asr17;
 | 
			
		||||
+	__asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
 | 
			
		||||
+	return asr17;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+static inline int sparc_leon3_cpuid(void)
 | 
			
		||||
+{
 | 
			
		||||
+	return sparc_leon3_asr17() >> 28;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 #endif /*!__ASSEMBLY__*/
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_SMP
 | 
			
		||||
--- a/arch/sparc/include/asm/leon_amba.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/leon_amba.h
 | 
			
		||||
@@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map {
 | 
			
		||||
 	u32 mpbroadcast;
 | 
			
		||||
 	u32 notused02;
 | 
			
		||||
 	u32 notused03;
 | 
			
		||||
-	u32 notused10;
 | 
			
		||||
-	u32 notused11;
 | 
			
		||||
-	u32 notused12;
 | 
			
		||||
+	u32 ampctrl;
 | 
			
		||||
+	u32 icsel[2];
 | 
			
		||||
 	u32 notused13;
 | 
			
		||||
 	u32 notused20;
 | 
			
		||||
 	u32 notused21;
 | 
			
		||||
@@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map {
 | 
			
		||||
 	u32 force[16];
 | 
			
		||||
 	/* Extended IRQ registers */
 | 
			
		||||
 	u32 intid[16];	/* 0xc0 */
 | 
			
		||||
+	u32 unused[(0x1000-0x100)/4];
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct leon3_apbuart_regs_map {
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -108,6 +108,7 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	struct device_node *rootnp, *np;
 | 
			
		||||
 	struct property *pp;
 | 
			
		||||
 	int len;
 | 
			
		||||
+	int cpu, icsel;
 | 
			
		||||
 
 | 
			
		||||
 	leondebug_irq_disable = 0;
 | 
			
		||||
 	leon_debug_irqout = 0;
 | 
			
		||||
@@ -153,6 +154,19 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
+		/* The IRQ controller may (if implemented) consist of multiple
 | 
			
		||||
+		 * IRQ controllers, each mapped on a 4Kb boundary.
 | 
			
		||||
+		 * Each CPU may be routed to different IRQCTRLs, however
 | 
			
		||||
+		 * we assume that all CPUs (in SMP system) is routed to the
 | 
			
		||||
+		 * same IRQ Controller, and for non-SMP only one IRQCTRL is
 | 
			
		||||
+		 * accessed anyway.
 | 
			
		||||
+		 * In AMP systems, Linux may not be run on CPU0.
 | 
			
		||||
+		 */
 | 
			
		||||
+		cpu = sparc_leon3_cpuid();
 | 
			
		||||
+		icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
 | 
			
		||||
+		icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
 | 
			
		||||
+		leon3_irqctrl_regs += icsel;
 | 
			
		||||
+
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
 | 
			
		||||
 		eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf;
 | 
			
		||||
 		if ( eirq != 0 ) {
 | 
			
		||||
							
								
								
									
										119
									
								
								target/linux/leon/patches/007-amp_timer.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								target/linux/leon/patches/007-amp_timer.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
From 1dffe06838c26b7c3fc99f9ddb7db78e378f6908 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 22 Sep 2010 13:21:13 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: added support for selecting Timer Core and Timer within core, useful for AMP systems.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c |   41 +++++++++++++++++++++++++-------------
 | 
			
		||||
 1 files changed, 27 insertions(+), 14 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -23,15 +23,16 @@
 | 
			
		||||
 #include "prom.h"
 | 
			
		||||
 #include "irq.h"
 | 
			
		||||
 
 | 
			
		||||
-struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */
 | 
			
		||||
-struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */
 | 
			
		||||
+struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */
 | 
			
		||||
+struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */
 | 
			
		||||
 struct amba_apb_device leon_percpu_timer_dev[16];
 | 
			
		||||
 
 | 
			
		||||
 int leondebug_irq_disable;
 | 
			
		||||
 int leon_debug_irqout;
 | 
			
		||||
 static int dummy_master_l10_counter;
 | 
			
		||||
 
 | 
			
		||||
-unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */
 | 
			
		||||
+unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */
 | 
			
		||||
+unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */
 | 
			
		||||
 unsigned int sparc_leon_eirq;
 | 
			
		||||
 #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +110,7 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	struct property *pp;
 | 
			
		||||
 	int len;
 | 
			
		||||
 	int cpu, icsel;
 | 
			
		||||
+	int ampopts;
 | 
			
		||||
 
 | 
			
		||||
 	leondebug_irq_disable = 0;
 | 
			
		||||
 	leon_debug_irqout = 0;
 | 
			
		||||
@@ -124,24 +126,35 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 | 
			
		||||
-	if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) {
 | 
			
		||||
+	np = rootnp;
 | 
			
		||||
+	while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) {
 | 
			
		||||
+		ampopts = 0;
 | 
			
		||||
+		pp = of_find_property(np, "ampopts", &len);
 | 
			
		||||
+		if ( pp && ((ampopts = *(int *)pp->value) == 0) ) {
 | 
			
		||||
+			/* Skip this instance, resource already allocated by other OS */
 | 
			
		||||
+			continue;
 | 
			
		||||
+		}
 | 
			
		||||
+		/* Select Timer-Instance on Timer Core. Default is zero */
 | 
			
		||||
+		leon3_gptimer_idx = ampopts & 0x7;
 | 
			
		||||
+
 | 
			
		||||
 		pp = of_find_property(np, "reg", &len);
 | 
			
		||||
 		if (pp)
 | 
			
		||||
 			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value;
 | 
			
		||||
 		pp = of_find_property(np, "interrupts", &len);
 | 
			
		||||
 		if (pp)
 | 
			
		||||
 			leon3_gptimer_irq = *(unsigned int *)pp->value;
 | 
			
		||||
+		break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
 | 
			
		||||
 				      (((1000000 / 100) - 1)));
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_SMP
 | 
			
		||||
 		leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
 | 
			
		||||
-		leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1;
 | 
			
		||||
+		leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx;
 | 
			
		||||
 
 | 
			
		||||
 		if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
 | 
			
		||||
 		      (1<<LEON3_GPTIMER_SEPIRQ))) {
 | 
			
		||||
@@ -149,9 +162,9 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 			BUG();
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1)));
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1)));
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
 		/* The IRQ controller may (if implemented) consist of multiple
 | 
			
		||||
@@ -178,7 +191,7 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 		BUG();
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	irq = request_irq(leon3_gptimer_irq,
 | 
			
		||||
+	irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx,
 | 
			
		||||
 			  counter_fn,
 | 
			
		||||
 			  (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -210,13 +223,13 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
 	if (leon3_gptimer_regs) {
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
 | 
			
		||||
 				      LEON3_GPTIMER_EN |
 | 
			
		||||
 				      LEON3_GPTIMER_RL |
 | 
			
		||||
 				      LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_SMP
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl,
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
 | 
			
		||||
 				      LEON3_GPTIMER_EN |
 | 
			
		||||
 				      LEON3_GPTIMER_RL |
 | 
			
		||||
 				      LEON3_GPTIMER_LD |
 | 
			
		||||
							
								
								
									
										30
									
								
								target/linux/leon/patches/008-hz_specific_timer_init.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								target/linux/leon/patches/008-hz_specific_timer_init.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
From e4d697dad4d43109f045a4f25cb1d706122045c0 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 22 Sep 2010 13:24:36 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: removed constant timer initialization as if HZ=100, now it reflects the value of HZ
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c |    4 ++--
 | 
			
		||||
 1 files changed, 2 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -149,7 +149,7 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
 | 
			
		||||
-				      (((1000000 / 100) - 1)));
 | 
			
		||||
+				      (((1000000 / HZ) - 1)));
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_SMP
 | 
			
		||||
@@ -163,7 +163,7 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1)));
 | 
			
		||||
+		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1)));
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										187
									
								
								target/linux/leon/patches/009-remove_second_timer.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								target/linux/leon/patches/009-remove_second_timer.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 22 Sep 2010 15:39:05 +0200
 | 
			
		||||
Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/include/asm/leon.h      |    2 +-
 | 
			
		||||
 arch/sparc/include/asm/leon_amba.h |    3 +-
 | 
			
		||||
 arch/sparc/kernel/entry.S          |    3 +-
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c    |   37 ++++++++---------------------------
 | 
			
		||||
 arch/sparc/kernel/leon_smp.c       |    8 ++++++-
 | 
			
		||||
 5 files changed, 21 insertions(+), 32 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/include/asm/leon.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/leon.h
 | 
			
		||||
@@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_SMP
 | 
			
		||||
 # define LEON3_IRQ_RESCHEDULE		13
 | 
			
		||||
-# define LEON3_IRQ_TICKER		(leon_percpu_timer_dev[0].irq)
 | 
			
		||||
+# define LEON3_IRQ_TICKER		(leon3_gptimer_irq + leon3_gptimer_idx)
 | 
			
		||||
 # define LEON3_IRQ_CROSS_CALL		15
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/sparc/include/asm/leon_amba.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/leon_amba.h
 | 
			
		||||
@@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp,
 | 
			
		||||
 
 | 
			
		||||
 extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
 | 
			
		||||
 extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
 | 
			
		||||
-extern struct amba_apb_device leon_percpu_timer_dev[16];
 | 
			
		||||
 extern int leondebug_irq_disable;
 | 
			
		||||
 extern int leon_debug_irqout;
 | 
			
		||||
 extern unsigned long leon3_gptimer_irq;
 | 
			
		||||
+extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */
 | 
			
		||||
 extern unsigned int sparc_leon_eirq;
 | 
			
		||||
+extern unsigned long leon3_cpu_idx;
 | 
			
		||||
 
 | 
			
		||||
 #endif /* __ASSEMBLY__ */
 | 
			
		||||
 
 | 
			
		||||
--- a/arch/sparc/kernel/entry.S
 | 
			
		||||
+++ b/arch/sparc/kernel/entry.S
 | 
			
		||||
@@ -411,8 +411,9 @@ smpleon_ticker:
 | 
			
		||||
 	WRITE_PAUSE
 | 
			
		||||
 	wr	%g2, PSR_ET, %psr
 | 
			
		||||
 	WRITE_PAUSE
 | 
			
		||||
+	mov	%l7, %o0		! irq level
 | 
			
		||||
 	call	leon_percpu_timer_interrupt
 | 
			
		||||
-	 add	%sp, STACKFRAME_SZ, %o0
 | 
			
		||||
+	 add	%sp, STACKFRAME_SZ, %o1 ! pt_regs
 | 
			
		||||
 	wr	%l0, PSR_ET, %psr
 | 
			
		||||
 	WRITE_PAUSE
 | 
			
		||||
 	RESTORE_ALL
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -25,7 +25,6 @@
 | 
			
		||||
 
 | 
			
		||||
 struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */
 | 
			
		||||
 struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */
 | 
			
		||||
-struct amba_apb_device leon_percpu_timer_dev[16];
 | 
			
		||||
 
 | 
			
		||||
 int leondebug_irq_disable;
 | 
			
		||||
 int leon_debug_irqout;
 | 
			
		||||
@@ -34,6 +33,7 @@ static int dummy_master_l10_counter;
 | 
			
		||||
 unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */
 | 
			
		||||
 unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */
 | 
			
		||||
 unsigned int sparc_leon_eirq;
 | 
			
		||||
+unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */
 | 
			
		||||
 #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
 | 
			
		||||
 
 | 
			
		||||
 /* Return the IRQ of the pending IRQ on the extended IRQ controller */
 | 
			
		||||
@@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	struct device_node *rootnp, *np;
 | 
			
		||||
 	struct property *pp;
 | 
			
		||||
 	int len;
 | 
			
		||||
-	int cpu, icsel;
 | 
			
		||||
+	int icsel;
 | 
			
		||||
 	int ampopts;
 | 
			
		||||
 
 | 
			
		||||
 	leondebug_irq_disable = 0;
 | 
			
		||||
 	leon_debug_irqout = 0;
 | 
			
		||||
 	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
 | 
			
		||||
 	dummy_master_l10_counter = 0;
 | 
			
		||||
+	leon3_cpu_idx = sparc_leon3_cpuid();
 | 
			
		||||
 
 | 
			
		||||
 	/* Find IRQMP IRQ Controller Registers base address otherwise bail out. */
 | 
			
		||||
 	rootnp = of_find_node_by_path("/ambapp0");
 | 
			
		||||
@@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 				      (((1000000 / HZ) - 1)));
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
 | 
			
		||||
 
 | 
			
		||||
-#ifdef CONFIG_SMP
 | 
			
		||||
-		leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
 | 
			
		||||
-		leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx;
 | 
			
		||||
-
 | 
			
		||||
 		if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
 | 
			
		||||
 		      (1<<LEON3_GPTIMER_SEPIRQ))) {
 | 
			
		||||
-			prom_printf("irq timer not configured with separate irqs\n");
 | 
			
		||||
-			BUG();
 | 
			
		||||
+			prom_printf("LEON-SMP: GPTIMER use shared irqs, using other timers will fail.\n");
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1)));
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
 | 
			
		||||
-# endif
 | 
			
		||||
-
 | 
			
		||||
 		/* The IRQ controller may (if implemented) consist of multiple
 | 
			
		||||
 		 * IRQ controllers, each mapped on a 4Kb boundary.
 | 
			
		||||
 		 * Each CPU may be routed to different IRQCTRLs, however
 | 
			
		||||
@@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 		 * accessed anyway.
 | 
			
		||||
 		 * In AMP systems, Linux may not be run on CPU0.
 | 
			
		||||
 		 */
 | 
			
		||||
-		cpu = sparc_leon3_cpuid();
 | 
			
		||||
-		icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
 | 
			
		||||
-		icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
 | 
			
		||||
+		icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]);
 | 
			
		||||
+		icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf;
 | 
			
		||||
 		leon3_irqctrl_regs += icsel;
 | 
			
		||||
 
 | 
			
		||||
 		LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
 | 
			
		||||
@@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 # ifdef CONFIG_SMP
 | 
			
		||||
 	{
 | 
			
		||||
 		unsigned long flags;
 | 
			
		||||
-		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)];
 | 
			
		||||
+		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + 
 | 
			
		||||
+						(leon3_gptimer_irq + leon3_gptimer_idx - 1)];
 | 
			
		||||
 
 | 
			
		||||
 		/* For SMP we use the level 14 ticker, however the bootup code
 | 
			
		||||
 		 * has copied the firmwares level 14 vector into boot cpu's
 | 
			
		||||
@@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 	}
 | 
			
		||||
 # endif
 | 
			
		||||
 
 | 
			
		||||
-	if (leon3_gptimer_regs) {
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
 | 
			
		||||
+	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
 | 
			
		||||
 				      LEON3_GPTIMER_EN |
 | 
			
		||||
 				      LEON3_GPTIMER_RL |
 | 
			
		||||
 				      LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
 | 
			
		||||
 
 | 
			
		||||
-#ifdef CONFIG_SMP
 | 
			
		||||
-		LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
 | 
			
		||||
-				      LEON3_GPTIMER_EN |
 | 
			
		||||
-				      LEON3_GPTIMER_RL |
 | 
			
		||||
-				      LEON3_GPTIMER_LD |
 | 
			
		||||
-				      LEON3_GPTIMER_IRQEN);
 | 
			
		||||
-#endif
 | 
			
		||||
-
 | 
			
		||||
-	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void leon_clear_clock_irq(void)
 | 
			
		||||
--- a/arch/sparc/kernel/leon_smp.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_smp.c
 | 
			
		||||
@@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin
 | 
			
		||||
 extern unsigned char boot_cpu_id;
 | 
			
		||||
 extern cpumask_t smp_commenced_mask;
 | 
			
		||||
 void __init leon_configure_cache_smp(void);
 | 
			
		||||
+extern void handler_irq(int irq, struct pt_regs * regs);
 | 
			
		||||
 
 | 
			
		||||
 static inline unsigned long do_swap(volatile unsigned long *ptr,
 | 
			
		||||
 				    unsigned long val)
 | 
			
		||||
@@ -385,7 +386,7 @@ void leon_cross_call_irq(void)
 | 
			
		||||
 	ccall_info.processors_out[i] = 1;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-void leon_percpu_timer_interrupt(struct pt_regs *regs)
 | 
			
		||||
+void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs)
 | 
			
		||||
 {
 | 
			
		||||
 	struct pt_regs *old_regs;
 | 
			
		||||
 	int cpu = smp_processor_id();
 | 
			
		||||
@@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct
 | 
			
		||||
 		prof_counter(cpu) = prof_multiplier(cpu);
 | 
			
		||||
 	}
 | 
			
		||||
 	set_irq_regs(old_regs);
 | 
			
		||||
+
 | 
			
		||||
+	if ( cpu == leon3_cpu_idx ) {
 | 
			
		||||
+		/* Ticker Clock is shared with the System Clock */
 | 
			
		||||
+		handler_irq(irq, regs);
 | 
			
		||||
+	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void __init smp_setup_percpu_timer(void)
 | 
			
		||||
							
								
								
									
										41
									
								
								target/linux/leon/patches/010-apbuart_ampopts.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								target/linux/leon/patches/010-apbuart_ampopts.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
From 8129fa5437f3fe5f95bac180a43cd5a856cebdf3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 20 Oct 2010 17:00:41 +0200
 | 
			
		||||
Subject: [PATCH] Added support for ampopts in APBUART driver. Used in AMP systems.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/serial/apbuart.c |    5 ++++-
 | 
			
		||||
 1 files changed, 4 insertions(+), 1 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/serial/apbuart.c
 | 
			
		||||
+++ b/drivers/serial/apbuart.c
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
 #include <linux/of.h>
 | 
			
		||||
 #include <linux/of_device.h>
 | 
			
		||||
 #include <linux/of_platform.h>
 | 
			
		||||
+#include <linux/of_irq.h>
 | 
			
		||||
 #include <linux/platform_device.h>
 | 
			
		||||
 #include <linux/io.h>
 | 
			
		||||
 #include <linux/serial_core.h>
 | 
			
		||||
@@ -573,7 +574,6 @@ static int __devinit apbuart_probe(struc
 | 
			
		||||
 	printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
 | 
			
		||||
 	       (unsigned long long) port->mapbase, port->irq);
 | 
			
		||||
 	return 0;
 | 
			
		||||
-
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static struct of_device_id __initdata apbuart_match[] = {
 | 
			
		||||
@@ -620,9 +620,12 @@ static void grlib_apbuart_configure(void
 | 
			
		||||
 		int *vendor = (int *) of_get_property(np, "vendor", NULL);
 | 
			
		||||
 		int *device = (int *) of_get_property(np, "device", NULL);
 | 
			
		||||
 		int *irqs = (int *) of_get_property(np, "interrupts", NULL);
 | 
			
		||||
+		int *ampopts = (int *) of_get_property(np, "ampopts", NULL);
 | 
			
		||||
 		regs = (struct amba_prom_registers *)
 | 
			
		||||
 		    of_get_property(np, "reg", NULL);
 | 
			
		||||
 
 | 
			
		||||
+		if (ampopts && (*ampopts == 0))
 | 
			
		||||
+			continue; /* Ignore if used by another OS instance */
 | 
			
		||||
 		if (vendor)
 | 
			
		||||
 			v = *vendor;
 | 
			
		||||
 		if (device)
 | 
			
		||||
							
								
								
									
										21
									
								
								target/linux/leon/patches/011-greth_fix_unhandled_irq.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								target/linux/leon/patches/011-greth_fix_unhandled_irq.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
From 3d7788e8f5ae3d44e48f9b7476528acf3d9c8b32 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 20 Oct 2010 17:07:12 +0200
 | 
			
		||||
Subject: [PATCH] GRETH: Fixed potential future problem where unhandled IRQ is cleared.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    2 +-
 | 
			
		||||
 1 files changed, 1 insertions(+), 1 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -584,7 +584,7 @@ static irqreturn_t greth_interrupt(int i
 | 
			
		||||
 	if (status & (GRETH_INT_RX | GRETH_INT_TX)) {
 | 
			
		||||
 
 | 
			
		||||
 		/* Clear interrupt status */
 | 
			
		||||
-		GRETH_REGORIN(greth->regs->status,
 | 
			
		||||
+		GRETH_REGSAVE(greth->regs->status,
 | 
			
		||||
 			      status & (GRETH_INT_RX | GRETH_INT_TX));
 | 
			
		||||
 
 | 
			
		||||
 		retval = IRQ_HANDLED;
 | 
			
		||||
							
								
								
									
										22
									
								
								target/linux/leon/patches/012-greth_amba_vendor_device.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								target/linux/leon/patches/012-greth_amba_vendor_device.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
From ff5f2ee8b37f2278dd86946761313c3664c51836 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Thu, 21 Oct 2010 14:34:48 +0200
 | 
			
		||||
Subject: [PATCH] GRETH: added raw AMBA vendor/device number to match against.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    3 +++
 | 
			
		||||
 1 files changed, 3 insertions(+), 0 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -1600,6 +1600,9 @@ static struct of_device_id greth_of_matc
 | 
			
		||||
 	{
 | 
			
		||||
 	 .name = "GAISLER_ETHMAC",
 | 
			
		||||
 	 },
 | 
			
		||||
+	{
 | 
			
		||||
+	 .name = "01_01d",
 | 
			
		||||
+	 },
 | 
			
		||||
 	{},
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
From 1c14b8995c1b8212180b5009dc04ac222a449ecb Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Thu, 21 Oct 2010 14:35:09 +0200
 | 
			
		||||
Subject: [PATCH] APBUART: added raw AMBA vendor/device number to match against.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/serial/apbuart.c |    3 +++
 | 
			
		||||
 1 files changed, 3 insertions(+), 0 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/serial/apbuart.c
 | 
			
		||||
+++ b/drivers/serial/apbuart.c
 | 
			
		||||
@@ -580,6 +580,9 @@ static struct of_device_id __initdata ap
 | 
			
		||||
 	{
 | 
			
		||||
 	 .name = "GAISLER_APBUART",
 | 
			
		||||
 	 },
 | 
			
		||||
+	{
 | 
			
		||||
+	 .name = "01_00c",
 | 
			
		||||
+	 },
 | 
			
		||||
 	{},
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
From 12782c44d0c687b5b0400a8224a9b1bf9eb9a428 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Tue, 26 Oct 2010 09:59:05 +0200
 | 
			
		||||
Subject: [PATCH] TIMER,IRQCTRL: added raw AMBA vendor/device number to match against.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/leon_kernel.c |    6 ++++--
 | 
			
		||||
 1 files changed, 4 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
+++ b/arch/sparc/kernel/leon_kernel.c
 | 
			
		||||
@@ -120,7 +120,8 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 
 | 
			
		||||
 	/* Find IRQMP IRQ Controller Registers base address otherwise bail out. */
 | 
			
		||||
 	rootnp = of_find_node_by_path("/ambapp0");
 | 
			
		||||
-	if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) {
 | 
			
		||||
+	if (rootnp && ((np=of_find_node_by_name(rootnp, "GAISLER_IRQMP")) ||
 | 
			
		||||
+			(np=of_find_node_by_name(rootnp, "01_00d")))) {
 | 
			
		||||
 		pp = of_find_property(np, "reg", &len);
 | 
			
		||||
 		if (pp)
 | 
			
		||||
 			leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
 | 
			
		||||
@@ -128,7 +129,8 @@ void __init leon_init_timers(irq_handler
 | 
			
		||||
 
 | 
			
		||||
 	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 | 
			
		||||
 	np = rootnp;
 | 
			
		||||
-	while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) {
 | 
			
		||||
+	while (np && ((np=of_find_node_by_name(np, "GAISLER_GPTIMER")) ||
 | 
			
		||||
+			(np=of_find_node_by_name(np, "01_011")))) {
 | 
			
		||||
 		ampopts = 0;
 | 
			
		||||
 		pp = of_find_property(np, "ampopts", &len);
 | 
			
		||||
 		if ( pp && ((ampopts = *(int *)pp->value) == 0) ) {
 | 
			
		||||
							
								
								
									
										296
									
								
								target/linux/leon/patches/015-dma_ops.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								target/linux/leon/patches/015-dma_ops.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,296 @@
 | 
			
		||||
From c6d8f92cfd7f4f19eb3b16545b3b68c561978fe8 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Kristoffer Glembo <kristoffer@gaisler.com>
 | 
			
		||||
Date: Mon, 7 Jun 2010 14:00:30 +0200
 | 
			
		||||
Subject: [PATCH] sparc32: Added LEON dma_ops.
 | 
			
		||||
 | 
			
		||||
Added leon3_dma_ops and mmu_inval_dma_area.
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/kernel/ioport.c |  139 +++++++++++++++++++++++++++++++------------
 | 
			
		||||
 1 files changed, 100 insertions(+), 39 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/kernel/ioport.c
 | 
			
		||||
+++ b/arch/sparc/kernel/ioport.c
 | 
			
		||||
@@ -50,10 +50,15 @@
 | 
			
		||||
 #include <asm/io-unit.h>
 | 
			
		||||
 #include <asm/leon.h>
 | 
			
		||||
 
 | 
			
		||||
-#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
-#define mmu_inval_dma_area(p, l) leon_flush_dcache_all()
 | 
			
		||||
-#else
 | 
			
		||||
+#ifndef CONFIG_SPARC_LEON
 | 
			
		||||
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
 | 
			
		||||
+#else
 | 
			
		||||
+static inline void mmu_inval_dma_area(unsigned long va, unsigned long len)
 | 
			
		||||
+{
 | 
			
		||||
+	if (!sparc_leon3_snooping_enabled()) {
 | 
			
		||||
+		leon_flush_dcache_all();
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 static struct resource *_sparc_find_resource(struct resource *r,
 | 
			
		||||
@@ -254,7 +259,7 @@ static void *sbus_alloc_coherent(struct
 | 
			
		||||
 				 dma_addr_t *dma_addrp, gfp_t gfp)
 | 
			
		||||
 {
 | 
			
		||||
 	struct platform_device *op = to_platform_device(dev);
 | 
			
		||||
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
 | 
			
		||||
+	unsigned long len_total = PAGE_ALIGN(len);
 | 
			
		||||
 	unsigned long va;
 | 
			
		||||
 	struct resource *res;
 | 
			
		||||
 	int order;
 | 
			
		||||
@@ -287,15 +292,19 @@ static void *sbus_alloc_coherent(struct
 | 
			
		||||
 	 * XXX That's where sdev would be used. Currently we load
 | 
			
		||||
 	 * all iommu tables with the same translations.
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
 | 
			
		||||
-		goto err_noiommu;
 | 
			
		||||
-
 | 
			
		||||
-	res->name = op->dev.of_node->name;
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);	
 | 
			
		||||
+	*dma_addrp = virt_to_phys(va);
 | 
			
		||||
+#else
 | 
			
		||||
+	if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) {
 | 
			
		||||
+		release_resource(res);
 | 
			
		||||
+		goto err_nova;
 | 
			
		||||
+	}
 | 
			
		||||
+#endif
 | 
			
		||||
+	res->name = op->node->name;
 | 
			
		||||
 
 | 
			
		||||
 	return (void *)(unsigned long)res->start;
 | 
			
		||||
 
 | 
			
		||||
-err_noiommu:
 | 
			
		||||
-	release_resource(res);
 | 
			
		||||
 err_nova:
 | 
			
		||||
 	free_pages(va, order);
 | 
			
		||||
 err_nomem:
 | 
			
		||||
@@ -321,7 +330,7 @@ static void sbus_free_coherent(struct de
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
 | 
			
		||||
+	n = PAGE_ALIGN(n);
 | 
			
		||||
 	if ((res->end-res->start)+1 != n) {
 | 
			
		||||
 		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
 | 
			
		||||
 		    (long)((res->end-res->start)+1), n);
 | 
			
		||||
@@ -333,7 +342,12 @@ static void sbus_free_coherent(struct de
 | 
			
		||||
 
 | 
			
		||||
 	/* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */
 | 
			
		||||
 	pgv = virt_to_page(p);
 | 
			
		||||
-	mmu_unmap_dma_area(dev, ba, n);
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+	sparc_unmapiorange((unsigned long)p, n);
 | 
			
		||||
+#else
 | 
			
		||||
+ 	mmu_unmap_dma_area(dev, ba, n);
 | 
			
		||||
+#endif
 | 
			
		||||
 
 | 
			
		||||
 	__free_pages(pgv, get_order(n));
 | 
			
		||||
 }
 | 
			
		||||
@@ -408,9 +422,6 @@ struct dma_map_ops sbus_dma_ops = {
 | 
			
		||||
 	.sync_sg_for_device	= sbus_sync_sg_for_device,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
-struct dma_map_ops *dma_ops = &sbus_dma_ops;
 | 
			
		||||
-EXPORT_SYMBOL(dma_ops);
 | 
			
		||||
-
 | 
			
		||||
 static int __init sparc_register_ioport(void)
 | 
			
		||||
 {
 | 
			
		||||
 	register_proc_sparc_ioport();
 | 
			
		||||
@@ -422,7 +433,7 @@ arch_initcall(sparc_register_ioport);
 | 
			
		||||
 
 | 
			
		||||
 #endif /* CONFIG_SBUS */
 | 
			
		||||
 
 | 
			
		||||
-#ifdef CONFIG_PCI
 | 
			
		||||
+#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON)
 | 
			
		||||
 
 | 
			
		||||
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
 | 
			
		||||
  * hwdev should be valid struct pci_dev pointer for PCI devices.
 | 
			
		||||
@@ -430,7 +441,7 @@ arch_initcall(sparc_register_ioport);
 | 
			
		||||
 static void *pci32_alloc_coherent(struct device *dev, size_t len,
 | 
			
		||||
 				  dma_addr_t *pba, gfp_t gfp)
 | 
			
		||||
 {
 | 
			
		||||
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
 | 
			
		||||
+	unsigned long len_total = PAGE_ALIGN(len);
 | 
			
		||||
 	unsigned long va;
 | 
			
		||||
 	struct resource *res;
 | 
			
		||||
 	int order;
 | 
			
		||||
@@ -463,10 +474,6 @@ static void *pci32_alloc_coherent(struct
 | 
			
		||||
 		return NULL;
 | 
			
		||||
 	}
 | 
			
		||||
 	mmu_inval_dma_area(va, len_total);
 | 
			
		||||
-#if 0
 | 
			
		||||
-/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n",
 | 
			
		||||
-  (long)va, (long)res->start, (long)virt_to_phys(va), len_total);
 | 
			
		||||
-#endif
 | 
			
		||||
 	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
 | 
			
		||||
 
 | 
			
		||||
 	*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
 | 
			
		||||
@@ -498,7 +505,7 @@ static void pci32_free_coherent(struct d
 | 
			
		||||
 		return;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
 | 
			
		||||
+	n = PAGE_ALIGN(n);
 | 
			
		||||
 	if ((res->end-res->start)+1 != n) {
 | 
			
		||||
 		printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
 | 
			
		||||
 		    (long)((res->end-res->start)+1), (long)n);
 | 
			
		||||
@@ -515,6 +522,14 @@ static void pci32_free_coherent(struct d
 | 
			
		||||
 	free_pages(pgp, get_order(n));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
 | 
			
		||||
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
 | 
			
		||||
+{
 | 
			
		||||
+	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
+		mmu_inval_dma_area((unsigned long)phys_to_virt(ba), PAGE_ALIGN(size));
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /*
 | 
			
		||||
  * Same as pci_map_single, but with pages.
 | 
			
		||||
  */
 | 
			
		||||
@@ -551,8 +566,7 @@ static int pci32_map_sg(struct device *d
 | 
			
		||||
 
 | 
			
		||||
 	/* IIep is write-through, not flushing. */
 | 
			
		||||
 	for_each_sg(sgl, sg, nents, n) {
 | 
			
		||||
-		BUG_ON(page_address(sg_page(sg)) == NULL);
 | 
			
		||||
-		sg->dma_address = virt_to_phys(sg_virt(sg));
 | 
			
		||||
+		sg->dma_address = sg_phys(sg);
 | 
			
		||||
 		sg->dma_length = sg->length;
 | 
			
		||||
 	}
 | 
			
		||||
 	return nents;
 | 
			
		||||
@@ -571,10 +585,7 @@ static void pci32_unmap_sg(struct device
 | 
			
		||||
 
 | 
			
		||||
 	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
 		for_each_sg(sgl, sg, nents, n) {
 | 
			
		||||
-			BUG_ON(page_address(sg_page(sg)) == NULL);
 | 
			
		||||
-			mmu_inval_dma_area(
 | 
			
		||||
-			    (unsigned long) page_address(sg_page(sg)),
 | 
			
		||||
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
 | 
			
		||||
+			mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length));
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -594,7 +605,7 @@ static void pci32_sync_single_for_cpu(st
 | 
			
		||||
 {
 | 
			
		||||
 	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
 		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
 | 
			
		||||
-		    (size + PAGE_SIZE-1) & PAGE_MASK);
 | 
			
		||||
+				   PAGE_ALIGN(size));
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -621,10 +632,7 @@ static void pci32_sync_sg_for_cpu(struct
 | 
			
		||||
 
 | 
			
		||||
 	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
 		for_each_sg(sgl, sg, nents, n) {
 | 
			
		||||
-			BUG_ON(page_address(sg_page(sg)) == NULL);
 | 
			
		||||
-			mmu_inval_dma_area(
 | 
			
		||||
-			    (unsigned long) page_address(sg_page(sg)),
 | 
			
		||||
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
 | 
			
		||||
+			mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length));
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -637,18 +645,38 @@ static void pci32_sync_sg_for_device(str
 | 
			
		||||
 
 | 
			
		||||
 	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
 		for_each_sg(sgl, sg, nents, n) {
 | 
			
		||||
-			BUG_ON(page_address(sg_page(sg)) == NULL);
 | 
			
		||||
-			mmu_inval_dma_area(
 | 
			
		||||
-			    (unsigned long) page_address(sg_page(sg)),
 | 
			
		||||
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
 | 
			
		||||
+			mmu_inval_dma_area((unsigned long)sg_virt(sg),  PAGE_ALIGN(sg->length));
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/* LEON3 unmapping functions 
 | 
			
		||||
+ * 
 | 
			
		||||
+ * We can only invalidate the whole cache so unmap_page and unmap_sg do the same thing
 | 
			
		||||
+ */
 | 
			
		||||
+static void leon3_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
 | 
			
		||||
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
 | 
			
		||||
+{
 | 
			
		||||
+	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
+		mmu_inval_dma_area(0, 0);
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void leon3_unmap_sg(struct device *dev, struct scatterlist *sgl,
 | 
			
		||||
+			   int nents, enum dma_data_direction dir,
 | 
			
		||||
+			   struct dma_attrs *attrs)
 | 
			
		||||
+{
 | 
			
		||||
+
 | 
			
		||||
+	if (dir != PCI_DMA_TODEVICE) {
 | 
			
		||||
+		mmu_inval_dma_area(0, 0);
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 struct dma_map_ops pci32_dma_ops = {
 | 
			
		||||
 	.alloc_coherent		= pci32_alloc_coherent,
 | 
			
		||||
 	.free_coherent		= pci32_free_coherent,
 | 
			
		||||
 	.map_page		= pci32_map_page,
 | 
			
		||||
+	.unmap_page		= pci32_unmap_page,
 | 
			
		||||
 	.map_sg			= pci32_map_sg,
 | 
			
		||||
 	.unmap_sg		= pci32_unmap_sg,
 | 
			
		||||
 	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
 | 
			
		||||
@@ -658,7 +686,30 @@ struct dma_map_ops pci32_dma_ops = {
 | 
			
		||||
 };
 | 
			
		||||
 EXPORT_SYMBOL(pci32_dma_ops);
 | 
			
		||||
 
 | 
			
		||||
-#endif /* CONFIG_PCI */
 | 
			
		||||
+struct dma_map_ops leon3_dma_ops = {
 | 
			
		||||
+	.alloc_coherent		= sbus_alloc_coherent,
 | 
			
		||||
+	.free_coherent		= sbus_free_coherent,
 | 
			
		||||
+	.map_page		= pci32_map_page,
 | 
			
		||||
+	.unmap_page		= leon3_unmap_page,
 | 
			
		||||
+	.map_sg			= pci32_map_sg,
 | 
			
		||||
+	.unmap_sg		= leon3_unmap_sg,
 | 
			
		||||
+	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
 | 
			
		||||
+	.sync_single_for_device	= pci32_sync_single_for_device,
 | 
			
		||||
+	.sync_sg_for_cpu	= pci32_sync_sg_for_cpu,
 | 
			
		||||
+	.sync_sg_for_device	= pci32_sync_sg_for_device,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_SPARC_LEON
 | 
			
		||||
+struct dma_map_ops *dma_ops = &leon3_dma_ops;
 | 
			
		||||
+#else
 | 
			
		||||
+struct dma_map_ops *dma_ops = &sbus_dma_ops;
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
+#ifdef CONFIG_SBUS
 | 
			
		||||
+EXPORT_SYMBOL(dma_ops);
 | 
			
		||||
+#endif
 | 
			
		||||
 
 | 
			
		||||
 /*
 | 
			
		||||
  * Return whether the given PCI device DMA address mask can be
 | 
			
		||||
@@ -676,6 +727,16 @@ int dma_supported(struct device *dev, u6
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(dma_supported);
 | 
			
		||||
 
 | 
			
		||||
+int dma_set_mask(struct device *dev, u64 dma_mask)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef CONFIG_PCI
 | 
			
		||||
+	if (dev->bus == &pci_bus_type)
 | 
			
		||||
+		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
 | 
			
		||||
+#endif
 | 
			
		||||
+	return -EOPNOTSUPP;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(dma_set_mask);
 | 
			
		||||
+
 | 
			
		||||
 #ifdef CONFIG_PROC_FS
 | 
			
		||||
 
 | 
			
		||||
 static int sparc_io_proc_show(struct seq_file *m, void *v)
 | 
			
		||||
@@ -717,7 +778,7 @@ static const struct file_operations spar
 | 
			
		||||
 static struct resource *_sparc_find_resource(struct resource *root,
 | 
			
		||||
 					     unsigned long hit)
 | 
			
		||||
 {
 | 
			
		||||
-        struct resource *tmp;
 | 
			
		||||
+	struct resource *tmp;
 | 
			
		||||
 
 | 
			
		||||
 	for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
 | 
			
		||||
 		if (tmp->start <= hit && tmp->end >= hit)
 | 
			
		||||
							
								
								
									
										51
									
								
								target/linux/leon/patches/016-ioport_update.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								target/linux/leon/patches/016-ioport_update.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
From 36cad96a50eb877d0c5cb3d8d93c1807ad9c774c Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 09:37:23 +0100
 | 
			
		||||
Subject: [PATCH] Fix kristoffers ioport.c patch for more recent kernel.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/sparc/include/asm/dma-mapping.h |   13 +------------
 | 
			
		||||
 arch/sparc/kernel/ioport.c           |    3 ++-
 | 
			
		||||
 2 files changed, 3 insertions(+), 13 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/arch/sparc/include/asm/dma-mapping.h
 | 
			
		||||
+++ b/arch/sparc/include/asm/dma-mapping.h
 | 
			
		||||
@@ -51,17 +51,6 @@ static inline int dma_mapping_error(stru
 | 
			
		||||
 	return (dma_addr == DMA_ERROR_CODE);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static inline int dma_set_mask(struct device *dev, u64 mask)
 | 
			
		||||
-{
 | 
			
		||||
-#ifdef CONFIG_PCI
 | 
			
		||||
-	if (dev->bus == &pci_bus_type) {
 | 
			
		||||
-		if (!dev->dma_mask || !dma_supported(dev, mask))
 | 
			
		||||
-			return -EINVAL;
 | 
			
		||||
-		*dev->dma_mask = mask;
 | 
			
		||||
-		return 0;
 | 
			
		||||
-	}
 | 
			
		||||
-#endif
 | 
			
		||||
-	return -EINVAL;
 | 
			
		||||
-}
 | 
			
		||||
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
 | 
			
		||||
 
 | 
			
		||||
 #endif
 | 
			
		||||
--- a/arch/sparc/kernel/ioport.c
 | 
			
		||||
+++ b/arch/sparc/kernel/ioport.c
 | 
			
		||||
@@ -301,7 +301,7 @@ static void *sbus_alloc_coherent(struct
 | 
			
		||||
 		goto err_nova;
 | 
			
		||||
 	}
 | 
			
		||||
 #endif
 | 
			
		||||
-	res->name = op->node->name;
 | 
			
		||||
+	res->name = op->dev.of_node->name;
 | 
			
		||||
 
 | 
			
		||||
 	return (void *)(unsigned long)res->start;
 | 
			
		||||
 
 | 
			
		||||
@@ -737,6 +737,7 @@ int dma_set_mask(struct device *dev, u64
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(dma_set_mask);
 | 
			
		||||
 
 | 
			
		||||
+
 | 
			
		||||
 #ifdef CONFIG_PROC_FS
 | 
			
		||||
 
 | 
			
		||||
 static int sparc_io_proc_show(struct seq_file *m, void *v)
 | 
			
		||||
							
								
								
									
										66
									
								
								target/linux/leon/patches/017-greth_no_gbit.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								target/linux/leon/patches/017-greth_no_gbit.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
From 2e864d18c31d4e0255269f9e9cfccc09512676c6 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 16:51:38 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: added greth_no_gbit option
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |   15 +++++++++++++--
 | 
			
		||||
 drivers/net/greth.h |    1 +
 | 
			
		||||
 2 files changed, 14 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -66,6 +66,10 @@ static int greth_edcl = 1;
 | 
			
		||||
 module_param(greth_edcl, int, 0);
 | 
			
		||||
 MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used.");
 | 
			
		||||
 
 | 
			
		||||
+static int no_gbit = 0;
 | 
			
		||||
+module_param(no_gbit, int, S_IRUGO);
 | 
			
		||||
+MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off).");
 | 
			
		||||
+
 | 
			
		||||
 static int greth_open(struct net_device *dev);
 | 
			
		||||
 static netdev_tx_t greth_start_xmit(struct sk_buff *skb,
 | 
			
		||||
 	   struct net_device *dev);
 | 
			
		||||
@@ -1284,7 +1288,7 @@ static int greth_mdio_probe(struct net_d
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	ret = phy_connect_direct(dev, phy, &greth_link_change,
 | 
			
		||||
-			0, greth->gbit_mac ?
 | 
			
		||||
+			0, greth->gbit_phy_support ?
 | 
			
		||||
 			PHY_INTERFACE_MODE_GMII :
 | 
			
		||||
 			PHY_INTERFACE_MODE_MII);
 | 
			
		||||
 	if (ret) {
 | 
			
		||||
@@ -1293,7 +1297,7 @@ static int greth_mdio_probe(struct net_d
 | 
			
		||||
 		return ret;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (greth->gbit_mac)
 | 
			
		||||
+	if (greth->gbit_phy_support)
 | 
			
		||||
 		phy->supported &= PHY_GBIT_FEATURES;
 | 
			
		||||
 	else
 | 
			
		||||
 		phy->supported &= PHY_BASIC_FEATURES;
 | 
			
		||||
@@ -1441,6 +1445,13 @@ static int __devinit greth_of_probe(stru
 | 
			
		||||
 	tmp = GRETH_REGLOAD(regs->control);
 | 
			
		||||
 	greth->gbit_mac = (tmp >> 27) & 1;
 | 
			
		||||
 
 | 
			
		||||
+	/* Let user skip GBit link mode by telling MDIO layer that MAC does
 | 
			
		||||
+	 * not support GBIT (for debug) */
 | 
			
		||||
+	if (greth->gbit_mac && !no_gbit)
 | 
			
		||||
+		greth->gbit_phy_support = 1;
 | 
			
		||||
+	else
 | 
			
		||||
+		greth->gbit_phy_support = 0;
 | 
			
		||||
+
 | 
			
		||||
 	/* Check for multicast capability */
 | 
			
		||||
 	greth->multicast = (tmp >> 25) & 1;
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/greth.h
 | 
			
		||||
+++ b/drivers/net/greth.h
 | 
			
		||||
@@ -138,6 +138,7 @@ struct greth_private {
 | 
			
		||||
 	u8 gbit_mac;
 | 
			
		||||
 	u8 mdio_int_en;
 | 
			
		||||
 	u8 edcl;
 | 
			
		||||
+	u8 gbit_phy_support;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 #endif
 | 
			
		||||
							
								
								
									
										41
									
								
								target/linux/leon/patches/018-greth_compat_mode.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								target/linux/leon/patches/018-greth_compat_mode.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
From a498d7076ee0f82ec3f508293a9cf1ccba15829e Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 16:52:19 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: added greth_compat_mode module parameter
 | 
			
		||||
 | 
			
		||||
The greth_compat_mode option can be used to set a GRETH GBit capable MAC
 | 
			
		||||
in operate as if the GRETH 10/100 device was found. The GRETH GBit supports
 | 
			
		||||
TCP/UDP checksum offloading, unaligned frame buffers, scatter gather etc.
 | 
			
		||||
Enabling this mode allows the developer to test the GRETH 10/100 device
 | 
			
		||||
without all features mentioned above on a GBit MAC capable of the above.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    9 +++++++++
 | 
			
		||||
 1 files changed, 9 insertions(+), 0 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -70,6 +70,11 @@ static int no_gbit = 0;
 | 
			
		||||
 module_param(no_gbit, int, S_IRUGO);
 | 
			
		||||
 MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off).");
 | 
			
		||||
 
 | 
			
		||||
+/* Use this option to enable GRETH 10/100 code on GRETH_GBIT hardware (debug legacy code option) */
 | 
			
		||||
+static int compat_mode = 0;
 | 
			
		||||
+module_param(compat_mode, int, S_IRUGO);
 | 
			
		||||
+MODULE_PARM_DESC(compat_mode, "GRETH 10/100 legacy mode enable. Only affects GRETH GBit MAC, default 0 (off).");
 | 
			
		||||
+
 | 
			
		||||
 static int greth_open(struct net_device *dev);
 | 
			
		||||
 static netdev_tx_t greth_start_xmit(struct sk_buff *skb,
 | 
			
		||||
 	   struct net_device *dev);
 | 
			
		||||
@@ -1452,6 +1457,10 @@ static int __devinit greth_of_probe(stru
 | 
			
		||||
 	else
 | 
			
		||||
 		greth->gbit_phy_support = 0;
 | 
			
		||||
 
 | 
			
		||||
+	/* Force GBit MAC in legacy 10/100 mode (no offloading etc.) */
 | 
			
		||||
+	if (compat_mode == 1)
 | 
			
		||||
+		greth->gbit_mac = 0;
 | 
			
		||||
+
 | 
			
		||||
 	/* Check for multicast capability */
 | 
			
		||||
 	greth->multicast = (tmp >> 25) & 1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								target/linux/leon/patches/019-greth_fix_open_close.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								target/linux/leon/patches/019-greth_fix_open_close.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
From 6216bc809c5bdd586b14d096fbaf6dc25574b928 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 09:59:14 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: fix opening/closing
 | 
			
		||||
 | 
			
		||||
When NAPI is disabled there is no point in having IRQs enabled, TX/RX
 | 
			
		||||
should be off before clearing the TX/RX descriptor rings.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    4 ++++
 | 
			
		||||
 1 files changed, 4 insertions(+), 0 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -365,6 +365,8 @@ static int greth_open(struct net_device
 | 
			
		||||
 		dev_dbg(&dev->dev, " starting queue\n");
 | 
			
		||||
 	netif_start_queue(dev);
 | 
			
		||||
 
 | 
			
		||||
+	GRETH_REGSAVE(greth->regs->status, 0xFF);
 | 
			
		||||
+
 | 
			
		||||
 	napi_enable(&greth->napi);
 | 
			
		||||
 
 | 
			
		||||
 	greth_enable_irqs(greth);
 | 
			
		||||
@@ -380,7 +382,9 @@ static int greth_close(struct net_device
 | 
			
		||||
 
 | 
			
		||||
 	napi_disable(&greth->napi);
 | 
			
		||||
 
 | 
			
		||||
+	greth_disable_irqs(greth);
 | 
			
		||||
 	greth_disable_tx(greth);
 | 
			
		||||
+	greth_disable_rx(greth);
 | 
			
		||||
 
 | 
			
		||||
 	netif_stop_queue(dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
From 544631281bed5cc37b8f2d3a99f44c9d4b97f9a8 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 10:07:12 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: GBit transmit descriptor handling optimization
 | 
			
		||||
 | 
			
		||||
It is safe to enable all fragments before enabling the first descriptor,
 | 
			
		||||
this way all descriptors don't have to be processed twice, added extra
 | 
			
		||||
memory barrier.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |   19 ++++++++++---------
 | 
			
		||||
 1 files changed, 10 insertions(+), 9 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -512,7 +512,7 @@ greth_start_xmit_gbit(struct sk_buff *sk
 | 
			
		||||
 		greth->tx_skbuff[curr_tx] = NULL;
 | 
			
		||||
 		bdp = greth->tx_bd_base + curr_tx;
 | 
			
		||||
 
 | 
			
		||||
-		status = GRETH_TXBD_CSALL;
 | 
			
		||||
+		status = GRETH_TXBD_CSALL | GRETH_BD_EN;
 | 
			
		||||
 		status |= frag->size & GRETH_BD_LEN;
 | 
			
		||||
 
 | 
			
		||||
 		/* Wrap around descriptor ring */
 | 
			
		||||
@@ -549,26 +549,27 @@ greth_start_xmit_gbit(struct sk_buff *sk
 | 
			
		||||
 
 | 
			
		||||
 	wmb();
 | 
			
		||||
 
 | 
			
		||||
-	/* Enable the descriptors that we configured ...  */
 | 
			
		||||
-	for (i = 0; i < nr_frags + 1; i++) {
 | 
			
		||||
-		bdp = greth->tx_bd_base + greth->tx_next;
 | 
			
		||||
-		greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
 | 
			
		||||
-		greth->tx_next = NEXT_TX(greth->tx_next);
 | 
			
		||||
-		greth->tx_free--;
 | 
			
		||||
-	}
 | 
			
		||||
+	/* Enable the descriptor chain by enabling the first descriptor */
 | 
			
		||||
+	bdp = greth->tx_bd_base + greth->tx_next;
 | 
			
		||||
+	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
 | 
			
		||||
+	greth->tx_next = curr_tx;
 | 
			
		||||
+	greth->tx_free -= nr_frags + 1;
 | 
			
		||||
+
 | 
			
		||||
+	wmb();
 | 
			
		||||
 
 | 
			
		||||
 	greth_enable_tx(greth);
 | 
			
		||||
 
 | 
			
		||||
 	return NETDEV_TX_OK;
 | 
			
		||||
 
 | 
			
		||||
 frag_map_error:
 | 
			
		||||
-	/* Unmap SKB mappings that succeeded */
 | 
			
		||||
+	/* Unmap SKB mappings that succeeded and disable descriptor */
 | 
			
		||||
 	for (i = 0; greth->tx_next + i != curr_tx; i++) {
 | 
			
		||||
 		bdp = greth->tx_bd_base + greth->tx_next + i;
 | 
			
		||||
 		dma_unmap_single(greth->dev,
 | 
			
		||||
 				 greth_read_bd(&bdp->addr),
 | 
			
		||||
 				 greth_read_bd(&bdp->stat) & GRETH_BD_LEN,
 | 
			
		||||
 				 DMA_TO_DEVICE);
 | 
			
		||||
+		greth_write_bd(&bdp->stat, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 map_error:
 | 
			
		||||
 	if (net_ratelimit())
 | 
			
		||||
							
								
								
									
										49
									
								
								target/linux/leon/patches/021-greth_fix_memory_leak.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								target/linux/leon/patches/021-greth_fix_memory_leak.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
From 54789a03adf9c924d0cf7b890323c9c1ca7ab042 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 10:26:09 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: fixed skb buffer memory leak on frame errors
 | 
			
		||||
 | 
			
		||||
A new SKB buffer should not be allocated when the old SKB is reused.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |   17 +++++++++++------
 | 
			
		||||
 1 files changed, 11 insertions(+), 6 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -879,10 +879,8 @@ static int greth_rx_gbit(struct net_devi
 | 
			
		||||
 			}
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		/* Allocate new skb to replace current */
 | 
			
		||||
-		newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN);
 | 
			
		||||
-
 | 
			
		||||
-		if (!bad && newskb) {
 | 
			
		||||
+		/* Allocate new skb to replace current, not needed if the current skb can be reused */
 | 
			
		||||
+		if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) {
 | 
			
		||||
 			skb_reserve(newskb, NET_IP_ALIGN);
 | 
			
		||||
 
 | 
			
		||||
 			dma_addr = dma_map_single(greth->dev,
 | 
			
		||||
@@ -919,12 +917,19 @@ static int greth_rx_gbit(struct net_devi
 | 
			
		||||
 				if (net_ratelimit())
 | 
			
		||||
 					dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n");
 | 
			
		||||
 				dev_kfree_skb(newskb);
 | 
			
		||||
-				dev->stats.rx_dropped++;
 | 
			
		||||
+				dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */
 | 
			
		||||
 			}
 | 
			
		||||
+		} else if ( bad ) {
 | 
			
		||||
+			/* Bad Frame transfer, the skb is reused */
 | 
			
		||||
+			dev->stats.rx_dropped++;
 | 
			
		||||
 		} else {
 | 
			
		||||
+			/* Failed Allocating a new skb. This is rather stupid but the current "filled" 
 | 
			
		||||
+			 * skb is reused, as if transfer failure. One could argue that RX descriptor table
 | 
			
		||||
+			 * handling should be divided into cleaning and filling as the TX part of the driver
 | 
			
		||||
+			 */
 | 
			
		||||
 			if (net_ratelimit())
 | 
			
		||||
 				dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n");
 | 
			
		||||
-			dev->stats.rx_dropped++;
 | 
			
		||||
+			dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		status = GRETH_BD_EN | GRETH_BD_IE;
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
From c2e963057ca5635d6e5387623c3ad0c0b3123754 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 10:28:37 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: avoid writing bad speed/duplex when setting transfer mode
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |   19 ++++++++-----------
 | 
			
		||||
 1 files changed, 8 insertions(+), 11 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -1236,29 +1236,26 @@ static void greth_link_change(struct net
 | 
			
		||||
 	struct greth_private *greth = netdev_priv(dev);
 | 
			
		||||
 	struct phy_device *phydev = greth->phy;
 | 
			
		||||
 	unsigned long flags;
 | 
			
		||||
-
 | 
			
		||||
 	int status_change = 0;
 | 
			
		||||
+	u32 ctrl;
 | 
			
		||||
 
 | 
			
		||||
 	spin_lock_irqsave(&greth->devlock, flags);
 | 
			
		||||
 
 | 
			
		||||
 	if (phydev->link) {
 | 
			
		||||
 
 | 
			
		||||
 		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
 | 
			
		||||
-
 | 
			
		||||
-			GRETH_REGANDIN(greth->regs->control,
 | 
			
		||||
-				       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB));
 | 
			
		||||
+			ctrl = GRETH_REGLOAD(greth->regs->control) & 
 | 
			
		||||
+			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);
 | 
			
		||||
 
 | 
			
		||||
 			if (phydev->duplex)
 | 
			
		||||
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD);
 | 
			
		||||
-
 | 
			
		||||
-			if (phydev->speed == SPEED_100) {
 | 
			
		||||
-
 | 
			
		||||
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP);
 | 
			
		||||
-			}
 | 
			
		||||
+				ctrl |= GRETH_CTRL_FD;
 | 
			
		||||
 
 | 
			
		||||
+			if (phydev->speed == SPEED_100)
 | 
			
		||||
+				ctrl |= GRETH_CTRL_SP;
 | 
			
		||||
 			else if (phydev->speed == SPEED_1000)
 | 
			
		||||
-				GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB);
 | 
			
		||||
+				ctrl |= GRETH_CTRL_GB;
 | 
			
		||||
 
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control, ctrl);
 | 
			
		||||
 			greth->speed = phydev->speed;
 | 
			
		||||
 			greth->duplex = phydev->duplex;
 | 
			
		||||
 			status_change = 1;
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
From f62c047af910c9c9696db7b47472a3728b8100e8 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 11:56:22 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: handle frame error interrupts
 | 
			
		||||
 | 
			
		||||
Not handling frame error interrupts are unlikly but may lead to dead
 | 
			
		||||
lock if 128 error frames are recieved in a row.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    5 +++--
 | 
			
		||||
 drivers/net/greth.h |    2 ++
 | 
			
		||||
 2 files changed, 5 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -595,11 +595,12 @@ static irqreturn_t greth_interrupt(int i
 | 
			
		||||
 	status = GRETH_REGLOAD(greth->regs->status);
 | 
			
		||||
 
 | 
			
		||||
 	/* Handle rx and tx interrupts through poll */
 | 
			
		||||
-	if (status & (GRETH_INT_RX | GRETH_INT_TX)) {
 | 
			
		||||
+	if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) {
 | 
			
		||||
 
 | 
			
		||||
 		/* Clear interrupt status */
 | 
			
		||||
 		GRETH_REGSAVE(greth->regs->status,
 | 
			
		||||
-			      status & (GRETH_INT_RX | GRETH_INT_TX));
 | 
			
		||||
+			      status & (GRETH_INT_RE | GRETH_INT_RX | 
 | 
			
		||||
+					GRETH_INT_TE | GRETH_INT_TX));
 | 
			
		||||
 
 | 
			
		||||
 		retval = IRQ_HANDLED;
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/greth.h
 | 
			
		||||
+++ b/drivers/net/greth.h
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
 #define GRETH_BD_LEN 0x7FF
 | 
			
		||||
 
 | 
			
		||||
 #define GRETH_TXEN 0x1
 | 
			
		||||
+#define GRETH_INT_TE 0x2
 | 
			
		||||
 #define GRETH_INT_TX 0x8
 | 
			
		||||
 #define GRETH_TXI 0x4
 | 
			
		||||
 #define GRETH_TXBD_STATUS 0x0001C000
 | 
			
		||||
@@ -35,6 +36,7 @@
 | 
			
		||||
 #define GRETH_TXBD_ERR_UE 0x4000
 | 
			
		||||
 #define GRETH_TXBD_ERR_AL 0x8000
 | 
			
		||||
 
 | 
			
		||||
+#define GRETH_INT_RE         0x1
 | 
			
		||||
 #define GRETH_INT_RX         0x4
 | 
			
		||||
 #define GRETH_RXEN           0x2
 | 
			
		||||
 #define GRETH_RXI            0x8
 | 
			
		||||
@@ -0,0 +1,399 @@
 | 
			
		||||
From 4439d933884ee3c7e320b8d33bd2e268dd5b6fa5 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 11:40:19 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: resolve SMP issues and other problems
 | 
			
		||||
 | 
			
		||||
Fixes the following:
 | 
			
		||||
1. POLL should not enable IRQ when work is not completed
 | 
			
		||||
2. No locking between TX descriptor cleaning and XMIT descriptor handling
 | 
			
		||||
3. No locking between RX POLL and XMIT modifying control register
 | 
			
		||||
4. Since TX cleaning (called from POLL) is running in parallel with XMIT
 | 
			
		||||
   unnecessary locking is needed.
 | 
			
		||||
5. IRQ handler looks at RX frame status solely, this is wrong when IRQ is
 | 
			
		||||
   temporarily disabled (in POLL), and when IRQ is shared.
 | 
			
		||||
6. IRQ handler clears IRQ status, which is unnecessary
 | 
			
		||||
7. TX queue was stopped in preventing cause when not MAX_SKB_FRAGS+1 descriptors
 | 
			
		||||
   were available after a SKB been scheduled by XMIT. Instead the TX queue is
 | 
			
		||||
   stopped first when not enough descriptors are available upon entering XMIT.
 | 
			
		||||
 | 
			
		||||
It was hard to split up this patch in smaller pieces since all are tied
 | 
			
		||||
together somehow.
 | 
			
		||||
 | 
			
		||||
Note the RX flag used in the interrupt handler does not signal that interrtupt
 | 
			
		||||
was asserted, but that a frame was received. Same goes for TX. Also, IRQ is not
 | 
			
		||||
asserted when the RX flag is set before enabling IRQ enable until a new frame is
 | 
			
		||||
received. So extra care must be taken to avoid enabling IRQ and all descriptors
 | 
			
		||||
are already used, hence dead lock will upon us. See new POLL implementation that
 | 
			
		||||
enableds IRQ then look at the RX flag to determine if one or more IRQs may have
 | 
			
		||||
been missed. TX/RX flags are cleared before handling previously enabled
 | 
			
		||||
descriptors, this ensures that the RX/TX flags are valid when determining if IRQ
 | 
			
		||||
should be turned on again.
 | 
			
		||||
 | 
			
		||||
By moving TX cleaning from POLL to XMIT in the standard case, removes some
 | 
			
		||||
locking trouble. Enabling TX cleaning from poll only when not enough TX
 | 
			
		||||
descriptors are available is safe because the TX queue is at the same time
 | 
			
		||||
stopped, thus XMIT will not be called. The TX queue is woken up again when
 | 
			
		||||
enough descriptrs are available.
 | 
			
		||||
 | 
			
		||||
TX Frames are always enabled with IRQ, however the TX IRQ Enable flag will not
 | 
			
		||||
be enabled until XMIT must wait for free descriptors.
 | 
			
		||||
 | 
			
		||||
Locking RX and XMIT parts of the driver from each other is needed because the
 | 
			
		||||
RX/TX enable bits share the same register.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |  158 ++++++++++++++++++++++++++++++---------------------
 | 
			
		||||
 1 files changed, 93 insertions(+), 65 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
 /*
 | 
			
		||||
  * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC.
 | 
			
		||||
  *
 | 
			
		||||
- * 2005-2009 (c) Aeroflex Gaisler AB
 | 
			
		||||
+ * 2005-2010 (c) Aeroflex Gaisler AB
 | 
			
		||||
  *
 | 
			
		||||
  * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs
 | 
			
		||||
  * available in the GRLIB VHDL IP core library.
 | 
			
		||||
@@ -401,12 +401,20 @@ greth_start_xmit(struct sk_buff *skb, st
 | 
			
		||||
 	struct greth_private *greth = netdev_priv(dev);
 | 
			
		||||
 	struct greth_bd *bdp;
 | 
			
		||||
 	int err = NETDEV_TX_OK;
 | 
			
		||||
-	u32 status, dma_addr;
 | 
			
		||||
+	u32 status, dma_addr, ctrl;
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
 
 | 
			
		||||
-	bdp = greth->tx_bd_base + greth->tx_next;
 | 
			
		||||
+	/* Clean TX Ring */
 | 
			
		||||
+	greth_clean_tx(greth->netdev);
 | 
			
		||||
 
 | 
			
		||||
 	if (unlikely(greth->tx_free <= 0)) {
 | 
			
		||||
+		spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 | 
			
		||||
+		ctrl = GRETH_REGLOAD(greth->regs->control);
 | 
			
		||||
+		/* Enable TX IRQ only if not already in poll() routine */
 | 
			
		||||
+		if ( ctrl & GRETH_RXI )
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
 | 
			
		||||
 		netif_stop_queue(dev);
 | 
			
		||||
+		spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 		return NETDEV_TX_BUSY;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -419,13 +427,14 @@ greth_start_xmit(struct sk_buff *skb, st
 | 
			
		||||
 		goto out;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	bdp = greth->tx_bd_base + greth->tx_next;
 | 
			
		||||
 	dma_addr = greth_read_bd(&bdp->addr);
 | 
			
		||||
 
 | 
			
		||||
 	memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len);
 | 
			
		||||
 
 | 
			
		||||
 	dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE);
 | 
			
		||||
 
 | 
			
		||||
-	status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN);
 | 
			
		||||
+	status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN);
 | 
			
		||||
 
 | 
			
		||||
 	/* Wrap around descriptor ring */
 | 
			
		||||
 	if (greth->tx_next == GRETH_TXBD_NUM_MASK) {
 | 
			
		||||
@@ -435,22 +444,11 @@ greth_start_xmit(struct sk_buff *skb, st
 | 
			
		||||
 	greth->tx_next = NEXT_TX(greth->tx_next);
 | 
			
		||||
 	greth->tx_free--;
 | 
			
		||||
 
 | 
			
		||||
-	/* No more descriptors */
 | 
			
		||||
-	if (unlikely(greth->tx_free == 0)) {
 | 
			
		||||
-
 | 
			
		||||
-		/* Free transmitted descriptors */
 | 
			
		||||
-		greth_clean_tx(dev);
 | 
			
		||||
-
 | 
			
		||||
-		/* If nothing was cleaned, stop queue & wait for irq */
 | 
			
		||||
-		if (unlikely(greth->tx_free == 0)) {
 | 
			
		||||
-			status |= GRETH_BD_IE;
 | 
			
		||||
-			netif_stop_queue(dev);
 | 
			
		||||
-		}
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
 	/* Write descriptor control word and enable transmission */
 | 
			
		||||
 	greth_write_bd(&bdp->stat, status);
 | 
			
		||||
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 | 
			
		||||
 	greth_enable_tx(greth);
 | 
			
		||||
+	spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 
 | 
			
		||||
 out:
 | 
			
		||||
 	dev_kfree_skb(skb);
 | 
			
		||||
@@ -463,13 +461,24 @@ greth_start_xmit_gbit(struct sk_buff *sk
 | 
			
		||||
 {
 | 
			
		||||
 	struct greth_private *greth = netdev_priv(dev);
 | 
			
		||||
 	struct greth_bd *bdp;
 | 
			
		||||
-	u32 status = 0, dma_addr;
 | 
			
		||||
+	u32 status = 0, dma_addr, ctrl;
 | 
			
		||||
 	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
 
 | 
			
		||||
 	nr_frags = skb_shinfo(skb)->nr_frags;
 | 
			
		||||
 
 | 
			
		||||
+	/* Clean TX Ring */
 | 
			
		||||
+	greth_clean_tx_gbit(dev);
 | 
			
		||||
+
 | 
			
		||||
 	if (greth->tx_free < nr_frags + 1) {
 | 
			
		||||
+		spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 | 
			
		||||
+		ctrl = GRETH_REGLOAD(greth->regs->control);
 | 
			
		||||
+		/* Enable TX IRQ only if not already in poll() routine */
 | 
			
		||||
+		if ( ctrl & GRETH_RXI ) {
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
 | 
			
		||||
+		}
 | 
			
		||||
 		netif_stop_queue(dev);
 | 
			
		||||
+		spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 		err = NETDEV_TX_BUSY;
 | 
			
		||||
 		goto out;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -522,14 +531,8 @@ greth_start_xmit_gbit(struct sk_buff *sk
 | 
			
		||||
 		/* More fragments left */
 | 
			
		||||
 		if (i < nr_frags - 1)
 | 
			
		||||
 			status |= GRETH_TXBD_MORE;
 | 
			
		||||
-
 | 
			
		||||
-		/* ... last fragment, check if out of descriptors  */
 | 
			
		||||
-		else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) {
 | 
			
		||||
-
 | 
			
		||||
-			/* Enable interrupts and stop queue */
 | 
			
		||||
-			status |= GRETH_BD_IE;
 | 
			
		||||
-			netif_stop_queue(dev);
 | 
			
		||||
-		}
 | 
			
		||||
+		else
 | 
			
		||||
+			status |= GRETH_BD_IE; /* enable IRQ on last fragment */
 | 
			
		||||
 
 | 
			
		||||
 		greth_write_bd(&bdp->stat, status);
 | 
			
		||||
 
 | 
			
		||||
@@ -557,7 +560,9 @@ greth_start_xmit_gbit(struct sk_buff *sk
 | 
			
		||||
 
 | 
			
		||||
 	wmb();
 | 
			
		||||
 
 | 
			
		||||
+	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
 | 
			
		||||
 	greth_enable_tx(greth);
 | 
			
		||||
+	spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 
 | 
			
		||||
 	return NETDEV_TX_OK;
 | 
			
		||||
 
 | 
			
		||||
@@ -579,12 +584,11 @@ out:
 | 
			
		||||
 	return err;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-
 | 
			
		||||
 static irqreturn_t greth_interrupt(int irq, void *dev_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct net_device *dev = dev_id;
 | 
			
		||||
 	struct greth_private *greth;
 | 
			
		||||
-	u32 status;
 | 
			
		||||
+	u32 status, ctrl;
 | 
			
		||||
 	irqreturn_t retval = IRQ_NONE;
 | 
			
		||||
 
 | 
			
		||||
 	greth = netdev_priv(dev);
 | 
			
		||||
@@ -594,13 +598,14 @@ static irqreturn_t greth_interrupt(int i
 | 
			
		||||
 	/* Get the interrupt events that caused us to be here. */
 | 
			
		||||
 	status = GRETH_REGLOAD(greth->regs->status);
 | 
			
		||||
 
 | 
			
		||||
-	/* Handle rx and tx interrupts through poll */
 | 
			
		||||
-	if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) {
 | 
			
		||||
+	/* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be set regardless
 | 
			
		||||
+	 * of whether IRQ is enabled or not. Especially important when shared IRQ.
 | 
			
		||||
+	 */
 | 
			
		||||
+	ctrl = GRETH_REGLOAD(greth->regs->control);
 | 
			
		||||
 
 | 
			
		||||
-		/* Clear interrupt status */
 | 
			
		||||
-		GRETH_REGSAVE(greth->regs->status,
 | 
			
		||||
-			      status & (GRETH_INT_RE | GRETH_INT_RX | 
 | 
			
		||||
-					GRETH_INT_TE | GRETH_INT_TX));
 | 
			
		||||
+	/* Handle rx and tx interrupts through poll */
 | 
			
		||||
+	if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) ||
 | 
			
		||||
+	    ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) {
 | 
			
		||||
 
 | 
			
		||||
 		retval = IRQ_HANDLED;
 | 
			
		||||
 
 | 
			
		||||
@@ -625,6 +630,8 @@ static void greth_clean_tx(struct net_de
 | 
			
		||||
 
 | 
			
		||||
 	while (1) {
 | 
			
		||||
 		bdp = greth->tx_bd_base + greth->tx_last;
 | 
			
		||||
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
 | 
			
		||||
+		mb();
 | 
			
		||||
 		stat = greth_read_bd(&bdp->stat);
 | 
			
		||||
 
 | 
			
		||||
 		if (unlikely(stat & GRETH_BD_EN))
 | 
			
		||||
@@ -685,7 +692,10 @@ static void greth_clean_tx_gbit(struct n
 | 
			
		||||
 
 | 
			
		||||
 		/* We only clean fully completed SKBs */
 | 
			
		||||
 		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
 | 
			
		||||
-		stat = bdp_last_frag->stat;
 | 
			
		||||
+
 | 
			
		||||
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
 | 
			
		||||
+		mb();
 | 
			
		||||
+		stat = greth_read_bd(&bdp_last_frag->stat);
 | 
			
		||||
 
 | 
			
		||||
 		if (stat & GRETH_BD_EN)
 | 
			
		||||
 			break;
 | 
			
		||||
@@ -717,23 +727,12 @@ static void greth_clean_tx_gbit(struct n
 | 
			
		||||
 		greth->tx_free += nr_frags+1;
 | 
			
		||||
 		dev_kfree_skb(skb);
 | 
			
		||||
 	}
 | 
			
		||||
-	if (greth->tx_free > (MAX_SKB_FRAGS + 1)) {
 | 
			
		||||
+
 | 
			
		||||
+	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS + 1))) {
 | 
			
		||||
 		netif_wake_queue(dev);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int greth_pending_packets(struct greth_private *greth)
 | 
			
		||||
-{
 | 
			
		||||
-	struct greth_bd *bdp;
 | 
			
		||||
-	u32 status;
 | 
			
		||||
-	bdp = greth->rx_bd_base + greth->rx_cur;
 | 
			
		||||
-	status = greth_read_bd(&bdp->stat);
 | 
			
		||||
-	if (status & GRETH_BD_EN)
 | 
			
		||||
-		return 0;
 | 
			
		||||
-	else
 | 
			
		||||
-		return 1;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 static int greth_rx(struct net_device *dev, int limit)
 | 
			
		||||
 {
 | 
			
		||||
 	struct greth_private *greth;
 | 
			
		||||
@@ -742,20 +741,24 @@ static int greth_rx(struct net_device *d
 | 
			
		||||
 	int pkt_len;
 | 
			
		||||
 	int bad, count;
 | 
			
		||||
 	u32 status, dma_addr;
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
 
 | 
			
		||||
 	greth = netdev_priv(dev);
 | 
			
		||||
 
 | 
			
		||||
 	for (count = 0; count < limit; ++count) {
 | 
			
		||||
 
 | 
			
		||||
 		bdp = greth->rx_bd_base + greth->rx_cur;
 | 
			
		||||
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
 | 
			
		||||
+		mb();
 | 
			
		||||
 		status = greth_read_bd(&bdp->stat);
 | 
			
		||||
-		dma_addr = greth_read_bd(&bdp->addr);
 | 
			
		||||
-		bad = 0;
 | 
			
		||||
 
 | 
			
		||||
 		if (unlikely(status & GRETH_BD_EN)) {
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
+		dma_addr = greth_read_bd(&bdp->addr);
 | 
			
		||||
+		bad = 0;
 | 
			
		||||
+
 | 
			
		||||
 		/* Check status for errors. */
 | 
			
		||||
 		if (unlikely(status & GRETH_RXBD_STATUS)) {
 | 
			
		||||
 			if (status & GRETH_RXBD_ERR_FT) {
 | 
			
		||||
@@ -817,7 +820,9 @@ static int greth_rx(struct net_device *d
 | 
			
		||||
 
 | 
			
		||||
 		dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
 | 
			
		||||
 
 | 
			
		||||
+		spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */
 | 
			
		||||
 		greth_enable_rx(greth);
 | 
			
		||||
+		spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 
 | 
			
		||||
 		greth->rx_cur = NEXT_RX(greth->rx_cur);
 | 
			
		||||
 	}
 | 
			
		||||
@@ -851,6 +856,7 @@ static int greth_rx_gbit(struct net_devi
 | 
			
		||||
 	int pkt_len;
 | 
			
		||||
 	int bad, count = 0;
 | 
			
		||||
 	u32 status, dma_addr;
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
 
 | 
			
		||||
 	greth = netdev_priv(dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -858,6 +864,8 @@ static int greth_rx_gbit(struct net_devi
 | 
			
		||||
 
 | 
			
		||||
 		bdp = greth->rx_bd_base + greth->rx_cur;
 | 
			
		||||
 		skb = greth->rx_skbuff[greth->rx_cur];
 | 
			
		||||
+		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
 | 
			
		||||
+		mb();
 | 
			
		||||
 		status = greth_read_bd(&bdp->stat);
 | 
			
		||||
 		bad = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -940,7 +948,9 @@ static int greth_rx_gbit(struct net_devi
 | 
			
		||||
 
 | 
			
		||||
 		wmb();
 | 
			
		||||
 		greth_write_bd(&bdp->stat, status);
 | 
			
		||||
+		spin_lock_irqsave(&greth->devlock, flags);
 | 
			
		||||
 		greth_enable_rx(greth);
 | 
			
		||||
+		spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 		greth->rx_cur = NEXT_RX(greth->rx_cur);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -952,15 +962,19 @@ static int greth_poll(struct napi_struct
 | 
			
		||||
 {
 | 
			
		||||
 	struct greth_private *greth;
 | 
			
		||||
 	int work_done = 0;
 | 
			
		||||
+	unsigned long flags;
 | 
			
		||||
+	u32 mask, ctrl;
 | 
			
		||||
 	greth = container_of(napi, struct greth_private, napi);
 | 
			
		||||
 
 | 
			
		||||
-	if (greth->gbit_mac) {
 | 
			
		||||
-		greth_clean_tx_gbit(greth->netdev);
 | 
			
		||||
-	} else {
 | 
			
		||||
-		greth_clean_tx(greth->netdev);
 | 
			
		||||
+restart_txrx_poll:
 | 
			
		||||
+	if ( netif_queue_stopped(greth->netdev) ) {
 | 
			
		||||
+		if (greth->gbit_mac) {
 | 
			
		||||
+			greth_clean_tx_gbit(greth->netdev);
 | 
			
		||||
+		} else {
 | 
			
		||||
+			greth_clean_tx(greth->netdev);
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-restart_poll:
 | 
			
		||||
 	if (greth->gbit_mac) {
 | 
			
		||||
 		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
 | 
			
		||||
 	} else {
 | 
			
		||||
@@ -969,15 +983,29 @@ restart_poll:
 | 
			
		||||
 
 | 
			
		||||
 	if (work_done < budget) {
 | 
			
		||||
 
 | 
			
		||||
-		napi_complete(napi);
 | 
			
		||||
+		spin_lock_irqsave(&greth->devlock, flags);
 | 
			
		||||
 
 | 
			
		||||
-		if (greth_pending_packets(greth)) {
 | 
			
		||||
-			napi_reschedule(napi);
 | 
			
		||||
-			goto restart_poll;
 | 
			
		||||
+		ctrl = GRETH_REGLOAD(greth->regs->control);
 | 
			
		||||
+		if (netif_queue_stopped(greth->netdev)) {
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control,
 | 
			
		||||
+					ctrl | GRETH_TXI | GRETH_RXI);
 | 
			
		||||
+			mask = GRETH_INT_RX | GRETH_INT_RE |
 | 
			
		||||
+			       GRETH_INT_TX | GRETH_INT_TE;
 | 
			
		||||
+		} else {
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI);
 | 
			
		||||
+			mask = GRETH_INT_RX | GRETH_INT_RE;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		if (GRETH_REGLOAD(greth->regs->status) & mask) {
 | 
			
		||||
+			GRETH_REGSAVE(greth->regs->control, ctrl);
 | 
			
		||||
+			spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
+			goto restart_txrx_poll;
 | 
			
		||||
+		} else {
 | 
			
		||||
+			__napi_complete(napi);
 | 
			
		||||
+			spin_unlock_irqrestore(&greth->devlock, flags);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	greth_enable_irqs(greth);
 | 
			
		||||
 	return work_done;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1172,11 +1200,11 @@ static const struct ethtool_ops greth_et
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 static struct net_device_ops greth_netdev_ops = {
 | 
			
		||||
-	.ndo_open = greth_open,
 | 
			
		||||
-	.ndo_stop = greth_close,
 | 
			
		||||
-	.ndo_start_xmit = greth_start_xmit,
 | 
			
		||||
-	.ndo_set_mac_address = greth_set_mac_add,
 | 
			
		||||
-	.ndo_validate_addr 	= eth_validate_addr,
 | 
			
		||||
+	.ndo_open		= greth_open,
 | 
			
		||||
+	.ndo_stop		= greth_close,
 | 
			
		||||
+	.ndo_start_xmit		= greth_start_xmit,
 | 
			
		||||
+	.ndo_set_mac_address	= greth_set_mac_add,
 | 
			
		||||
+	.ndo_validate_addr	= eth_validate_addr,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 static inline int wait_for_mdio(struct greth_private *greth)
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
From 66d5b37cc6d32291419bf99161e83e2946ea5f25 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 12:11:03 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: added option to disable a device node from bootloader.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    6 ++++++
 | 
			
		||||
 1 files changed, 6 insertions(+), 0 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -1428,6 +1428,12 @@ static int __devinit greth_of_probe(stru
 | 
			
		||||
 	int err;
 | 
			
		||||
 	int tmp;
 | 
			
		||||
 	unsigned long timeout;
 | 
			
		||||
+	int *ampopts;
 | 
			
		||||
+
 | 
			
		||||
+	/* Skip device if used by another OS instance */
 | 
			
		||||
+	ampopts = (int *) of_get_property(ofdev->dev.of_node, "ampopts", NULL);
 | 
			
		||||
+	if (ampopts && (*ampopts == 0))
 | 
			
		||||
+		return -EIO;
 | 
			
		||||
 
 | 
			
		||||
 	dev = alloc_etherdev(sizeof(struct greth_private));
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
From 50fcb51c42bc721f18f1bfa10f705519cd344a2a Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Hellstrom <daniel@gaisler.com>
 | 
			
		||||
Date: Wed, 1 Dec 2010 16:20:01 +0100
 | 
			
		||||
Subject: [PATCH] GRETH: Newer GBit MACs need setting EE bit when EDCL should be enabled
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/greth.c |    2 +-
 | 
			
		||||
 drivers/net/greth.h |    1 +
 | 
			
		||||
 2 files changed, 2 insertions(+), 1 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/greth.c
 | 
			
		||||
+++ b/drivers/net/greth.c
 | 
			
		||||
@@ -1511,7 +1511,7 @@ static int __devinit greth_of_probe(stru
 | 
			
		||||
 	/* If we have EDCL we disable the EDCL speed-duplex FSM so
 | 
			
		||||
 	 * it doesn't interfere with the software */
 | 
			
		||||
 	if (greth->edcl != 0)
 | 
			
		||||
-		GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX);
 | 
			
		||||
+		GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX|GRETH_CTRL_EE);
 | 
			
		||||
 
 | 
			
		||||
 	/* Check if MAC can handle MDIO interrupts */
 | 
			
		||||
 	greth->mdio_int_en = (tmp >> 26) & 1;
 | 
			
		||||
--- a/drivers/net/greth.h
 | 
			
		||||
+++ b/drivers/net/greth.h
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
 #define GRETH_CTRL_PSTATIEN   0x400
 | 
			
		||||
 #define GRETH_CTRL_MCEN       0x800
 | 
			
		||||
 #define GRETH_CTRL_DISDUPLEX  0x1000
 | 
			
		||||
+#define GRETH_CTRL_EE         0x4000
 | 
			
		||||
 #define GRETH_STATUS_PHYSTAT  0x100
 | 
			
		||||
 
 | 
			
		||||
 #define GRETH_BD_EN 0x800
 | 
			
		||||
		Reference in New Issue
	
	Block a user