]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 4 Jul 2009 17:31:26 +0000 (10:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 4 Jul 2009 17:31:26 +0000 (10:31 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6:
  mfd: fix pcap adc locking
  mfd: sm501, fix lock imbalance

152 files changed:
.gitignore
Makefile
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/ar7/Makefile [new file with mode: 0644]
arch/mips/ar7/clock.c [new file with mode: 0644]
arch/mips/ar7/gpio.c [new file with mode: 0644]
arch/mips/ar7/irq.c [new file with mode: 0644]
arch/mips/ar7/memory.c [new file with mode: 0644]
arch/mips/ar7/platform.c [new file with mode: 0644]
arch/mips/ar7/prom.c [new file with mode: 0644]
arch/mips/ar7/setup.c [new file with mode: 0644]
arch/mips/ar7/time.c [new file with mode: 0644]
arch/mips/cavium-octeon/Makefile
arch/mips/cavium-octeon/dma-octeon.c
arch/mips/cavium-octeon/pci-common.c [deleted file]
arch/mips/cobalt/buttons.c
arch/mips/cobalt/lcd.c
arch/mips/cobalt/led.c
arch/mips/cobalt/mtd.c
arch/mips/cobalt/rtc.c
arch/mips/cobalt/serial.c
arch/mips/cobalt/time.c
arch/mips/configs/ar7_defconfig [new file with mode: 0644]
arch/mips/gt64120/wrppmc/serial.c
arch/mips/include/asm/amon.h [new file with mode: 0644]
arch/mips/include/asm/ds1287.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/gcmpregs.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/irq_gt641xx.h
arch/mips/include/asm/mach-ar7/ar7.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/gpio.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/prom.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/spaces.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/war.h [new file with mode: 0644]
arch/mips/include/asm/mach-cobalt/irq.h
arch/mips/include/asm/mach-cobalt/mach-gt64120.h
arch/mips/include/asm/octeon/pci-octeon.h [moved from arch/mips/cavium-octeon/pci-common.h with 52% similarity]
arch/mips/include/asm/page.h
arch/mips/include/asm/reg.h
arch/mips/include/asm/swab.h
arch/mips/include/asm/unistd.h
arch/mips/include/asm/vr41xx/capcella.h
arch/mips/include/asm/vr41xx/giu.h
arch/mips/include/asm/vr41xx/irq.h
arch/mips/include/asm/vr41xx/mpc30x.h
arch/mips/include/asm/vr41xx/pci.h
arch/mips/include/asm/vr41xx/siu.h
arch/mips/include/asm/vr41xx/tb0219.h
arch/mips/include/asm/vr41xx/tb0226.h
arch/mips/include/asm/vr41xx/vr41xx.h
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/cevt-ds1287.c
arch/mips/kernel/cevt-gt641xx.c
arch/mips/kernel/csrc-ioasic.c
arch/mips/kernel/irq-gic.c
arch/mips/kernel/irq-gt641xx.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/sync-r4k.c
arch/mips/kernel/vpe.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-reset.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-capcella.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-tb0219.c
arch/mips/pci/fixup-tb0226.c
arch/mips/pci/fixup-tb0287.c
arch/mips/pci/msi-octeon.c [moved from arch/mips/cavium-octeon/msi.c with 88% similarity]
arch/mips/pci/ops-vr41xx.c
arch/mips/pci/pci-octeon.c [moved from arch/mips/cavium-octeon/pci.c with 78% similarity]
arch/mips/pci/pci-vr41xx.c
arch/mips/pci/pci-vr41xx.h
arch/mips/pci/pcie-octeon.c [moved from arch/mips/cavium-octeon/pcie.c with 98% similarity]
arch/mips/vr41xx/casio-e55/setup.c
arch/mips/vr41xx/common/bcu.c
arch/mips/vr41xx/common/cmu.c
arch/mips/vr41xx/common/giu.c
arch/mips/vr41xx/common/icu.c
arch/mips/vr41xx/common/init.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/common/pmu.c
arch/mips/vr41xx/common/rtc.c
arch/mips/vr41xx/common/siu.c
arch/mips/vr41xx/common/type.c
arch/mips/vr41xx/ibm-workpad/setup.c
arch/mn10300/kernel/vmlinux.lds.S
arch/x86/Kconfig
arch/x86/kernel/pci-dma.c
block/blk-merge.c
block/elevator.c
drivers/block/cciss.c
drivers/block/cciss_cmd.h
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/tb0219.c
drivers/char/vr41xx_giu.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/vr41xx_giu.c [new file with mode: 0644]
drivers/input/misc/cobalt_btns.c
drivers/leds/leds-cobalt-raq.c
drivers/pci/intel-iommu.c
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/vrc4173_cardu.c
drivers/pcmcia/vrc4173_cardu.h
drivers/rtc/rtc-vr41xx.c
drivers/scsi/cxgb3i/Kbuild
drivers/scsi/cxgb3i/cxgb3i_iscsi.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/zalon.c
drivers/serial/vr41xx_siu.c
drivers/ssb/driver_mipscore.c
drivers/video/cobalt_lcdfb.c
fs/btrfs/async-thread.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/transaction.c
fs/nfsd/vfs.c
fs/notify/inotify/inotify_user.c
include/asm-generic/vmlinux.lds.h
include/linux/init_task.h
include/linux/linkage.h
scripts/.gitignore
scripts/package/builddeb
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0110.c
sound/pci/hda/patch_realtek.c
sound/pci/oxygen/virtuoso.c
sound/soc/fsl/Kconfig
sound/soc/omap/omap-pcm.c
sound/soc/pxa/pxa2xx-i2s.c
sound/sound_core.c
sound/usb/caiaq/device.c
sound/usb/usx2y/us122l.c
sound/usb/usx2y/usbusx2y.c

index cecb3b040cc17d22acdb9268e130a459e771608a..b93fb7eff94286c7a15d475fa581dac32a89b0db 100644 (file)
@@ -27,6 +27,7 @@
 *.gz
 *.lzma
 *.patch
+*.gcno
 
 #
 # Top-level generic files
index d1216fea0c922bf70de0203d3a51124a825c98c4..b4c7ef5ab431d1c32fd8b53e8e928152c5f06049 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -140,15 +140,13 @@ _all: modules
 endif
 
 srctree                := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
-TOPDIR         := $(srctree)
-# FIXME - TOPDIR is obsolete, use srctree/objtree
 objtree                := $(CURDIR)
 src            := $(srctree)
 obj            := $(objtree)
 
 VPATH          := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
 
-export srctree objtree VPATH TOPDIR
+export srctree objtree VPATH
 
 
 # SUBARCH tells the usermode build what the underlying arch is.  That is set
@@ -344,7 +342,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__
 
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
-                  -Werror-implicit-function-declaration
+                  -Werror-implicit-function-declaration \
+                  -Wno-format-security
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
index 8c4be1f301cf2f9b1310eae61502ebd33b5391f1..3ca0fe1a91231441d9767fdcd56a9caafe203c83 100644 (file)
@@ -22,6 +22,26 @@ choice
 config MACH_ALCHEMY
        bool "Alchemy processor based machines"
 
+config AR7
+       bool "Texas Instruments AR7"
+       select BOOT_ELF32
+       select DMA_NONCOHERENT
+       select CEVT_R4K
+       select CSRC_R4K
+       select IRQ_CPU
+       select NO_EXCEPT_FILL
+       select SWAP_IO_SPACE
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select GENERIC_GPIO
+       select GCD
+       select VLYNQ
+       help
+         Support for the Texas Instruments AR7 System-on-a-Chip
+         family: TNETD7100, 7200 and 7300.
+
 config BASLER_EXCITE
        bool "Basler eXcite smart camera"
        select CEVT_R4K
@@ -209,7 +229,7 @@ config MIPS_MALTA
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
-       select SYS_SUPPORTS_MIPS_CMP if BROKEN  # because SYNC_R4K is broken
+       select SYS_SUPPORTS_MIPS_CMP
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_SMARTMIPS
        help
@@ -247,6 +267,7 @@ config MACH_VR41XX
        select CEVT_R4K
        select CSRC_R4K
        select SYS_HAS_CPU_VR41XX
+       select ARCH_REQUIRE_GPIOLIB
 
 config NXP_STB220
        bool "NXP STB220 board"
@@ -1635,7 +1656,7 @@ config MIPS_APSP_KSPD
 config MIPS_CMP
        bool "MIPS CMP framework support"
        depends on SYS_SUPPORTS_MIPS_CMP
-       select SYNC_R4K if BROKEN
+       select SYNC_R4K
        select SYS_SUPPORTS_SMP
        select SYS_SUPPORTS_SCHED_SMT if SMP
        select WEAK_ORDERING
@@ -2147,11 +2168,11 @@ menu "Power management options"
 
 config ARCH_HIBERNATION_POSSIBLE
        def_bool y
-       depends on SYS_SUPPORTS_HOTPLUG_CPU
+       depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
 
 config ARCH_SUSPEND_POSSIBLE
        def_bool y
-       depends on SYS_SUPPORTS_HOTPLUG_CPU
+       depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
 
 source "kernel/power/Kconfig"
 
index 807572a6a4d2df80335ee2334518c9ae5726841f..861da514a468a7cf84bdb0d32cd703921f7853e0 100644 (file)
@@ -172,6 +172,13 @@ libs-y                             += arch/mips/fw/lib/
 # Board-dependent options and extra files
 #
 
+#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7)             += arch/mips/ar7/
+cflags-$(CONFIG_AR7)           += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7)             += 0xffffffff94100000
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644 (file)
index 0000000..7435e44
--- /dev/null
@@ -0,0 +1,10 @@
+
+obj-y := \
+       prom.o \
+       setup.o \
+       memory.o \
+       irq.o \
+       time.o \
+       platform.o \
+       gpio.o \
+       clock.o
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644 (file)
index 0000000..27dc666
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <linux/io.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK   0x3
+#define CPU_PLL_SOURCE_SHIFT   16
+#define BUS_PLL_SOURCE_SHIFT   14
+#define USB_PLL_SOURCE_SHIFT   18
+#define DSP_PLL_SOURCE_SHIFT   22
+#define BOOT_PLL_SOURCE_AFE    0
+#define BOOT_PLL_SOURCE_BUS    0
+#define BOOT_PLL_SOURCE_REF    1
+#define BOOT_PLL_SOURCE_XTAL   2
+#define BOOT_PLL_SOURCE_CPU    3
+#define BOOT_PLL_BYPASS                0x00000020
+#define BOOT_PLL_ASYNC_MODE    0x02000000
+#define BOOT_PLL_2TO1_MODE     0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU 0
+#define TNETD7200_CLOCK_ID_DSP 1
+#define TNETD7200_CLOCK_ID_USB 2
+
+#define TNETD7200_DEF_CPU_CLK  211000000
+#define TNETD7200_DEF_DSP_CLK  125000000
+#define TNETD7200_DEF_USB_CLK  48000000
+
+struct tnetd7300_clock {
+       u32 ctrl;
+#define PREDIV_MASK    0x001f0000
+#define PREDIV_SHIFT   16
+#define POSTDIV_MASK   0x0000001f
+       u32 unused1[3];
+       u32 pll;
+#define MUL_MASK       0x0000f000
+#define MUL_SHIFT      12
+#define PLL_MODE_MASK  0x00000001
+#define PLL_NDIV       0x00000800
+#define PLL_DIV                0x00000002
+#define PLL_STATUS     0x00000001
+       u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+       struct tnetd7300_clock bus;
+       struct tnetd7300_clock cpu;
+       struct tnetd7300_clock usb;
+       struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+       u32 ctrl;
+       u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+       u32 mul;
+       u32 prediv;
+       u32 postdiv;
+       u32 postdiv2;
+       u32 unused2[6];
+       u32 cmd;
+       u32 status;
+       u32 cmden;
+       u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+       struct tnetd7200_clock cpu;
+       struct tnetd7200_clock dsp;
+       struct tnetd7200_clock usb;
+};
+
+int ar7_cpu_clock = 150000000;
+EXPORT_SYMBOL(ar7_cpu_clock);
+int ar7_bus_clock = 125000000;
+EXPORT_SYMBOL(ar7_bus_clock);
+int ar7_dsp_clock;
+EXPORT_SYMBOL(ar7_dsp_clock);
+
+static void approximate(int base, int target, int *prediv,
+                       int *postdiv, int *mul)
+{
+       int i, j, k, freq, res = target;
+       for (i = 1; i <= 16; i++)
+               for (j = 1; j <= 32; j++)
+                       for (k = 1; k <= 32; k++) {
+                               freq = abs(base / j * i / k - target);
+                               if (freq < res) {
+                                       res = freq;
+                                       *mul = i;
+                                       *prediv = j;
+                                       *postdiv = k;
+                               }
+                       }
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+       int *mul)
+{
+       int tmp_gcd, tmp_base, tmp_freq;
+
+       for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+               tmp_base = base / *prediv;
+               tmp_gcd = gcd(target, tmp_base);
+               *mul = target / tmp_gcd;
+               *postdiv = tmp_base / tmp_gcd;
+               if ((*mul < 1) || (*mul >= 16))
+                       continue;
+               if ((*postdiv > 0) & (*postdiv <= 32))
+                       break;
+       }
+
+       if (base / *prediv * *mul / *postdiv != target) {
+               approximate(base, target, prediv, postdiv, mul);
+               tmp_freq = base / *prediv * *mul / *postdiv;
+               printk(KERN_WARNING
+                      "Adjusted requested frequency %d to %d\n",
+                      target, tmp_freq);
+       }
+
+       printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+              *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+       u32 didr1, didr2;
+       u8 rev = ar7_chip_rev();
+       didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+       didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+       if (didr2 & (1 << 23))
+               return 0;
+       if ((rev >= 0x23) && (rev != 0x57))
+               return 250000000;
+       if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+           > 4208000)
+               return 250000000;
+       return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+       u32 *bootcr, u32 bus_clock)
+{
+       int product;
+       int base_clock = AR7_REF_CLOCK;
+       u32 ctrl = readl(&clock->ctrl);
+       u32 pll = readl(&clock->pll);
+       int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+       int postdiv = (ctrl & POSTDIV_MASK) + 1;
+       int divisor = prediv * postdiv;
+       int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+       switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+       case BOOT_PLL_SOURCE_BUS:
+               base_clock = bus_clock;
+               break;
+       case BOOT_PLL_SOURCE_REF:
+               base_clock = AR7_REF_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_XTAL:
+               base_clock = AR7_XTAL_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_CPU:
+               base_clock = ar7_cpu_clock;
+               break;
+       }
+
+       if (*bootcr & BOOT_PLL_BYPASS)
+               return base_clock / divisor;
+
+       if ((pll & PLL_MODE_MASK) == 0)
+               return (base_clock >> (mul / 16 + 1)) / divisor;
+
+       if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+               product = (mul & 1) ?
+                       (base_clock * mul) >> 1 :
+                       (base_clock * (mul - 1)) >> 2;
+               return product / divisor;
+       }
+
+       if (mul == 16)
+               return base_clock / divisor;
+
+       return base_clock * mul / divisor;
+}
+
+static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
+       u32 *bootcr, u32 frequency)
+{
+       int prediv, postdiv, mul;
+       int base_clock = ar7_bus_clock;
+
+       switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+       case BOOT_PLL_SOURCE_BUS:
+               base_clock = ar7_bus_clock;
+               break;
+       case BOOT_PLL_SOURCE_REF:
+               base_clock = AR7_REF_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_XTAL:
+               base_clock = AR7_XTAL_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_CPU:
+               base_clock = ar7_cpu_clock;
+               break;
+       }
+
+       calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+       writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+       msleep(1);
+       writel(4, &clock->pll);
+       while (readl(&clock->pll) & PLL_STATUS)
+               ;
+       writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+       msleep(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+       u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+       struct tnetd7300_clocks *clocks =
+                                       ioremap_nocache(UR8_REGS_CLOCKS,
+                                       sizeof(struct tnetd7300_clocks));
+
+       ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
+               &clocks->bus, bootcr, AR7_AFE_CLOCK);
+
+       if (*bootcr & BOOT_PLL_ASYNC_MODE)
+               ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
+                       &clocks->cpu, bootcr, AR7_AFE_CLOCK);
+       else
+               ar7_cpu_clock = ar7_bus_clock;
+
+       if (ar7_dsp_clock == 250000000)
+               tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+                       bootcr, ar7_dsp_clock);
+
+       iounmap(clocks);
+       iounmap(bootcr);
+}
+
+static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
+       u32 *bootcr, u32 bus_clock)
+{
+       int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
+               ((readl(&clock->postdiv) & 0x1f) + 1);
+
+       if (*bootcr & BOOT_PLL_BYPASS)
+               return base / divisor;
+
+       return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
+}
+
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+       int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+       printk(KERN_INFO
+               "Clocks: base = %d, frequency = %u, prediv = %d, "
+               "postdiv = %d, postdiv2 = %d, mul = %d\n",
+               base, frequency, prediv, postdiv, postdiv2, mul);
+
+       writel(0, &clock->ctrl);
+       writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+       writel((mul - 1) & 0xF, &clock->mul);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+       writel(readl(&clock->cmden) | 1, &clock->cmden);
+       writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+       writel(readl(&clock->cmden) | 1, &clock->cmden);
+       writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+       if (*bootcr & BOOT_PLL_ASYNC_MODE)
+               /* Async */
+               switch (clock_id) {
+               case TNETD7200_CLOCK_ID_DSP:
+                       return AR7_REF_CLOCK;
+               default:
+                       return AR7_AFE_CLOCK;
+               }
+       else
+               /* Sync */
+               if (*bootcr & BOOT_PLL_2TO1_MODE)
+                       /* 2:1 */
+                       switch (clock_id) {
+                       case TNETD7200_CLOCK_ID_DSP:
+                               return AR7_REF_CLOCK;
+                       default:
+                               return AR7_AFE_CLOCK;
+                       }
+               else
+                       /* 1:1 */
+                       return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+       u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+       struct tnetd7200_clocks *clocks =
+                                       ioremap_nocache(AR7_REGS_CLOCKS,
+                                       sizeof(struct tnetd7200_clocks));
+       int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+       int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+       int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+       cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+       dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+       if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+               printk(KERN_INFO "Clocks: Async mode\n");
+
+               printk(KERN_INFO "Clocks: Setting DSP clock\n");
+               calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
+                       &dsp_prediv, &dsp_postdiv, &dsp_mul);
+               ar7_bus_clock =
+                       ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
+               tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                       dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+                       ar7_bus_clock);
+
+               printk(KERN_INFO "Clocks: Setting CPU clock\n");
+               calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+                       &cpu_postdiv, &cpu_mul);
+               ar7_cpu_clock =
+                       ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
+               tnetd7200_set_clock(cpu_base, &clocks->cpu,
+                       cpu_prediv, cpu_postdiv, -1, cpu_mul,
+                       ar7_cpu_clock);
+
+       } else
+               if (*bootcr & BOOT_PLL_2TO1_MODE) {
+                       printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+                       printk(KERN_INFO "Clocks: Setting CPU clock\n");
+                       calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+                               &cpu_postdiv, &cpu_mul);
+                       ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
+                                                               / cpu_postdiv;
+                       tnetd7200_set_clock(cpu_base, &clocks->cpu,
+                               cpu_prediv, cpu_postdiv, -1, cpu_mul,
+                               ar7_cpu_clock);
+
+                       printk(KERN_INFO "Clocks: Setting DSP clock\n");
+                       calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+                               &dsp_postdiv, &dsp_mul);
+                       ar7_bus_clock = ar7_cpu_clock / 2;
+                       tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                               dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+                               dsp_mul * 2, ar7_bus_clock);
+               } else {
+                       printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
+
+                       printk(KERN_INFO "Clocks: Setting DSP clock\n");
+                       calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+                               &dsp_postdiv, &dsp_mul);
+                       ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
+                                                               / dsp_postdiv;
+                       tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                               dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+                               dsp_mul * 2, ar7_bus_clock);
+
+                       ar7_cpu_clock = ar7_bus_clock;
+               }
+
+       printk(KERN_INFO "Clocks: Setting USB clock\n");
+       usb_base = ar7_bus_clock;
+       calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
+               &usb_postdiv, &usb_mul);
+       tnetd7200_set_clock(usb_base, &clocks->usb,
+               usb_prediv, usb_postdiv, -1, usb_mul,
+               TNETD7200_DEF_USB_CLK);
+
+       ar7_dsp_clock = ar7_cpu_clock;
+
+       iounmap(clocks);
+       iounmap(bootcr);
+}
+
+int __init ar7_init_clocks(void)
+{
+       switch (ar7_chip_id()) {
+       case AR7_CHIP_7100:
+       case AR7_CHIP_7200:
+               tnetd7200_init_clocks();
+               break;
+       case AR7_CHIP_7300:
+               ar7_dsp_clock = tnetd7300_dsp_clock();
+               tnetd7300_init_clocks();
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+arch_initcall(ar7_init_clocks);
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644 (file)
index 0000000..74e14a3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       if (ar7_gpio_list[gpio])
+               return -EBUSY;
+
+       if (label)
+               ar7_gpio_list[gpio] = label;
+       else
+               ar7_gpio_list[gpio] = "busy";
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       BUG_ON(!ar7_gpio_list[gpio]);
+       ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644 (file)
index 0000000..c781556
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET  0x80
+#define PACE_OFFSET    0xA0
+#define CHNLS_OFFSET   0x200
+
+#define REG_OFFSET(irq, reg)   ((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg)    (EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET          (SEC_REG_OFFSET(0))     /* 0x80 */
+#define CR_OFFSET(irq)         (REG_OFFSET(irq, 1))    /* 0x10 */
+#define SEC_CR_OFFSET          (SEC_REG_OFFSET(1))     /* 0x88 */
+#define ESR_OFFSET(irq)                (REG_OFFSET(irq, 2))    /* 0x20 */
+#define SEC_ESR_OFFSET         (SEC_REG_OFFSET(2))     /* 0x90 */
+#define ECR_OFFSET(irq)                (REG_OFFSET(irq, 3))    /* 0x30 */
+#define SEC_ECR_OFFSET         (SEC_REG_OFFSET(3))     /* 0x98 */
+#define PIR_OFFSET             (0x40)
+#define MSR_OFFSET             (0x44)
+#define PM_OFFSET(irq)         (REG_OFFSET(irq, 5))    /* 0x50 */
+#define TM_OFFSET(irq)         (REG_OFFSET(irq, 6))    /* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static int ar7_irq_base;
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+}
+
+static struct irq_chip ar7_irq_type = {
+       .name = "AR7",
+       .unmask = ar7_unmask_irq,
+       .mask = ar7_mask_irq,
+       .ack = ar7_ack_irq
+};
+
+static struct irq_chip ar7_sec_irq_type = {
+       .name = "AR7",
+       .unmask = ar7_unmask_sec_irq,
+       .mask = ar7_mask_sec_irq,
+       .ack = ar7_ack_sec_irq,
+};
+
+static struct irqaction ar7_cascade_action = {
+       .handler = no_action,
+       .name = "AR7 cascade interrupt"
+};
+
+static void __init ar7_irq_init(int base)
+{
+       int i;
+       /*
+        * Disable interrupts and clear pending
+        */
+       writel(0xffffffff, REG(ECR_OFFSET(0)));
+       writel(0xff, REG(ECR_OFFSET(32)));
+       writel(0xffffffff, REG(SEC_ECR_OFFSET));
+       writel(0xffffffff, REG(CR_OFFSET(0)));
+       writel(0xff, REG(CR_OFFSET(32)));
+       writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+       ar7_irq_base = base;
+
+       for (i = 0; i < 40; i++) {
+               writel(i, REG(CHNL_OFFSET(i)));
+               /* Primary IRQ's */
+               set_irq_chip_and_handler(base + i, &ar7_irq_type,
+                                        handle_level_irq);
+               /* Secondary IRQ's */
+               if (i < 32)
+                       set_irq_chip_and_handler(base + i + 40,
+                                                &ar7_sec_irq_type,
+                                                handle_level_irq);
+       }
+
+       setup_irq(2, &ar7_cascade_action);
+       setup_irq(ar7_irq_base, &ar7_cascade_action);
+       set_c0_status(IE_IRQ0);
+}
+
+void __init arch_init_irq(void)
+{
+       mips_cpu_irq_init();
+       ar7_irq_init(8);
+}
+
+static void ar7_cascade(void)
+{
+       u32 status;
+       int i, irq;
+
+       /* Primary IRQ's */
+       irq = readl(REG(PIR_OFFSET)) & 0x3f;
+       if (irq) {
+               do_IRQ(ar7_irq_base + irq);
+               return;
+       }
+
+       /* Secondary IRQ's are cascaded through primary '0' */
+       writel(1, REG(CR_OFFSET(irq)));
+       status = readl(REG(SEC_SR_OFFSET));
+       for (i = 0; i < 32; i++) {
+               if (status & 1) {
+                       do_IRQ(ar7_irq_base + i + 40);
+                       return;
+               }
+               status >>= 1;
+       }
+
+       spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+       if (pending & STATUSF_IP7)              /* cpu timer */
+               do_IRQ(7);
+       else if (pending & STATUSF_IP2)         /* int0 hardware line */
+               ar7_cascade();
+       else
+               spurious_interrupt();
+}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644 (file)
index 0000000..46fed44
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+       u32 size = (64 << 20);
+       u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
+       u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+       u32 *tmpaddr = addr;
+
+       while (tmpaddr > kernel_end) {
+               *tmpaddr = (u32)tmpaddr;
+               size >>= 1;
+               tmpaddr -= size >> 2;
+       }
+
+       do {
+               tmpaddr += size >> 2;
+               if (*tmpaddr != (u32)tmpaddr)
+                       break;
+               size <<= 1;
+       } while (size < (64 << 20));
+
+       writel(tmpaddr, &addr);
+
+       return size;
+}
+
+void __init prom_meminit(void)
+{
+       unsigned long pages;
+
+       pages = memsize() >> PAGE_SHIFT;
+       add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+                         BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+       /* Nothing to free */
+}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644 (file)
index 0000000..5422449
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+struct plat_vlynq_data {
+       struct plat_vlynq_ops ops;
+       int gpio_bit;
+       int reset_bit;
+};
+
+
+static int vlynq_on(struct vlynq_device *dev)
+{
+       int result;
+       struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+       result = gpio_request(pdata->gpio_bit, "vlynq");
+       if (result)
+               goto out;
+
+       ar7_device_reset(pdata->reset_bit);
+
+       result = ar7_gpio_disable(pdata->gpio_bit);
+       if (result)
+               goto out_enabled;
+
+       result = ar7_gpio_enable(pdata->gpio_bit);
+       if (result)
+               goto out_enabled;
+
+       result = gpio_direction_output(pdata->gpio_bit, 0);
+       if (result)
+               goto out_gpio_enabled;
+
+       msleep(50);
+
+       gpio_set_value(pdata->gpio_bit, 1);
+       msleep(50);
+
+       return 0;
+
+out_gpio_enabled:
+       ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+       ar7_device_disable(pdata->reset_bit);
+       gpio_free(pdata->gpio_bit);
+out:
+       return result;
+}
+
+static void vlynq_off(struct vlynq_device *dev)
+{
+       struct plat_vlynq_data *pdata = dev->dev.platform_data;
+       ar7_gpio_disable(pdata->gpio_bit);
+       gpio_free(pdata->gpio_bit);
+       ar7_device_disable(pdata->reset_bit);
+}
+
+static struct resource physmap_flash_resource = {
+       .name = "mem",
+       .flags = IORESOURCE_MEM,
+       .start = 0x10000000,
+       .end = 0x107fffff,
+};
+
+static struct resource cpmac_low_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_MAC0,
+               .end = AR7_REGS_MAC0 + 0x7ff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 27,
+               .end = 27,
+       },
+};
+
+static struct resource cpmac_high_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_MAC1,
+               .end = AR7_REGS_MAC1 + 0x7ff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 41,
+               .end = 41,
+       },
+};
+
+static struct resource vlynq_low_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_VLYNQ0,
+               .end = AR7_REGS_VLYNQ0 + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 29,
+               .end = 29,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x04000000,
+               .end = 0x04ffffff,
+       },
+       {
+               .name = "devirq",
+               .flags = IORESOURCE_IRQ,
+               .start = 80,
+               .end = 111,
+       },
+};
+
+static struct resource vlynq_high_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_VLYNQ1,
+               .end = AR7_REGS_VLYNQ1 + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 33,
+               .end = 33,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x0c000000,
+               .end = 0x0cffffff,
+       },
+       {
+               .name = "devirq",
+               .flags = IORESOURCE_IRQ,
+               .start = 112,
+               .end = 143,
+       },
+};
+
+static struct resource usb_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_USB,
+               .end = AR7_REGS_USB + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 32,
+               .end = 32,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x03400000,
+               .end = 0x034001fff,
+       },
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+       .width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+       .reset_bit = 17,
+       .power_bit = 20,
+       .phy_mask = 0x80000000,
+};
+
+static struct plat_cpmac_data cpmac_high_data = {
+       .reset_bit = 21,
+       .power_bit = 22,
+       .phy_mask = 0x7fffffff,
+};
+
+static struct plat_vlynq_data vlynq_low_data = {
+       .ops.on = vlynq_on,
+       .ops.off = vlynq_off,
+       .reset_bit = 20,
+       .gpio_bit = 18,
+};
+
+static struct plat_vlynq_data vlynq_high_data = {
+       .ops.on = vlynq_on,
+       .ops.off = vlynq_off,
+       .reset_bit = 16,
+       .gpio_bit = 19,
+};
+
+static struct platform_device physmap_flash = {
+       .id = 0,
+       .name = "physmap-flash",
+       .dev.platform_data = &physmap_flash_data,
+       .resource = &physmap_flash_resource,
+       .num_resources = 1,
+};
+
+static u64 cpmac_dma_mask = DMA_32BIT_MASK;
+static struct platform_device cpmac_low = {
+       .id = 0,
+       .name = "cpmac",
+       .dev = {
+               .dma_mask = &cpmac_dma_mask,
+               .coherent_dma_mask = DMA_32BIT_MASK,
+               .platform_data = &cpmac_low_data,
+       },
+       .resource = cpmac_low_res,
+       .num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+       .id = 1,
+       .name = "cpmac",
+       .dev = {
+               .dma_mask = &cpmac_dma_mask,
+               .coherent_dma_mask = DMA_32BIT_MASK,
+               .platform_data = &cpmac_high_data,
+       },
+       .resource = cpmac_high_res,
+       .num_resources = ARRAY_SIZE(cpmac_high_res),
+};
+
+static struct platform_device vlynq_low = {
+       .id = 0,
+       .name = "vlynq",
+       .dev.platform_data = &vlynq_low_data,
+       .resource = vlynq_low_res,
+       .num_resources = ARRAY_SIZE(vlynq_low_res),
+};
+
+static struct platform_device vlynq_high = {
+       .id = 1,
+       .name = "vlynq",
+       .dev.platform_data = &vlynq_high_data,
+       .resource = vlynq_high_res,
+       .num_resources = ARRAY_SIZE(vlynq_high_res),
+};
+
+
+static struct gpio_led default_leds[] = {
+       {
+               .name = "status",
+               .gpio = 8,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led dsl502t_leds[] = {
+       {
+               .name = "status",
+               .gpio = 9,
+               .active_low = 1,
+       },
+       {
+               .name = "ethernet",
+               .gpio = 7,
+               .active_low = 1,
+       },
+       {
+               .name = "usb",
+               .gpio = 12,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led dg834g_leds[] = {
+       {
+               .name = "ppp",
+               .gpio = 6,
+               .active_low = 1,
+       },
+       {
+               .name = "status",
+               .gpio = 7,
+               .active_low = 1,
+       },
+       {
+               .name = "adsl",
+               .gpio = 8,
+               .active_low = 1,
+       },
+       {
+               .name = "wifi",
+               .gpio = 12,
+               .active_low = 1,
+       },
+       {
+               .name = "power",
+               .gpio = 14,
+               .active_low = 1,
+               .default_trigger = "default-on",
+       },
+};
+
+static struct gpio_led fb_sl_leds[] = {
+       {
+               .name = "1",
+               .gpio = 7,
+       },
+       {
+               .name = "2",
+               .gpio = 13,
+               .active_low = 1,
+       },
+       {
+               .name = "3",
+               .gpio = 10,
+               .active_low = 1,
+       },
+       {
+               .name = "4",
+               .gpio = 12,
+               .active_low = 1,
+       },
+       {
+               .name = "5",
+               .gpio = 9,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led fb_fon_leds[] = {
+       {
+               .name = "1",
+               .gpio = 8,
+       },
+       {
+               .name = "2",
+               .gpio = 3,
+               .active_low = 1,
+       },
+       {
+               .name = "3",
+               .gpio = 5,
+       },
+       {
+               .name = "4",
+               .gpio = 4,
+               .active_low = 1,
+       },
+       {
+               .name = "5",
+               .gpio = 11,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led_platform_data ar7_led_data;
+
+static struct platform_device ar7_gpio_leds = {
+       .name = "leds-gpio",
+       .id = -1,
+       .dev = {
+               .platform_data = &ar7_led_data,
+       }
+};
+
+static struct platform_device ar7_udc = {
+       .id = -1,
+       .name = "ar7_udc",
+       .resource = usb_res,
+       .num_resources = ARRAY_SIZE(usb_res),
+};
+
+static inline unsigned char char2hex(char h)
+{
+       switch (h) {
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+               return h - '0';
+       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+               return h - 'A' + 10;
+       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+               return h - 'a' + 10;
+       default:
+               return 0;
+       }
+}
+
+static void cpmac_get_mac(int instance, unsigned char *dev_addr)
+{
+       int i;
+       char name[5], default_mac[ETH_ALEN], *mac;
+
+       mac = NULL;
+       sprintf(name, "mac%c", 'a' + instance);
+       mac = prom_getenv(name);
+       if (!mac) {
+               sprintf(name, "mac%c", 'a');
+               mac = prom_getenv(name);
+       }
+       if (!mac) {
+               random_ether_addr(default_mac);
+               mac = default_mac;
+       }
+       for (i = 0; i < 6; i++)
+               dev_addr[i] = (char2hex(mac[i * 3]) << 4) +
+                       char2hex(mac[i * 3 + 1]);
+}
+
+static void __init detect_leds(void)
+{
+       char *prid, *usb_prod;
+
+       /* Default LEDs */
+       ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+       ar7_led_data.leds = default_leds;
+
+       /* FIXME: the whole thing is unreliable */
+       prid = prom_getenv("ProductID");
+       usb_prod = prom_getenv("usb_prod");
+
+       /* If we can't get the product id from PROM, use the default LEDs */
+       if (!prid)
+               return;
+
+       if (strstr(prid, "Fritz_Box_FON")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+               ar7_led_data.leds = fb_fon_leds;
+       } else if (strstr(prid, "Fritz_Box_")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+               ar7_led_data.leds = fb_sl_leds;
+       } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
+               && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+               ar7_led_data.leds = dsl502t_leds;
+       } else if (strstr(prid, "DG834")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+               ar7_led_data.leds = dg834g_leds;
+       }
+}
+
+static int __init ar7_register_devices(void)
+{
+       int res;
+       static struct uart_port uart_port[2];
+
+       memset(uart_port, 0, sizeof(struct uart_port) * 2);
+
+       uart_port[0].type = PORT_16550A;
+       uart_port[0].line = 0;
+       uart_port[0].irq = AR7_IRQ_UART0;
+       uart_port[0].uartclk = ar7_bus_freq() / 2;
+       uart_port[0].iotype = UPIO_MEM32;
+       uart_port[0].mapbase = AR7_REGS_UART0;
+       uart_port[0].membase = ioremap(uart_port[0].mapbase, 256);
+       uart_port[0].regshift = 2;
+       res = early_serial_setup(&uart_port[0]);
+       if (res)
+               return res;
+
+
+       /* Only TNETD73xx have a second serial port */
+       if (ar7_has_second_uart()) {
+               uart_port[1].type = PORT_16550A;
+               uart_port[1].line = 1;
+               uart_port[1].irq = AR7_IRQ_UART1;
+               uart_port[1].uartclk = ar7_bus_freq() / 2;
+               uart_port[1].iotype = UPIO_MEM32;
+               uart_port[1].mapbase = UR8_REGS_UART1;
+               uart_port[1].membase = ioremap(uart_port[1].mapbase, 256);
+               uart_port[1].regshift = 2;
+               res = early_serial_setup(&uart_port[1]);
+               if (res)
+                       return res;
+       }
+
+       res = platform_device_register(&physmap_flash);
+       if (res)
+               return res;
+
+       ar7_device_disable(vlynq_low_data.reset_bit);
+       res = platform_device_register(&vlynq_low);
+       if (res)
+               return res;
+
+       if (ar7_has_high_vlynq()) {
+               ar7_device_disable(vlynq_high_data.reset_bit);
+               res = platform_device_register(&vlynq_high);
+               if (res)
+                       return res;
+       }
+
+       if (ar7_has_high_cpmac()) {
+               cpmac_get_mac(1, cpmac_high_data.dev_addr);
+               res = platform_device_register(&cpmac_high);
+               if (res)
+                       return res;
+       } else {
+               cpmac_low_data.phy_mask = 0xffffffff;
+       }
+
+       cpmac_get_mac(0, cpmac_low_data.dev_addr);
+       res = platform_device_register(&cpmac_low);
+       if (res)
+               return res;
+
+       detect_leds();
+       res = platform_device_register(&ar7_gpio_leds);
+       if (res)
+               return res;
+
+       res = platform_device_register(&ar7_udc);
+
+       return res;
+}
+arch_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644 (file)
index 0000000..a320bce
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+       char *name;
+       char *value;
+};
+
+static struct env_var adam2_env[MAX_ENTRY];
+
+char *prom_getenv(const char *name)
+{
+       int i;
+       for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
+               if (!strcmp(name, adam2_env[i].name))
+                       return adam2_env[i].value;
+
+       return NULL;
+}
+EXPORT_SYMBOL(prom_getenv);
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+static void  __init ar7_init_cmdline(int argc, char *argv[])
+{
+       char *cp;
+       int actr;
+
+       actr = 1; /* Always ignore argv[0] */
+
+       cp = &(arcs_cmdline[0]);
+       while (actr < argc) {
+               strcpy(cp, argv[actr]);
+               cp += strlen(argv[actr]);
+               *cp++ = ' ';
+               actr++;
+       }
+       if (cp != &(arcs_cmdline[0])) {
+               /* get rid of trailing space */
+               --cp;
+               *cp = '\0';
+       }
+}
+
+struct psbl_rec {
+       u32 psbl_size;
+       u32 env_base;
+       u32 env_size;
+       u32 ffs_base;
+       u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+       u8 num;
+       u8 ctrl;
+       u16 csum;
+       u8 len;
+       char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+       u8 num;
+       char *value;
+};
+
+static struct psp_var_map_entry psp_var_map[] = {
+       { 1, "cpufrequency" },
+       { 2, "memsize" },
+       { 3, "flashsize" },
+       { 4, "modetty0" },
+       { 5, "modetty1" },
+       { 8, "maca" },
+       { 9, "macb" },
+       { 28, "sysfrequency" },
+       { 38, "mipsfrequency" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE  4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+       int i;
+
+       for (i = 0; i < sizeof(psp_var_map); i++)
+               if (psp_var_map[i].num == num)
+                       return psp_var_map[i].value;
+
+       return NULL;
+}
+
+static void __init add_adam2_var(char *name, char *value)
+{
+       int i;
+       for (i = 0; i < MAX_ENTRY; i++) {
+               if (!adam2_env[i].name) {
+                       adam2_env[i].name = name;
+                       adam2_env[i].value = value;
+                       return;
+               } else if (!strcmp(adam2_env[i].name, name)) {
+                       adam2_env[i].value = value;
+                       return;
+               }
+       }
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+       int i, n;
+       char *name, *value;
+       struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+       memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+       i = 1;
+       n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+       while (i < n) {
+               if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+                       break;
+               value = chunks[i].data;
+               if (chunks[i].num) {
+                       name = lookup_psp_var_map(chunks[i].num);
+               } else {
+                       name = value;
+                       value += strlen(name) + 1;
+               }
+               if (name)
+                       add_adam2_var(name, value);
+               i += chunks[i].len;
+       }
+       return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+       int i;
+       struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+       void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+       if (strcmp(psp_env, psp_env_version) == 0) {
+               parse_psp_env(psp_env);
+       } else {
+               for (i = 0; i < MAX_ENTRY; i++, env++)
+                       if (env->name)
+                               add_adam2_var(env->name, env->value);
+       }
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char console_string[40];
+       int baud = 0;
+       char parity = '\0', bits = '\0', flow = '\0';
+       char *s, *p;
+
+       if (strstr(prom_getcmdline(), "console="))
+               return;
+
+#ifdef CONFIG_KGDB
+       if (!strstr(prom_getcmdline(), "nokgdb")) {
+               strcat(prom_getcmdline(), " console=kgdb");
+               kgdb_enabled = 1;
+               return;
+       }
+#endif
+
+       s = prom_getenv("modetty0");
+       if (s) {
+               baud = simple_strtoul(s, &p, 10);
+               s = p;
+               if (*s == ',')
+                       s++;
+               if (*s)
+                       parity = *s++;
+               if (*s == ',')
+                       s++;
+               if (*s)
+                       bits = *s++;
+               if (*s == ',')
+                       s++;
+               if (*s == 'h')
+                       flow = 'r';
+       }
+
+       if (baud == 0)
+               baud = 38400;
+       if (parity != 'n' && parity != 'o' && parity != 'e')
+               parity = 'n';
+       if (bits != '7' && bits != '8')
+               bits = '8';
+
+       if (flow == 'r')
+               sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+                       parity, bits, flow);
+       else
+               sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+                       bits);
+       strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+       ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+       ar7_init_env((struct env_var *)fw_arg2);
+       console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+       return readl((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+       writel(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+       while (!(serial_in(UART_LSR) & UART_LSR_DR))
+               ;
+       return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+       while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+               ;
+       serial_out(UART_TX, c);
+       return 1;
+}
+
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644 (file)
index 0000000..6ebb5f1
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/time.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command)
+{
+       u32 *softres_reg = ioremap(AR7_REGS_RESET +
+                                         AR7_RESET_SOFTWARE, 1);
+       writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+       while (1)
+               ;
+}
+
+static void ar7_machine_power_off(void)
+{
+       u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
+       u32 power_state = readl(power_reg) | (3 << 30);
+       writel(power_state, power_reg);
+       ar7_machine_halt();
+}
+
+const char *get_system_type(void)
+{
+       u16 chip_id = ar7_chip_id();
+       switch (chip_id) {
+       case AR7_CHIP_7300:
+               return "TI AR7 (TNETD7300)";
+       case AR7_CHIP_7100:
+               return "TI AR7 (TNETD7100)";
+       case AR7_CHIP_7200:
+               return "TI AR7 (TNETD7200)";
+       default:
+               return "TI AR7 (Unknown)";
+       }
+}
+
+static int __init ar7_init_console(void)
+{
+       return 0;
+}
+console_initcall(ar7_init_console);
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+
+void __init plat_mem_setup(void)
+{
+       unsigned long io_base;
+
+       _machine_restart = ar7_machine_restart;
+       _machine_halt = ar7_machine_halt;
+       pm_power_off = ar7_machine_power_off;
+       panic_timeout = 3;
+
+       io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
+       if (!io_base)
+               panic("Can't remap IO base!\n");
+       set_io_port_base(io_base);
+
+       prom_meminit();
+
+       printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
+                                       get_system_type(),
+               ar7_chip_id(), ar7_chip_rev());
+}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644 (file)
index 0000000..a1fba89
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+       mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
index 7c0528b0e34ccabd1668bcd5c3b4436076f00e76..d6903c3f3d513c0cd0990138aaada2445d27562b 100644 (file)
@@ -14,9 +14,5 @@ obj-y += dma-octeon.o flash_setup.o
 obj-y += octeon-memcpy.o
 
 obj-$(CONFIG_SMP)                     += smp.o
-obj-$(CONFIG_PCI)                     += pci-common.o
-obj-$(CONFIG_PCI)                     += pci.o
-obj-$(CONFIG_PCI)                     += pcie.o
-obj-$(CONFIG_PCI_MSI)                 += msi.o
 
 EXTRA_CFLAGS += -Werror
index 627c162a615980df13bffda63dc8517d66ac5695..4b92bfc662db0b629e253a92336a9396b41555ac 100644 (file)
@@ -29,7 +29,7 @@
 #include <dma-coherence.h>
 
 #ifdef CONFIG_PCI
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 #endif
 
 #define BAR2_PCI_ADDRESS 0x8000000000ul
diff --git a/arch/mips/cavium-octeon/pci-common.c b/arch/mips/cavium-octeon/pci-common.c
deleted file mode 100644 (file)
index cd029f8..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005-2007 Cavium Networks
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include "pci-common.h"
-
-typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
-enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
-
-/**
- * Map a PCI device to the appropriate interrupt line
- *
- * @param dev    The Linux PCI device structure for the device to map
- * @param slot   The slot number for this device on __BUS 0__. Linux
- *               enumerates through all the bridges and figures out the
- *               slot on Bus 0 where this device eventually hooks to.
- * @param pin    The PCI interrupt pin read from the device, then swizzled
- *               as it goes through each bridge.
- * @return Interrupt number for the device
- */
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-       if (octeon_pcibios_map_irq)
-               return octeon_pcibios_map_irq(dev, slot, pin);
-       else
-               panic("octeon_pcibios_map_irq doesn't point to a "
-                     "pcibios_map_irq() function");
-}
-
-
-/**
- * Called to perform platform specific PCI setup
- *
- * @param dev
- * @return
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       uint16_t config;
-       uint32_t dconfig;
-       int pos;
-       /*
-        * Force the Cache line setting to 64 bytes. The standard
-        * Linux bus scan doesn't seem to set it. Octeon really has
-        * 128 byte lines, but Intel bridges get really upset if you
-        * try and set values above 64 bytes. Value is specified in
-        * 32bit words.
-        */
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
-       /* Set latency timers for all devices */
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
-
-       /* Enable reporting System errors and parity errors on all devices */
-       /* Enable parity checking and error reporting */
-       pci_read_config_word(dev, PCI_COMMAND, &config);
-       config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-       pci_write_config_word(dev, PCI_COMMAND, config);
-
-       if (dev->subordinate) {
-               /* Set latency timers on sub bridges */
-               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
-               /* More bridge error detection */
-               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
-               config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
-               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
-       }
-
-       /* Enable the PCIe normal error reporting */
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (pos) {
-               /* Update Device Control */
-               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
-               /* Correctable Error Reporting */
-               config |= PCI_EXP_DEVCTL_CERE;
-               /* Non-Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_NFERE;
-               /* Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_FERE;
-               /* Unsupported Request */
-               config |= PCI_EXP_DEVCTL_URRE;
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
-       }
-
-       /* Find the Advanced Error Reporting capability */
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (pos) {
-               /* Clear Uncorrectable Error Status */
-               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
-                                     &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
-                                      dconfig);
-               /* Enable reporting of all uncorrectable errors */
-               /* Uncorrectable Error Mask - turned on bits disable errors */
-               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
-               /*
-                * Leave severity at HW default. This only controls if
-                * errors are reported as uncorrectable or
-                * correctable, not if the error is reported.
-                */
-               /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
-               /* Clear Correctable Error Status */
-               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
-               /* Enable reporting of all correctable errors */
-               /* Correctable Error Mask - turned on bits disable errors */
-               pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
-               /* Advanced Error Capabilities */
-               pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
-               /* ECRC Generation Enable */
-               if (config & PCI_ERR_CAP_ECRC_GENC)
-                       config |= PCI_ERR_CAP_ECRC_GENE;
-               /* ECRC Check Enable */
-               if (config & PCI_ERR_CAP_ECRC_CHKC)
-                       config |= PCI_ERR_CAP_ECRC_CHKE;
-               pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
-               /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
-               /* Report all errors to the root complex */
-               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
-                                      PCI_ERR_ROOT_CMD_COR_EN |
-                                      PCI_ERR_ROOT_CMD_NONFATAL_EN |
-                                      PCI_ERR_ROOT_CMD_FATAL_EN);
-               /* Clear the Root status register */
-               pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
-       }
-
-       return 0;
-}
index 9e143989c7b8b889dcabc900fa86058d9c1517b2..4eaec8b46e0ce16280b70f261e1199fcf0959ee6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt buttons platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0720e4fae3112c41fb3c52cff618ad22bb5d4134..0f1cd90f37edcbcfcfa37447831045777374fbc5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LCD platform device.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 1c6ebd468b07ff3f440f5fd2401c7f78b4d1c3f6..d3ce6fa1dc74cec54c66d6e973ae03eeb429e2e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LED platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2b088ef3839a4b69d275b3b2e30eedc31051198c..691d620b6766a078b51c051ceeb4c57af4e76033 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt MTD device.
  *
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e70794b8bcba897dc818a196c44581e4b6cac7ab..3ab39898b4e46b3a3b7c5615b8b5fe85b5e8473b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 53b8d0d6da90824ccc2d4447526f205bf36ed506..7cb51f57275e584bdf4d7ba61762e004023f01d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 4a570e7145fe65fc0d551f60600feb916541bc3c..0162f9edc693c57bcf35c614be66289eb3db7f90 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt time initialization.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
new file mode 100644 (file)
index 0000000..dad5b67
--- /dev/null
@@ -0,0 +1,1182 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Wed Jun 24 14:08:59 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+CONFIG_AR7=y
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_KEXEC=y
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_PROBE_INITRD_HEADER=y
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+CONFIG_DEFAULT_WESTWOOD=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="westwood"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_ATM is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+# CONFIG_AX25 is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_CPMAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AR7_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_SERIAL=y
+CONFIG_SSB_DRIVER_MIPS=y
+CONFIG_SSB_EMBEDDED=y
+CONFIG_SSB_DRIVER_EXTIF=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_VLYNQ=y
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index 5ec1c2ffd3a5e24b8c588156288c26195ebfb84e..6f9d0858f596e1ad53445c051a057b0cad348b22 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of WRPPMC UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h
new file mode 100644 (file)
index 0000000..c3dc1a6
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Amon support
+ */
+
+int amon_cpu_avail(int);
+void amon_cpu_start(int, unsigned long, unsigned long,
+                   unsigned long, unsigned long);
index ba1702e86931bff400708ee1c6d23089c9e705ed..3af0b8fb3b8c23500f9cd7476f769ae36cc05cfc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DS1287 timer functions.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d58f128aa747be974ac10ffd5fb1749d3292f505..7990694cda221dbd9f0da1c2b11b4f8e77688680 100644 (file)
@@ -316,9 +316,13 @@ extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
 extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
 
+#ifndef ELF_CORE_COPY_REGS
 #define ELF_CORE_COPY_REGS(elf_regs, regs)                     \
        elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
+#endif
+#ifndef ELF_CORE_COPY_TASK_REGS
 #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+#endif
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)                  \
        dump_task_fpu(tsk, elf_fpregs)
 
index d74a8a4ca861a9d5b2de96e995e5e7b1302b26d5..36fd969d64d6fc83a1b37daf5a22fe3b46c504b1 100644 (file)
 #define GCMP_CCB_DINTGROUP_OFS         0x0030          /* DINT Group Participate */
 #define GCMP_CCB_DBGGROUP_OFS          0x0100          /* DebugBreak Group */
 
+extern int __init gcmp_probe(unsigned long, unsigned long);
+
 #endif /* _ASM_GCMPREGS_H */
index 954807d9d66ae82233cc48362c0ebeb7ce144eff..10292e37c1f714b56d2b4eb854f180cc8f5c0975 100644 (file)
 #define GIC_TRIG_EDGE                  1
 #define GIC_TRIG_LEVEL                 0
 
+#if CONFIG_SMP
+#define GIC_NUM_INTRS                  (24 + NR_CPUS * 2)
+#else
 #define GIC_NUM_INTRS                  32
+#endif
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)            (*(volatile unsigned int *) (addr))
@@ -483,5 +487,7 @@ extern void gic_init(unsigned long gic_base_addr,
 
 extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
+extern unsigned int plat_ipi_call_int_xlate(unsigned int);
+extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 
 #endif /* _ASM_GICREGS_H */
index f9a7c3ac2e6677445e25a47df7248b1fd2773f19..250a2407b599c32b51b71d803bce7c4694666854 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Galileo/Marvell GT641xx IRQ definitions.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
new file mode 100644 (file)
index 0000000..de71694
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <asm/addrspace.h>
+
+#define AR7_SDRAM_BASE 0x14000000
+
+#define AR7_REGS_BASE  0x08610000
+
+#define AR7_REGS_MAC0  (AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO  (AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80)
+#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20)
+#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB   (AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0        (AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL   (AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1        (AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO  (AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ   (AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1  (AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT   (AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT   (AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL  0x0
+#define AR7_RESET_SOFTWARE     0x4
+#define AR7_RESET_STATUS       0x8
+
+#define AR7_RESET_BIT_CPMAC_LO 17
+#define AR7_RESET_BIT_CPMAC_HI 21
+#define AR7_RESET_BIT_MDIO     22
+#define AR7_RESET_BIT_EPHY     26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT 0x0
+#define AR7_GPIO_OUTPUT        0x4
+#define AR7_GPIO_DIR   0x8
+#define AR7_GPIO_ENABLE        0xc
+
+#define AR7_CHIP_7100  0x18
+#define AR7_CHIP_7200  0x2b
+#define AR7_CHIP_7300  0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0  15
+#define AR7_IRQ_UART1  16
+
+/* Clocks */
+#define AR7_AFE_CLOCK  35328000
+#define AR7_REF_CLOCK  25000000
+#define AR7_XTAL_CLOCK 24000000
+
+struct plat_cpmac_data {
+       int reset_bit;
+       int power_bit;
+       u32 phy_mask;
+       char dev_addr[6];
+};
+
+struct plat_dsl_data {
+       int reset_bit_dsl;
+       int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+       return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+       return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+       return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+       return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+       return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+       return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+       u16 chip_id = ar7_chip_id();
+       switch (chip_id) {
+       case AR7_CHIP_7100:
+       case AR7_CHIP_7200:
+               return 0;
+       case AR7_CHIP_7300:
+               return 1;
+       default:
+               return -ENXIO;
+       }
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+       void *reset_reg =
+               (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+       writel(readl(reset_reg) | (1 << bit), reset_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+       void *reset_reg =
+               (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+       writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+       ar7_device_disable(bit);
+       ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+       void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+       writel(readl(power_reg) | (1 << bit), power_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+       void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+       writel(readl(power_reg) & ~(1 << bit), power_reg);
+       msleep(20);
+}
+
+#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
new file mode 100644 (file)
index 0000000..cbe9c4f
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+       void __iomem *gpio_in =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+       return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       void __iomem *gpio_out =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+       unsigned tmp;
+
+       tmp = readl(gpio_out) & ~(1 << gpio);
+       if (value)
+               tmp |= 1 << gpio;
+       writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+       void __iomem *gpio_dir =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+       return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+       void __iomem *gpio_dir =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       gpio_set_value(gpio, value);
+       writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+       return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+       void __iomem *gpio_en =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+       writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+       return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+       void __iomem *gpio_en =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+       writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+       return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
new file mode 100644 (file)
index 0000000..39e9757
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS        256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
new file mode 100644 (file)
index 0000000..088f61f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006, 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
new file mode 100644 (file)
index 0000000..ac28f27
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET            0x94000000UL
+#define PHYS_OFFSET            0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
new file mode 100644 (file)
index 0000000..f4862b5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR    0
+#define R4600_V1_HIT_CACHEOP_WAR       0
+#define R4600_V2_HIT_CACHEOP_WAR       0
+#define R5432_CP0_INTERRUPT_WAR                0
+#define BCM1250_M3_WAR                 0
+#define SIBYTE_1956_WAR                        0
+#define MIPS4K_ICACHE_REFILL_WAR       0
+#define MIPS_CACHE_SYNC_WAR            0
+#define TX49XX_ICACHE_INDEX_INV_WAR    0
+#define RM9000_CDEX_SMP_WAR            0
+#define ICACHE_REFILLS_WORKAROUND_WAR  0
+#define R10000_LLSC_WAR                        0
+#define MIPS34K_MISSED_ITLB_WAR                0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
index 57c8c9ac585162b6a16a32d912d7d438d0a772be..9da9acf5dcba4754642404fc05380946aa4a7ff8 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 1997 Cobalt Microserver
  * Copyright (C) 1997, 2003 Ralf Baechle
  * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv)
- * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org>
  */
 #ifndef _ASM_COBALT_IRQ_H
 #define _ASM_COBALT_IRQ_H
index ae9c5523c7effae9679ce4c3b79a290121d58fd0..f8afec3f294330ea4322211f7b640f4146aabad8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 52%
rename from arch/mips/cavium-octeon/pci-common.h
rename to arch/mips/include/asm/octeon/pci-octeon.h
index 74ae79991e456410f35424b09b4d180feceab6cc..6ac5d3e3398eaff20144dafc5190910eb8f4ef13 100644 (file)
@@ -3,23 +3,29 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
-#ifndef __OCTEON_PCI_COMMON_H__
-#define __OCTEON_PCI_COMMON_H__
+
+#ifndef __PCI_OCTEON_H__
+#define __PCI_OCTEON_H__
 
 #include <linux/pci.h>
 
 /* Some PCI cards require delays when accessing config space. */
 #define PCI_CONFIG_SPACE_DELAY 10000
 
-/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the
-   Octeon specific version pointed to by this variable. This function needs to
-   change for PCI or PCIe based hosts */
-extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
+/*
+ * pcibios_map_irq() is defined inside pci-octeon.c. All it does is
+ * call the Octeon specific version pointed to by this variable. This
+ * function needs to change for PCI or PCIe based hosts.
+ */
+extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+                                    u8 slot, u8 pin);
 
-/* The following defines are only used when octeon_dma_bar_type =
-   OCTEON_DMA_BAR_TYPE_BIG */
+/*
+ * The following defines are used when octeon_dma_bar_type =
+ * OCTEON_DMA_BAR_TYPE_BIG
+ */
 #define OCTEON_PCI_BAR1_HOLE_BITS 5
 #define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3))
 
@@ -30,9 +36,9 @@ enum octeon_dma_bar_type {
        OCTEON_DMA_BAR_TYPE_PCIE
 };
 
-/**
- * This is a variable to tell the DMA mapping system in dma-octeon.c
- * how to map PCI DMA addresses.
+/*
+ * This tells the DMA mapping system in dma-octeon.c how to map PCI
+ * DMA addresses.
  */
 extern enum octeon_dma_bar_type octeon_dma_bar_type;
 
index dc0eaa7312816112a006cb6af0a0b0b6f5022979..96a14a426a7c39f7e2d4ccf5bef49a7be5c425f7 100644 (file)
@@ -165,7 +165,14 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)         ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
+#define pfn_valid(pfn)                                                 \
+({                                                                     \
+       unsigned long __pfn = (pfn);                                    \
+       /* avoid <linux/bootmem.h> include hell */                      \
+       extern unsigned long min_low_pfn;                               \
+                                                                       \
+       __pfn >= min_low_pfn && __pfn < max_mapnr;                      \
+})
 
 #elif defined(CONFIG_SPARSEMEM)
 
index 634b55d7e7f6d1ada10dfa02175c11a81790f78d..910e71a12466de2f1fb3f1fab82c6203ef062e63 100644 (file)
@@ -69,7 +69,7 @@
 
 #endif
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
 
 #define EF_R0                   0
 #define EF_R1                   1
index 99993c0d6c12bb3ea50996991c8072ed254d7155..97c2f81b4b43af66d766778ea2c17dcca6d8303b 100644 (file)
@@ -38,7 +38,11 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 }
 #define __arch_swab32 __arch_swab32
 
-#ifdef CONFIG_CPU_MIPS64_R2
+/*
+ * Having already checked for CONFIG_CPU_MIPSR2, enable the
+ * optimized version for 64-bit kernel on r2 CPUs.
+ */
+#ifdef CONFIG_64BIT
 static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
 {
        __asm__(
@@ -50,6 +54,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
        return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* CONFIG_CPU_MIPS64_R2 */
+#endif /* CONFIG_64BIT */
 #endif /* CONFIG_CPU_MIPSR2 */
 #endif /* _ASM_SWAB_H */
index 40005010827cb4f72c1734778a520a74c7958153..b70c49fdda26afb0b66b6f74f241d570da09ad09 100644 (file)
 #define __NR_inotify_init1             (__NR_Linux + 329)
 #define __NR_preadv                    (__NR_Linux + 330)
 #define __NR_pwritev                   (__NR_Linux + 331)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 332)
+#define __NR_perf_counter_open         (__NR_Linux + 333)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            331
+#define __NR_Linux_syscalls            333
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                331
+#define __NR_O32_Linux_syscalls                333
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_inotify_init1             (__NR_Linux + 288)
 #define __NR_preadv                    (__NR_Linux + 289)
 #define __NR_pwritev                   (__NR_Linux + 290)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 291)
+#define __NR_perf_counter_open         (__NR_Linux + 292)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            290
+#define __NR_Linux_syscalls            292
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         290
+#define __NR_64_Linux_syscalls         292
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_inotify_init1             (__NR_Linux + 292)
 #define __NR_preadv                    (__NR_Linux + 293)
 #define __NR_pwritev                   (__NR_Linux + 294)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 295)
+#define __NR_perf_counter_open         (__NR_Linux + 296)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            294
+#define __NR_Linux_syscalls            296
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                294
+#define __NR_N32_Linux_syscalls                296
 
 #ifdef __KERNEL__
 
index e0ee05a3dfcccfd3c1bc13e1d843793bfb78f8ba..fcc6569414faaf2fda683289894fa78a32e8f985 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  capcella.h, Include file for ZAO Networks Capcella.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0bcdd3a5c2560b6817174af92d1e1dbfe2a9cd07..6a90bc1d916b4aa58ddc57ae6edd8ee40ae9b4ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series General-purpose I/O Unit.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2009  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,7 +41,8 @@ typedef enum {
        IRQ_SIGNAL_HOLD,
 } irq_signal_t;
 
-extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+                                  irq_signal_t signal);
 
 typedef enum {
        IRQ_LEVEL_LOW,
@@ -50,23 +51,6 @@ typedef enum {
 
 extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
 
-typedef enum {
-       GPIO_DATA_LOW,
-       GPIO_DATA_HIGH,
-       GPIO_DATA_INVAL,
-} gpio_data_t;
-
-extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
-extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
-
-typedef enum {
-       GPIO_INPUT,
-       GPIO_OUTPUT,
-       GPIO_OUTPUT_DISABLE,
-} gpio_direction_t;
-
-extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
-
 typedef enum {
        GPIO_PULL_DOWN,
        GPIO_PULL_UP,
index d315dfbc08f2c269fcc4b0c1ebfde5b0b38c5292..b07f7321751dd577004e4e3025acc272a09d31f2 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
index 1d67df843dc32d93f9feada3ab2a3d0df5fe0454..130d09d8c8cbbc285a44fca21063569a4004454b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mpc30x.h, Include file for Victor MP-C303/304.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 6fc01ce1977706fbb09325299342d55d7b073358..c231a3d6cfd8fb5ccb01b1da7cdb72238c1a84b3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series PCI Control Unit.
  *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index da9f6e3734099b31198cf31dd77b6070e158fdbb..ca806bc4ddc8a8857247e3985672a8d343c49a0f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2005-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index dc981b4be0a404bd0ff3090baccbcd22be8d20ed..c78e8243b447e3b4fde3d697d58be19d125a6c45 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  tb0219.h, Include file for TANBAC TB0219.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  Modified for TANBAC TB0219:
  *  Copyright (C) 2003 Megasolution Inc.  <matsu@megasolution.jp>
index de527dcfa5f31b0301430c170aa36cc0afba32bf..36f5f798e4169cb4a05db452960fcb97bbffa9be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  tb0226.h, Include file for TANBAC TB0226.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 22be64971cc69202823ddb79ff83f32500f1a7da..7b96a43b72ba5e09351f48e21a7d7d01006d1624 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
index e1333d7319e275a065546490baa8401b87c9bf47..ff448233dab55737ca2ba1aa54edfa252263b924 100644 (file)
@@ -53,6 +53,23 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
 
 #include <asm/processor.h>
+
+/*
+ * When this file is selected, we are definitely running a 64bit kernel.
+ * So using the right regs define in asm/reg.h
+ */
+#define WANT_COMPAT_REG_H
+
+/* These MUST be defined before elf.h gets included */
+extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
+#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
+#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)                           \
+({                                                                     \
+       int __res = 1;                                                  \
+       elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));             \
+       __res;                                                          \
+})
+
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -110,9 +127,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
        value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-#undef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-
 void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
        int i;
index 1ada45ea07003d426cf591b2d639d45ffda0c53b..6996da4d74a276ed1d61cf07459fb7ac82dfd7db 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DS1287 clockevent driver
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e9b787feedcb7595fb763e057cfb18a06fb1ede1..92351e00ae0e2ff3f98f8d7432aebf88d659966f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  GT641xx clockevent routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index b551f48d3a076483eccd3b543f6188c4f87797df..23da108506b0a325a8c0c4f8de12d744129d2676 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DEC I/O ASIC's counter clocksource
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 39000f103f2caf250cdd26297e0c70cd33e3b201..d2072cd385922db78c5b1278622ad4d4243a4949 100644 (file)
@@ -107,9 +107,7 @@ static unsigned int gic_irq_startup(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_SET_INTR_MASK(irq, 1);
        return 0;
 }
 
@@ -120,8 +118,7 @@ static void gic_irq_ack(unsigned int irq)
 #endif
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_CLR_INTR_MASK(irq, 1);
 
        if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
                if (!gic_wedgeb2bok)
@@ -138,18 +135,14 @@ static void gic_mask_irq(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_CLR_INTR_MASK(irq, 1);
 }
 
 static void gic_unmask_irq(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_SET_INTR_MASK(irq, 1);
 }
 
 #ifdef CONFIG_SMP
@@ -254,6 +247,10 @@ static void __init gic_basic_init(void)
                if (cpu == X)
                        continue;
 
+               if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
+                                       _intrmap[i].ipiflag == 0)
+                       continue;
+
                setup_intr(_intrmap[i].intrnum,
                                _intrmap[i].cpunum,
                                _intrmap[i].pin,
index 1b81b131f43c9acff2f39b9b954651555020a06a..ebcc5f7ad9c21e6155413e826613c5dc39c58220 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  GT641xx IRQ routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0b31b9bda0486988128d39d07d52ac2c0d0ad8d8..20a86e08fd58d4bf942688fd4e4d02d1333d4a8a 100644 (file)
@@ -652,6 +652,8 @@ einval:     li      v0, -ENOSYS
        sys     sys_inotify_init1       1
        sys     sys_preadv              6       /* 4330 */
        sys     sys_pwritev             6
+       sys     sys_rt_tgsigqueueinfo   4
+       sys     sys_perf_counter_open   5
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index c647fd6e722f7acb2872ad0f01491b6f2a2637e9..b046130d4c5d57338c3aa5aac9b109eff297d412 100644 (file)
@@ -489,4 +489,6 @@ sys_call_table:
        PTR     sys_inotify_init1
        PTR     sys_preadv
        PTR     sys_pwritev                     /* 5390 */
+       PTR     sys_rt_tgsigqueueinfo
+       PTR     sys_perf_counter_open
        .size   sys_call_table,.-sys_call_table
index 93cc672f4522169977739553eeb1001ddb40bd2b..15874f9812ccc1cb3fae7d56147fc51502f10810 100644 (file)
@@ -415,4 +415,6 @@ EXPORT(sysn32_call_table)
        PTR     sys_inotify_init1
        PTR     sys_preadv
        PTR     sys_pwritev
+       PTR     compat_sys_rt_tgsigqueueinfo    /* 5295 */
+       PTR     sys_perf_counter_open
        .size   sysn32_call_table,.-sysn32_call_table
index a5598b2339dd451a4586d3dde4b30050a48c5290..781e0f1e9533ae3f36c9624b3f9554d3c90520a2 100644 (file)
@@ -535,4 +535,6 @@ sys_call_table:
        PTR     sys_inotify_init1
        PTR     compat_sys_preadv               /* 4330 */
        PTR     compat_sys_pwritev
+       PTR     compat_sys_rt_tgsigqueueinfo
+       PTR     sys_perf_counter_open
        .size   sys_call_table,.-sys_call_table
index 653be061b9ec6745c17cac05f6f5827ed2013b17..ad0ff5dc4d59bfbcdef6e967f1317b0ea2459c3a 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
-
-/*
- * Crude manipulation of the CPU masks to control which
- * which CPU's are brought online during initialisation
- *
- * Beware... this needs to be called after CPU discovery
- * but before CPU bringup
- */
-static int __init allowcpus(char *str)
-{
-       cpumask_t cpu_allow_map;
-       char buf[256];
-       int len;
-
-       cpus_clear(cpu_allow_map);
-       if (cpulist_parse(str, &cpu_allow_map) == 0) {
-               cpu_set(0, cpu_allow_map);
-               cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
-               len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map);
-               buf[len] = '\0';
-               pr_debug("Allowable CPUs: %s\n", buf);
-               return 1;
-       } else
-               return 0;
-}
-__setup("allowcpus=", allowcpus);
+#include <asm/amon.h>
+#include <asm/gic.h>
 
 static void ipi_call_function(unsigned int cpu)
 {
-       unsigned int action = 0;
-
        pr_debug("CPU%d: %s cpu %d status %08x\n",
                 smp_processor_id(), __func__, cpu, read_c0_status());
 
-       switch (cpu) {
-       case 0:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE0;
-               break;
-       case 1:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE1;
-               break;
-       case 2:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE2;
-               break;
-       case 3:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE3;
-               break;
-       }
-       gic_send_ipi(action);
+       gic_send_ipi(plat_ipi_call_int_xlate(cpu));
 }
 
 
 static void ipi_resched(unsigned int cpu)
 {
-       unsigned int action = 0;
-
        pr_debug("CPU%d: %s cpu %d status %08x\n",
                 smp_processor_id(), __func__, cpu, read_c0_status());
 
-       switch (cpu) {
-       case 0:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE0;
-               break;
-       case 1:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE1;
-               break;
-       case 2:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE2;
-               break;
-       case 3:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE3;
-               break;
-       }
-       gic_send_ipi(action);
+       gic_send_ipi(plat_ipi_resched_int_xlate(cpu));
 }
 
 /*
@@ -206,7 +150,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle)
                           (unsigned long)(gp + sizeof(struct thread_info)));
 #endif
 
-       amon_cpu_start(cpu, pc, sp, gp, a0);
+       amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
 }
 
 /*
index 9021108eb9c1af0edbf67946284ebf3dad8c5513..05dd170a83f7e379ec4e40fe37c454e2c7a4e61a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Count register synchronisation.
  *
- * All CPUs will have their count registers synchronised to the CPU0 expirelo
+ * All CPUs will have their count registers synchronised to the CPU0 next time
  * value. This can cause a small timewarp for CPU0. All other CPU's should
  * not have done anything significant (but they may have had interrupts
  * enabled briefly - prom_smp_finish() should not be responsible for enabling
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
-#include <linux/r4k-timer.h>
+#include <linux/cpumask.h>
 
+#include <asm/r4k-timer.h>
 #include <asm/atomic.h>
 #include <asm/barrier.h>
-#include <asm/cpumask.h>
 #include <asm/mipsregs.h>
 
-static atomic_t __initdata count_start_flag = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_start = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
 
 #define COUNTON        100
 #define NR_LOOPS 5
 
-void __init synchronise_count_master(void)
+void __cpuinit synchronise_count_master(void)
 {
        int i;
        unsigned long flags;
@@ -42,19 +43,20 @@ void __init synchronise_count_master(void)
        return;
 #endif
 
-       pr_info("Checking COUNT synchronization across %u CPUs: ",
-               num_online_cpus());
+       printk(KERN_INFO "Synchronize counters across %u CPUs: ",
+              num_online_cpus());
 
        local_irq_save(flags);
 
        /*
         * Notify the slaves that it's time to start
         */
+       atomic_set(&count_reference, read_c0_count());
        atomic_set(&count_start_flag, 1);
        smp_wmb();
 
-       /* Count will be initialised to expirelo for all CPU's */
-       initcount = expirelo;
+       /* Count will be initialised to current timer for all CPU's */
+       initcount = read_c0_count();
 
        /*
         * We loop a few times to get a primed instruction cache,
@@ -106,7 +108,7 @@ void __init synchronise_count_master(void)
        printk("done.\n");
 }
 
-void __init synchronise_count_slave(void)
+void __cpuinit synchronise_count_slave(void)
 {
        int i;
        unsigned long flags;
@@ -131,8 +133,8 @@ void __init synchronise_count_slave(void)
        while (!atomic_read(&count_start_flag))
                mb();
 
-       /* Count will be initialised to expirelo for all CPU's */
-       initcount = expirelo;
+       /* Count will be initialised to next expire for all CPU's */
+       initcount = atomic_read(&count_reference);
 
        ncpus = num_online_cpus();
        for (i = 0; i < NR_LOOPS; i++) {
@@ -156,4 +158,3 @@ void __init synchronise_count_slave(void)
        local_irq_restore(flags);
 }
 #undef NR_LOOPS
-#endif
index 3ca5f42e819dc3ab4a6793510216d38218b6bc72..07b9ec2c6e3d04d1194a46a66e6783f2dcf0d29b 100644 (file)
@@ -1387,7 +1387,7 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
        return len;
 
 out_einval:
-       return -EINVAL;;
+       return -EINVAL;
 }
 
 static struct device_attribute vpe_class_attributes[] = {
index 475038a141a65038ee34792a6d06395010004a93..27c807b67feaf4fc1a8f7e745462d8dd1bcc9624 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
+#include <asm/gcmpregs.h>
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
@@ -192,6 +193,8 @@ extern struct plat_smp_ops msmtc_smp_ops;
 
 void __init prom_init(void)
 {
+       int result;
+
        prom_argc = fw_arg0;
        _prom_argv = (int *) fw_arg1;
        _prom_envp = (int *) fw_arg2;
@@ -358,12 +361,21 @@ void __init prom_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
        console_config();
 #endif
+       /* Early detection of CMP support */
+       result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
+
 #ifdef CONFIG_MIPS_CMP
-       register_smp_ops(&cmp_smp_ops);
+       if (result)
+               register_smp_ops(&cmp_smp_ops);
 #endif
 #ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_CMP
+       if (!result)
+               register_smp_ops(&vsmp_smp_ops);
+#else
        register_smp_ops(&vsmp_smp_ops);
 #endif
+#endif
 #ifdef CONFIG_MIPS_MT_SMTC
        register_smp_ops(&msmtc_smp_ops);
 #endif
index b4eaf137e4a7143bf046c04303166e4d7446f7fc..a8756f82c31b9d6d06a7f5191c9d7c67fc28118c 100644 (file)
@@ -331,6 +331,21 @@ static struct irqaction irq_call = {
        .flags          = IRQF_DISABLED|IRQF_PERCPU,
        .name           = "IPI_call"
 };
+
+static int gic_resched_int_base;
+static int gic_call_int_base;
+#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
+#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
+
+unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
+{
+       return GIC_CALL_INT(cpu);
+}
+
+unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
+{
+       return GIC_RESCHED_INT(cpu);
+}
 #endif /* CONFIG_MIPS_MT_SMP */
 
 static struct irqaction i8259irq = {
@@ -370,7 +385,7 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
  * Interrupts and CPUs/Core Interrupts. The nature of the External
  * Interrupts is also defined here - polarity/trigger.
  */
-static struct gic_intr_map gic_intr_map[] = {
+static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
        { GIC_EXT_INTR(0),      X,      X,              X,              X,              0 },
        { GIC_EXT_INTR(1),      X,      X,              X,              X,              0 },
        { GIC_EXT_INTR(2),      X,      X,              X,              X,              0 },
@@ -387,21 +402,14 @@ static struct gic_intr_map gic_intr_map[] = {
        { GIC_EXT_INTR(13),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
        { GIC_EXT_INTR(14),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
        { GIC_EXT_INTR(15),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(16),     0,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(17),     0,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(18),     1,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(19),     1,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(20),     2,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(21),     2,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(22),     3,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(23),     3,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
+/* This is the end of the general interrupts now we do IPI ones */
 };
 #endif
 
 /*
  * GCMP needs to be detected before any SMP initialisation
  */
-static int __init gcmp_probe(unsigned long addr, unsigned long size)
+int __init gcmp_probe(unsigned long addr, unsigned long size)
 {
        if (gcmp_present >= 0)
                return gcmp_present;
@@ -416,28 +424,36 @@ static int __init gcmp_probe(unsigned long addr, unsigned long size)
 }
 
 #if defined(CONFIG_MIPS_MT_SMP)
+static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
+{
+       int intr = baseintr + cpu;
+       gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
+       gic_intr_map[intr].cpunum = cpu;
+       gic_intr_map[intr].pin = cpupin;
+       gic_intr_map[intr].polarity = GIC_POL_POS;
+       gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
+       gic_intr_map[intr].ipiflag = 1;
+       ipi_map[cpu] |= (1 << (cpupin + 2));
+}
+
 static void __init fill_ipi_map(void)
 {
-       int i;
+       int cpu;
 
-       for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) {
-               if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X))
-                       ipi_map[gic_intr_map[i].cpunum] |=
-                               (1 << (gic_intr_map[i].pin + 2));
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
+               fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
        }
 }
 #endif
 
 void __init arch_init_irq(void)
 {
-       int gic_present, gcmp_present;
-
        init_i8259_irqs();
 
        if (!cpu_has_veic)
                mips_cpu_irq_init();
 
-       gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
        if (gcmp_present)  {
                GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
                gic_present = 1;
@@ -514,24 +530,10 @@ void __init arch_init_irq(void)
        if (gic_present) {
                /* FIXME */
                int i;
-               struct {
-                       unsigned int resched;
-                       unsigned int call;
-               } ipiirq[] = {
-                       {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE0},
-                       {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE1
-                       }, {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE2
-                       }, {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE3
-                       }
-               };
+
+               gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
+               gic_resched_int_base = gic_call_int_base - NR_CPUS;
+
                fill_ipi_map();
                gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
                if (!gcmp_present) {
@@ -553,12 +555,15 @@ void __init arch_init_irq(void)
                printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
                write_c0_status(0x1100dc00);
                printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
-               for (i = 0; i < ARRAY_SIZE(ipiirq); i++) {
-                       setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched);
-                       setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call);
-
-                       set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq);
+               for (i = 0; i < NR_CPUS; i++) {
+                       setup_irq(MIPS_GIC_IRQ_BASE +
+                                       GIC_RESCHED_INT(i), &irq_resched);
+                       setup_irq(MIPS_GIC_IRQ_BASE +
+                                       GIC_CALL_INT(i), &irq_call);
+                       set_irq_handler(MIPS_GIC_IRQ_BASE +
+                                       GIC_RESCHED_INT(i), handle_percpu_irq);
+                       set_irq_handler(MIPS_GIC_IRQ_BASE +
+                                       GIC_CALL_INT(i), handle_percpu_irq);
                }
        } else {
                /* set up ipi interrupts */
index 42dee4da37bad5ad5d0b2932b475bf99577d9e2c..f48d60e8429017b52352e8e0b59bc18faa0e9061 100644 (file)
@@ -28,9 +28,6 @@
 #include <asm/reboot.h>
 #include <asm/mips-boards/generic.h>
 
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
 static void mips_machine_restart(char *command)
 {
        unsigned int __iomem *softres_reg =
index e8a97f59e0661e585fc40565212d0e7d74130d1f..63d8a297c58da4f85abf378fa4da6e7e2c9ed5e6 100644 (file)
@@ -52,3 +52,8 @@ obj-$(CONFIG_VICTOR_MPC30X)   += fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)     += fixup-capcella.o
 obj-$(CONFIG_WR_PPMC)          += fixup-wrppmc.o
 obj-$(CONFIG_MIKROTIK_RB532)   += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += pci-octeon.o pcie-octeon.o
+
+ifdef CONFIG_PCI_MSI
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += msi-octeon.o
+endif
index 1416bca6d1a3f8962bd23e76d34d0668c703d767..1c02f5737367aa7e75569afeb98aebcd3ebb5327 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 5911596257222dec18a807e3fdae132ac2548a50..e08f49cb6875abd65d50b7cb1cee964f816d96b7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index ed87733f679682d778b4b31a1cd62c10ffbe3f45..8084b17d44066a3f1ca658902f4b191939c91d84 100644 (file)
@@ -2,7 +2,7 @@
  *  fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
  *
  *  Copyright (C) 2003  Megasolution Inc. <matsu@megasolution.jp>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e3eedf4bf9bd088567074cd3dc12df6f28fac811..4196ccf3ea3da5e6783de7acd913f68d2fc218bc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
  *
- *  Copyright (C) 2002-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 267ab3dc3d421420cde426812bf71ce6d661acaa..2fe29db4372595d5393ab11b38c8ac3f0fff466d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 88%
rename from arch/mips/cavium-octeon/msi.c
rename to arch/mips/pci/msi-octeon.c
index 964b03b75a8f29b775ea0b19d80c1d23763230dc..03742e64765717ec3976c0eb7d7e77c8d8a283e0 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -16,8 +16,7 @@
 #include <asm/octeon/cvmx-pci-defs.h>
 #include <asm/octeon/cvmx-npei-defs.h>
 #include <asm/octeon/cvmx-pexp-defs.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 /*
  * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is
@@ -47,8 +46,8 @@ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock);
  * programming the MSI control bits [6:4] before calling
  * pci_enable_msi().
  *
- * @param dev    Device requesting MSI interrupts
- * @param desc   MSI descriptor
+ * @dev:    Device requesting MSI interrupts
+ * @desc:   MSI descriptor
  *
  * Returns 0 on success.
  */
@@ -213,14 +212,9 @@ void arch_teardown_msi_irq(unsigned int irq)
 }
 
 
-/**
+/*
  * Called by the interrupt handling code when an MSI interrupt
  * occurs.
- *
- * @param cpl
- * @param dev_id
- *
- * @return
  */
 static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
 {
@@ -256,31 +250,37 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
 }
 
 
-/**
+/*
  * Initializes the MSI interrupt handling code
- *
- * @return
  */
 int octeon_msi_initialize(void)
 {
-       int r;
        if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
-               r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+               if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
                                IRQF_SHARED,
-                               "MSI[0:63]", octeon_msi_interrupt);
+                               "MSI[0:63]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
        } else if (octeon_is_pci_host()) {
-               r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+               if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
                                IRQF_SHARED,
-                               "MSI[0:15]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[16:31]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[32:47]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[48:63]", octeon_msi_interrupt);
+                               "MSI[0:15]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[16:31]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[32:47]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[48:63]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed");
+
        }
        return 0;
 }
index 900c6b32576c3db47e301655f42b5ca4f4c69f4b..28962a7c66066140865072556c741441ee9b2fd8 100644 (file)
@@ -2,8 +2,8 @@
  *  ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/pci.h>
similarity index 78%
rename from arch/mips/cavium-octeon/pci.c
rename to arch/mips/pci/pci-octeon.c
index 67c0ff5e92f1a528a7b133c1df206001cbf7532f..9cb0c807f564bdc00ac7e0f3f4e6ee43d4c1d730 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -17,8 +17,7 @@
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-npi-defs.h>
 #include <asm/octeon/cvmx-pci-defs.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 #define USE_OCTEON_INTERNAL_ARBITER
 
@@ -54,6 +53,126 @@ union octeon_pci_address {
        } s;
 };
 
+int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+                                        u8 slot, u8 pin);
+enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
+ *               enumerates through all the bridges and figures out the
+ *               slot on Bus 0 where this device eventually hooks to.
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
+ *               as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (octeon_pcibios_map_irq)
+               return octeon_pcibios_map_irq(dev, slot, pin);
+       else
+               panic("octeon_pcibios_map_irq not set.");
+}
+
+
+/*
+ * Called to perform platform specific PCI setup
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       uint16_t config;
+       uint32_t dconfig;
+       int pos;
+       /*
+        * Force the Cache line setting to 64 bytes. The standard
+        * Linux bus scan doesn't seem to set it. Octeon really has
+        * 128 byte lines, but Intel bridges get really upset if you
+        * try and set values above 64 bytes. Value is specified in
+        * 32bit words.
+        */
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
+       /* Set latency timers for all devices */
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
+
+       /* Enable reporting System errors and parity errors on all devices */
+       /* Enable parity checking and error reporting */
+       pci_read_config_word(dev, PCI_COMMAND, &config);
+       config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       pci_write_config_word(dev, PCI_COMMAND, config);
+
+       if (dev->subordinate) {
+               /* Set latency timers on sub bridges */
+               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
+               /* More bridge error detection */
+               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
+               config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
+       }
+
+       /* Enable the PCIe normal error reporting */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (pos) {
+               /* Update Device Control */
+               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
+               /* Correctable Error Reporting */
+               config |= PCI_EXP_DEVCTL_CERE;
+               /* Non-Fatal Error Reporting */
+               config |= PCI_EXP_DEVCTL_NFERE;
+               /* Fatal Error Reporting */
+               config |= PCI_EXP_DEVCTL_FERE;
+               /* Unsupported Request */
+               config |= PCI_EXP_DEVCTL_URRE;
+               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
+       }
+
+       /* Find the Advanced Error Reporting capability */
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (pos) {
+               /* Clear Uncorrectable Error Status */
+               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                                     &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                                      dconfig);
+               /* Enable reporting of all uncorrectable errors */
+               /* Uncorrectable Error Mask - turned on bits disable errors */
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
+               /*
+                * Leave severity at HW default. This only controls if
+                * errors are reported as uncorrectable or
+                * correctable, not if the error is reported.
+                */
+               /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
+               /* Clear Correctable Error Status */
+               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
+               /* Enable reporting of all correctable errors */
+               /* Correctable Error Mask - turned on bits disable errors */
+               pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
+               /* Advanced Error Capabilities */
+               pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
+               /* ECRC Generation Enable */
+               if (config & PCI_ERR_CAP_ECRC_GENC)
+                       config |= PCI_ERR_CAP_ECRC_GENE;
+               /* ECRC Check Enable */
+               if (config & PCI_ERR_CAP_ECRC_CHKC)
+                       config |= PCI_ERR_CAP_ECRC_CHKE;
+               pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
+               /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
+               /* Report all errors to the root complex */
+               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
+                                      PCI_ERR_ROOT_CMD_COR_EN |
+                                      PCI_ERR_ROOT_CMD_NONFATAL_EN |
+                                      PCI_ERR_ROOT_CMD_FATAL_EN);
+               /* Clear the Root status register */
+               pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
+       }
+
+       return 0;
+}
+
 /**
  * Return the mapping of PCI device number to IRQ line. Each
  * character in the return string represents the interrupt
@@ -136,9 +255,8 @@ int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev,
 }
 
 
-/**
+/*
  * Read a value from configuration space
- *
  */
 static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
                              int reg, int size, u32 *val)
@@ -174,15 +292,8 @@ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
 }
 
 
-/**
+/*
  * Write a value to PCI configuration space
- *
- * @bus:
- * @devfn:
- * @reg:
- * @size:
- * @val:
- * Returns
  */
 static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
                               int reg, int size, u32 val)
@@ -251,10 +362,8 @@ static struct pci_controller octeon_pci_controller = {
 };
 
 
-/**
+/*
  * Low level initialize the Octeon PCI controller
- *
- * Returns
  */
 static void octeon_pci_initialize(void)
 {
@@ -398,7 +507,7 @@ static void octeon_pci_initialize(void)
                pci_int_arb_cfg.s.en = 1;       /* Internal arbiter enable */
                cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64);
        }
-#endif                         /* USE_OCTEON_INTERNAL_ARBITER */
+#endif /* USE_OCTEON_INTERNAL_ARBITER */
 
        /*
         * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
@@ -457,10 +566,8 @@ static void octeon_pci_initialize(void)
 }
 
 
-/**
+/*
  * Initialize the Octeon PCI controller
- *
- * Returns
  */
 static int __init octeon_pci_setup(void)
 {
index d1e049b55f34f07f2035f830fd82d7324f8fbe41..56525711f8b75deb270b6c6b7f32db0b38289029 100644 (file)
@@ -2,8 +2,8 @@
  *  pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *  Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/init.h>
index 8a35e32b8376f734f61da3a74ec5b8726f5f1e48..6b1ae2eb1c065bc3b5b547ec6ff6258e14f05926 100644 (file)
@@ -2,8 +2,8 @@
  *  pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 98%
rename from arch/mips/cavium-octeon/pcie.c
rename to arch/mips/pci/pcie-octeon.c
index 49d14081b3b5aa2585911f812732a04cf61a7f12..75262247f3e482d445c677dcf6d4d2590b596727 100644 (file)
@@ -18,8 +18,7 @@
 #include <asm/octeon/cvmx-pescx-defs.h>
 #include <asm/octeon/cvmx-pexp-defs.h>
 #include <asm/octeon/cvmx-helper-errata.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 union cvmx_pcie_address {
        uint64_t u64;
@@ -976,13 +975,13 @@ static int cvmx_pcie_rc_initialize(int pcie_port)
 /**
  * Map a PCI device to the appropriate interrupt line
  *
- * @param dev    The Linux PCI device structure for the device to map
- * @param slot   The slot number for this device on __BUS 0__. Linux
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
  *               enumerates through all the bridges and figures out the
  *               slot on Bus 0 where this device eventually hooks to.
- * @param pin    The PCI interrupt pin read from the device, then swizzled
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
  *               as it goes through each bridge.
- * @return Interrupt number for the device
+ * Returns Interrupt number for the device
  */
 int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
                                       u8 slot, u8 pin)
@@ -1025,12 +1024,12 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
 /**
  * Read a value from configuration space
  *
- * @param bus
- * @param devfn
- * @param reg
- * @param size
- * @param val
- * @return
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
  */
 static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
                                          unsigned int devfn, int reg, int size,
@@ -1156,12 +1155,12 @@ static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn,
 /**
  * Write a value to PCI configuration space
  *
- * @param bus
- * @param devfn
- * @param reg
- * @param size
- * @param val
- * @return
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
  */
 static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus,
                                           unsigned int devfn, int reg,
@@ -1254,7 +1253,7 @@ static struct pci_controller octeon_pcie1_controller = {
 /**
  * Initialize the Octeon PCIe controllers
  *
- * @return
+ * Returns
  */
 static int __init octeon_pcie_setup(void)
 {
index 6d9bab8905877fe1b7b0324a4670bd424584b706..719f4a5b984458103ac95de630b0c6d3dfb9d7ae 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d77c330a0d592b49b700597529ec48a0f03e2f4a..6346c59c9f9d96d361396944c4e40e4fb20052e6 100644 (file)
@@ -2,8 +2,8 @@
  *  bcu.c, Bus Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/kernel.h>
index ad0e8e3409d9099d3d6450a31533c1204574b152..8ba7d04a5ec58e4b05cf1d792eb766698b66e850 100644 (file)
@@ -2,8 +2,8 @@
  *  cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copuright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copuright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
index 2b272f1496fe97e55b57975e1850ad32e2ee26e0..22cc6f2100a1acba6d15f983804c3ee46660bdaa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series GIU platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 3f23d9fda662621e2879ff37a2d1ecbef24cf1a5..6d39e222b170b1db7250cb990c7726f875127305 100644 (file)
@@ -2,8 +2,8 @@
  *  icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Coped with INTASSIGN of NEC VR4133.
  */
 #include <linux/errno.h>
index c64995342ba82f12922267674f46936fbf2b9571..1386e6f081c86aa370e3ddf31179b07b668f9ba0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  init.c, Common initialization routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9cc389109b19f42ee82f5d09f69b8d3e8de27024..bef06872f012d6ecb055aafeae92d9ed6f962135 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Interrupt handing routines for NEC VR4100 series.
  *
- *  Copyright (C) 2005-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 028aaf75eb216690a5217cfa69fb1bb65a4d4d5f..692b4e85b7fc98475ed33b5a8f3b9efd6733aa67 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  pmu.c, Power Management Unit routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9f26c14edcac25cfdbf588babf855c9b0b1d8109..ebc5dcf0ed8e29dad672a529e6cf6abf45c66f6c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 654dee6208be2258ce85ef608c0cc7a639696ad4..54eae56108fb94db06a5add150e8baad4ef5dbfe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series SIU platform device.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e0c1ac5e988e48335b471f8bf752ac21485a851f..ff841422b6389317567054761990d7d39ff4cb3b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  type.c, System type for NEC VR4100 series.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9eef297eca1a9ec1d52dbe7f3cda2a5ff200a4c8..3982f378a3e603242ebffe85fa45e6e4dbb52ae5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the IBM WorkPad z50.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index bcebcefb4ad7abee8b96bd69e4d231e355fb44d6..c96ba3da95ac15b6b2582fae648925179e2d9d6b 100644 (file)
@@ -61,7 +61,7 @@ SECTIONS
        _edata = .;             /* End of data section */
   }
 
-  .data.init_task : { INIT_TASK(THREAD_SIZE); }
+  .data.init_task : { INIT_TASK_DATA(THREAD_SIZE); }
 
   /* might get freed after init */
   . = ALIGN(PAGE_SIZE);
index d1430ef6b4f9a463c7ddc3b7be49754f5fa883bd..c07f722059094567ef61ceedda182a6de01bdfae 100644 (file)
@@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON
          recommended you say N here while the DMAR code remains
          experimental.
 
-config DMAR_GFX_WA
-       def_bool y
-       prompt "Support for Graphics workaround"
-       depends on DMAR
-       ---help---
-         Current Graphics drivers tend to use physical address
-         for DMA and avoid using DMA APIs. Setting this config
-         option permits the IOMMU driver to set a unity map for
-         all the OS-visible memory. Hence the driver can continue
-         to use physical addresses for DMA.
-
 config DMAR_FLOPPY_WA
        def_bool y
        depends on DMAR
        ---help---
-         Floppy disk drivers are know to bypass DMA API calls
+         Floppy disk drivers are known to bypass DMA API calls
          thereby failing to work when IOMMU is enabled. This
          workaround will setup a 1:1 mapping for the first
-         16M to make floppy (an ISA device) work.
+         16MiB to make floppy (an ISA device) work.
 
 config INTR_REMAP
        bool "Support for Interrupt Remapping (EXPERIMENTAL)"
index 47630479b0677e3cb51ee3fb473a584fdd4dfa8e..1a041bcf506bd8efd0d27a4e99e2003e07ff6445 100644 (file)
@@ -211,11 +211,11 @@ static __init int iommu_setup(char *p)
 #ifdef CONFIG_SWIOTLB
                if (!strncmp(p, "soft", 4))
                        swiotlb = 1;
+#endif
                if (!strncmp(p, "pt", 2)) {
                        iommu_pass_through = 1;
                        return 1;
                }
-#endif
 
                gart_parse_options(p);
 
index 39ce64432ba6d4cdcff6427851fe19aac172a2d7..e1999679a4d5156b967729c5e2b6b229a8747954 100644 (file)
@@ -350,6 +350,12 @@ static int attempt_merge(struct request_queue *q, struct request *req,
        if (blk_integrity_rq(req) != blk_integrity_rq(next))
                return 0;
 
+       /* don't merge requests of different failfast settings */
+       if (blk_failfast_dev(req)       != blk_failfast_dev(next)       ||
+           blk_failfast_transport(req) != blk_failfast_transport(next) ||
+           blk_failfast_driver(req)    != blk_failfast_driver(next))
+               return 0;
+
        /*
         * If we are allowed to merge, then append bio list
         * from next to rq and release next. merge_requests_fn
index ca861927ba41b2dfc9ff80c139f6c8cc162fc251..6f2375339a996a794c17c96d0f32aa724fd1fae2 100644 (file)
@@ -100,6 +100,14 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
        if (bio_integrity(bio) != blk_integrity_rq(rq))
                return 0;
 
+       /*
+        * Don't merge if failfast settings don't match
+        */
+       if (bio_failfast_dev(bio)       != blk_failfast_dev(rq)         ||
+           bio_failfast_transport(bio) != blk_failfast_transport(rq)   ||
+           bio_failfast_driver(bio)    != blk_failfast_driver(rq))
+               return 0;
+
        if (!elv_iosched_allow_merge(rq, bio))
                return 0;
 
index c7a527c08a0980d542c1fffbd30687bbc95289d0..65a0655e7fc8451380d34decf3b04025776f9d0c 100644 (file)
@@ -226,8 +226,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c)
 
 static inline void removeQ(CommandList_struct *c)
 {
-       if (WARN_ON(hlist_unhashed(&c->list)))
+       /*
+        * After kexec/dump some commands might still
+        * be in flight, which the firmware will try
+        * to complete. Resetting the firmware doesn't work
+        * with old fw revisions, so we have to mark
+        * them off as 'stale' to prevent the driver from
+        * falling over.
+        */
+       if (WARN_ON(hlist_unhashed(&c->list))) {
+               c->cmd_type = CMD_MSG_STALE;
                return;
+       }
 
        hlist_del_init(&c->list);
 }
@@ -4246,7 +4256,8 @@ static void fail_all_cmds(unsigned long ctlr)
        while (!hlist_empty(&h->cmpQ)) {
                c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
                removeQ(c);
-               c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+               if (c->cmd_type != CMD_MSG_STALE)
+                       c->err_info->CommandStatus = CMD_HARDWARE_ERR;
                if (c->cmd_type == CMD_RWREQ) {
                        complete_command(h, c, 0);
                } else if (c->cmd_type == CMD_IOCTL_PEND)
index cd665b00c7c5b333176e160102fc25f5b6f998e5..dbaed1ea0da3c9c2ba71993dfec116d291a87770 100644 (file)
@@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct {
 #define CMD_SCSI       0x03
 #define CMD_MSG_DONE   0x04
 #define CMD_MSG_TIMEOUT 0x05
+#define CMD_MSG_STALE  0xff
 
 /* This structure needs to be divisible by 8 for new
  * indexing method.
index 0bd01f49cfd8bc76baf500b7d903ffbe8b40de96..6a06913b01d30151065471350ec492e7df79a6a3 100644 (file)
@@ -1029,10 +1029,6 @@ config CS5535_GPIO
 
          If compiled as a module, it will be called cs5535_gpio.
 
-config GPIO_VR41XX
-       tristate "NEC VR4100 series General-purpose I/O Unit support"
-       depends on CPU_VR41XX
-
 config RAW_DRIVER
        tristate "RAW driver (/dev/raw/rawN)"
        depends on BLOCK
index 189efcff08ce246a58900ab15a7cacd487c37724..66f779ad4f4c05297409c5eefadcf92d0a3903f1 100644 (file)
@@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO)     += scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)     += pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)         += nsc_gpio.o
 obj-$(CONFIG_CS5535_GPIO)      += cs5535_gpio.o
-obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
 obj-$(CONFIG_GPIO_TB0219)      += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
index 6062b62800fd2d97e01a640fedaf655983b6997d..b3ec9b10e29208e5272f2f00593d6cf9421503c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for TANBAC TB0219 base board.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0219.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
 MODULE_LICENSE("GPL");
 
index 54c837288d19453ff2baf3756d28b8cbc5b1092e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,680 +0,0 @@
-/*
- *  Driver for NEC VR4100 series General-purpose I/O Unit.
- *
- *  Copyright (C) 2002 MontaVista Software Inc.
- *     Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-#include <asm/vr41xx/giu.h>
-#include <asm/vr41xx/irq.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
-MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
-MODULE_LICENSE("GPL");
-
-static int major;      /* default is dynamic major device number */
-module_param(major, int, 0);
-MODULE_PARM_DESC(major, "Major device number");
-
-#define GIUIOSELL      0x00
-#define GIUIOSELH      0x02
-#define GIUPIODL       0x04
-#define GIUPIODH       0x06
-#define GIUINTSTATL    0x08
-#define GIUINTSTATH    0x0a
-#define GIUINTENL      0x0c
-#define GIUINTENH      0x0e
-#define GIUINTTYPL     0x10
-#define GIUINTTYPH     0x12
-#define GIUINTALSELL   0x14
-#define GIUINTALSELH   0x16
-#define GIUINTHTSELL   0x18
-#define GIUINTHTSELH   0x1a
-#define GIUPODATL      0x1c
-#define GIUPODATEN     0x1c
-#define GIUPODATH      0x1e
- #define PIOEN0                0x0100
- #define PIOEN1                0x0200
-#define GIUPODAT       0x1e
-#define GIUFEDGEINHL   0x20
-#define GIUFEDGEINHH   0x22
-#define GIUREDGEINHL   0x24
-#define GIUREDGEINHH   0x26
-
-#define GIUUSEUPDN     0x1e0
-#define GIUTERMUPDN    0x1e2
-
-#define GPIO_HAS_PULLUPDOWN_IO         0x0001
-#define GPIO_HAS_OUTPUT_ENABLE         0x0002
-#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
-
-static spinlock_t giu_lock;
-static unsigned long giu_flags;
-static unsigned int giu_nr_pins;
-
-static void __iomem *giu_base;
-
-#define giu_read(offset)               readw(giu_base + (offset))
-#define giu_write(offset, value)       writew((value), giu_base + (offset))
-
-#define GPIO_PIN_OF_IRQ(irq)   ((irq) - GIU_IRQ_BASE)
-#define GIUINT_HIGH_OFFSET     16
-#define GIUINT_HIGH_MAX                32
-
-static inline uint16_t giu_set(uint16_t offset, uint16_t set)
-{
-       uint16_t data;
-
-       data = giu_read(offset);
-       data |= set;
-       giu_write(offset, data);
-
-       return data;
-}
-
-static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
-{
-       uint16_t data;
-
-       data = giu_read(offset);
-       data &= ~clear;
-       giu_write(offset, data);
-
-       return data;
-}
-
-static void ack_giuint_low(unsigned int irq)
-{
-       giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static void mask_giuint_low(unsigned int irq)
-{
-       giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static void mask_ack_giuint_low(unsigned int irq)
-{
-       unsigned int pin;
-
-       pin = GPIO_PIN_OF_IRQ(irq);
-       giu_clear(GIUINTENL, 1 << pin);
-       giu_write(GIUINTSTATL, 1 << pin);
-}
-
-static void unmask_giuint_low(unsigned int irq)
-{
-       giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static struct irq_chip giuint_low_irq_chip = {
-       .name           = "GIUINTL",
-       .ack            = ack_giuint_low,
-       .mask           = mask_giuint_low,
-       .mask_ack       = mask_ack_giuint_low,
-       .unmask         = unmask_giuint_low,
-};
-
-static void ack_giuint_high(unsigned int irq)
-{
-       giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_giuint_high(unsigned int irq)
-{
-       giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_ack_giuint_high(unsigned int irq)
-{
-       unsigned int pin;
-
-       pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
-       giu_clear(GIUINTENH, 1 << pin);
-       giu_write(GIUINTSTATH, 1 << pin);
-}
-
-static void unmask_giuint_high(unsigned int irq)
-{
-       giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static struct irq_chip giuint_high_irq_chip = {
-       .name           = "GIUINTH",
-       .ack            = ack_giuint_high,
-       .mask           = mask_giuint_high,
-       .mask_ack       = mask_ack_giuint_high,
-       .unmask         = unmask_giuint_high,
-};
-
-static int giu_get_irq(unsigned int irq)
-{
-       uint16_t pendl, pendh, maskl, maskh;
-       int i;
-
-       pendl = giu_read(GIUINTSTATL);
-       pendh = giu_read(GIUINTSTATH);
-       maskl = giu_read(GIUINTENL);
-       maskh = giu_read(GIUINTENH);
-
-       maskl &= pendl;
-       maskh &= pendh;
-
-       if (maskl) {
-               for (i = 0; i < 16; i++) {
-                       if (maskl & (1 << i))
-                               return GIU_IRQ(i);
-               }
-       } else if (maskh) {
-               for (i = 0; i < 16; i++) {
-                       if (maskh & (1 << i))
-                               return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
-               }
-       }
-
-       printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
-              maskl, pendl, maskh, pendh);
-
-       atomic_inc(&irq_err_count);
-
-       return -EINVAL;
-}
-
-void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
-{
-       uint16_t mask;
-
-       if (pin < GIUINT_HIGH_OFFSET) {
-               mask = 1 << pin;
-               if (trigger != IRQ_TRIGGER_LEVEL) {
-                       giu_set(GIUINTTYPL, mask);
-                       if (signal == IRQ_SIGNAL_HOLD)
-                               giu_set(GIUINTHTSELL, mask);
-                       else
-                               giu_clear(GIUINTHTSELL, mask);
-                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-                               switch (trigger) {
-                               case IRQ_TRIGGER_EDGE_FALLING:
-                                       giu_set(GIUFEDGEINHL, mask);
-                                       giu_clear(GIUREDGEINHL, mask);
-                                       break;
-                               case IRQ_TRIGGER_EDGE_RISING:
-                                       giu_clear(GIUFEDGEINHL, mask);
-                                       giu_set(GIUREDGEINHL, mask);
-                                       break;
-                               default:
-                                       giu_set(GIUFEDGEINHL, mask);
-                                       giu_set(GIUREDGEINHL, mask);
-                                       break;
-                               }
-                       }
-                       set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_edge_irq);
-               } else {
-                       giu_clear(GIUINTTYPL, mask);
-                       giu_clear(GIUINTHTSELL, mask);
-                       set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_level_irq);
-               }
-               giu_write(GIUINTSTATL, mask);
-       } else if (pin < GIUINT_HIGH_MAX) {
-               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-               if (trigger != IRQ_TRIGGER_LEVEL) {
-                       giu_set(GIUINTTYPH, mask);
-                       if (signal == IRQ_SIGNAL_HOLD)
-                               giu_set(GIUINTHTSELH, mask);
-                       else
-                               giu_clear(GIUINTHTSELH, mask);
-                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-                               switch (trigger) {
-                               case IRQ_TRIGGER_EDGE_FALLING:
-                                       giu_set(GIUFEDGEINHH, mask);
-                                       giu_clear(GIUREDGEINHH, mask);
-                                       break;
-                               case IRQ_TRIGGER_EDGE_RISING:
-                                       giu_clear(GIUFEDGEINHH, mask);
-                                       giu_set(GIUREDGEINHH, mask);
-                                       break;
-                               default:
-                                       giu_set(GIUFEDGEINHH, mask);
-                                       giu_set(GIUREDGEINHH, mask);
-                                       break;
-                               }
-                       }
-                       set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_edge_irq);
-               } else {
-                       giu_clear(GIUINTTYPH, mask);
-                       giu_clear(GIUINTHTSELH, mask);
-                       set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_level_irq);
-               }
-               giu_write(GIUINTSTATH, mask);
-       }
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
-
-void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
-{
-       uint16_t mask;
-
-       if (pin < GIUINT_HIGH_OFFSET) {
-               mask = 1 << pin;
-               if (level == IRQ_LEVEL_HIGH)
-                       giu_set(GIUINTALSELL, mask);
-               else
-                       giu_clear(GIUINTALSELL, mask);
-               giu_write(GIUINTSTATL, mask);
-       } else if (pin < GIUINT_HIGH_MAX) {
-               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-               if (level == IRQ_LEVEL_HIGH)
-                       giu_set(GIUINTALSELH, mask);
-               else
-                       giu_clear(GIUINTALSELH, mask);
-               giu_write(GIUINTSTATH, mask);
-       }
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
-
-gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
-{
-       uint16_t reg, mask;
-
-       if (pin >= giu_nr_pins)
-               return GPIO_DATA_INVAL;
-
-       if (pin < 16) {
-               reg = giu_read(GIUPIODL);
-               mask = (uint16_t)1 << pin;
-       } else if (pin < 32) {
-               reg = giu_read(GIUPIODH);
-               mask = (uint16_t)1 << (pin - 16);
-       } else if (pin < 48) {
-               reg = giu_read(GIUPODATL);
-               mask = (uint16_t)1 << (pin - 32);
-       } else {
-               reg = giu_read(GIUPODATH);
-               mask = (uint16_t)1 << (pin - 48);
-       }
-
-       if (reg & mask)
-               return GPIO_DATA_HIGH;
-
-       return GPIO_DATA_LOW;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
-
-int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
-{
-       uint16_t offset, mask, reg;
-       unsigned long flags;
-
-       if (pin >= giu_nr_pins)
-               return -EINVAL;
-
-       if (pin < 16) {
-               offset = GIUPIODL;
-               mask = (uint16_t)1 << pin;
-       } else if (pin < 32) {
-               offset = GIUPIODH;
-               mask = (uint16_t)1 << (pin - 16);
-       } else if (pin < 48) {
-               offset = GIUPODATL;
-               mask = (uint16_t)1 << (pin - 32);
-       } else {
-               offset = GIUPODATH;
-               mask = (uint16_t)1 << (pin - 48);
-       }
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       reg = giu_read(offset);
-       if (data == GPIO_DATA_HIGH)
-               reg |= mask;
-       else
-               reg &= ~mask;
-       giu_write(offset, reg);
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
-
-int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
-{
-       uint16_t offset, mask, reg;
-       unsigned long flags;
-
-       if (pin >= giu_nr_pins)
-               return -EINVAL;
-
-       if (pin < 16) {
-               offset = GIUIOSELL;
-               mask = (uint16_t)1 << pin;
-       } else if (pin < 32) {
-               offset = GIUIOSELH;
-               mask = (uint16_t)1 << (pin - 16);
-       } else {
-               if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
-                       offset = GIUPODATEN;
-                       mask = (uint16_t)1 << (pin - 32);
-               } else {
-                       switch (pin) {
-                       case 48:
-                               offset = GIUPODATH;
-                               mask = PIOEN0;
-                               break;
-                       case 49:
-                               offset = GIUPODATH;
-                               mask = PIOEN1;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       reg = giu_read(offset);
-       if (dir == GPIO_OUTPUT)
-               reg |= mask;
-       else
-               reg &= ~mask;
-       giu_write(offset, reg);
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
-
-int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
-{
-       uint16_t reg, mask;
-       unsigned long flags;
-
-       if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
-               return -EPERM;
-
-       if (pin >= 15)
-               return -EINVAL;
-
-       mask = (uint16_t)1 << pin;
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
-               reg = giu_read(GIUTERMUPDN);
-               if (pull == GPIO_PULL_UP)
-                       reg |= mask;
-               else
-                       reg &= ~mask;
-               giu_write(GIUTERMUPDN, reg);
-
-               reg = giu_read(GIUUSEUPDN);
-               reg |= mask;
-               giu_write(GIUUSEUPDN, reg);
-       } else {
-               reg = giu_read(GIUUSEUPDN);
-               reg &= ~mask;
-               giu_write(GIUUSEUPDN, reg);
-       }
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
-
-static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
-                         loff_t *ppos)
-{
-       unsigned int pin;
-       char value = '0';
-
-       pin = iminor(file->f_path.dentry->d_inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
-               value = '1';
-
-       if (len <= 0)
-               return -EFAULT;
-
-       if (put_user(value, buf))
-               return -EFAULT;
-
-       return 1;
-}
-
-static ssize_t gpio_write(struct file *file, const char __user *data,
-                          size_t len, loff_t *ppos)
-{
-       unsigned int pin;
-       size_t i;
-       char c;
-       int retval = 0;
-
-       pin = iminor(file->f_path.dentry->d_inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       for (i = 0; i < len; i++) {
-               if (get_user(c, data + i))
-                       return -EFAULT;
-
-               switch (c) {
-               case '0':
-                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
-                       break;
-               case '1':
-                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
-                       break;
-               case 'D':
-                       printk(KERN_INFO "GPIO%d: pull down\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
-                       break;
-               case 'd':
-                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-                       break;
-               case 'I':
-                       printk(KERN_INFO "GPIO%d: input\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
-                       break;
-               case 'O':
-                       printk(KERN_INFO "GPIO%d: output\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
-                       break;
-               case 'o':
-                       printk(KERN_INFO "GPIO%d: output disable\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
-                       break;
-               case 'P':
-                       printk(KERN_INFO "GPIO%d: pull up\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
-                       break;
-               case 'p':
-                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-                       break;
-               default:
-                       break;
-               }
-
-               if (retval < 0)
-                       break;
-       }
-
-       return i;
-}
-
-static int gpio_open(struct inode *inode, struct file *file)
-{
-       unsigned int pin;
-
-       cycle_kernel_lock();
-       pin = iminor(inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       return nonseekable_open(inode, file);
-}
-
-static int gpio_release(struct inode *inode, struct file *file)
-{
-       unsigned int pin;
-
-       pin = iminor(inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       return 0;
-}
-
-static const struct file_operations gpio_fops = {
-       .owner          = THIS_MODULE,
-       .read           = gpio_read,
-       .write          = gpio_write,
-       .open           = gpio_open,
-       .release        = gpio_release,
-};
-
-static int __devinit giu_probe(struct platform_device *dev)
-{
-       struct resource *res;
-       unsigned int trigger, i, pin;
-       struct irq_chip *chip;
-       int irq, retval;
-
-       switch (dev->id) {
-       case GPIO_50PINS_PULLUPDOWN:
-               giu_flags = GPIO_HAS_PULLUPDOWN_IO;
-               giu_nr_pins = 50;
-               break;
-       case GPIO_36PINS:
-               giu_nr_pins = 36;
-               break;
-       case GPIO_48PINS_EDGE_SELECT:
-               giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-               giu_nr_pins = 48;
-               break;
-       default:
-               printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EBUSY;
-
-       giu_base = ioremap(res->start, res->end - res->start + 1);
-       if (!giu_base)
-               return -ENOMEM;
-
-       retval = register_chrdev(major, "GIU", &gpio_fops);
-       if (retval < 0) {
-               iounmap(giu_base);
-               giu_base = NULL;
-               return retval;
-       }
-
-       if (major == 0) {
-               major = retval;
-               printk(KERN_INFO "GIU: major number %d\n", major);
-       }
-
-       spin_lock_init(&giu_lock);
-
-       giu_write(GIUINTENL, 0);
-       giu_write(GIUINTENH, 0);
-
-       trigger = giu_read(GIUINTTYPH) << 16;
-       trigger |= giu_read(GIUINTTYPL);
-       for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
-               pin = GPIO_PIN_OF_IRQ(i);
-               if (pin < GIUINT_HIGH_OFFSET)
-                       chip = &giuint_low_irq_chip;
-               else
-                       chip = &giuint_high_irq_chip;
-
-               if (trigger & (1 << pin))
-                       set_irq_chip_and_handler(i, chip, handle_edge_irq);
-               else
-                       set_irq_chip_and_handler(i, chip, handle_level_irq);
-
-       }
-
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0 || irq >= nr_irqs)
-               return -EBUSY;
-
-       return cascade_irq(irq, giu_get_irq);
-}
-
-static int __devexit giu_remove(struct platform_device *dev)
-{
-       if (giu_base) {
-               iounmap(giu_base);
-               giu_base = NULL;
-       }
-
-       return 0;
-}
-
-static struct platform_driver giu_device_driver = {
-       .probe          = giu_probe,
-       .remove         = __devexit_p(giu_remove),
-       .driver         = {
-               .name   = "GIU",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init vr41xx_giu_init(void)
-{
-       return platform_driver_register(&giu_device_driver);
-}
-
-static void __exit vr41xx_giu_exit(void)
-{
-       platform_driver_unregister(&giu_device_driver);
-}
-
-module_init(vr41xx_giu_init);
-module_exit(vr41xx_giu_exit);
index 3582c39f97258ee7f9a95612816fa0f1c83bc467..96dda81c922855ecb564a232df184a5896f6ec99 100644 (file)
@@ -79,6 +79,12 @@ config GPIO_XILINX
        help
          Say yes here to support the Xilinx FPGA GPIO device
 
+config GPIO_VR41XX
+       tristate "NEC VR4100 series General-purpose I/O Uint support"
+       depends on CPU_VR41XX
+       help
+         Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+
 comment "I2C GPIO expanders:"
 
 config GPIO_MAX732X
index ef90203e8f3c77df4c2f1b9cbe1433f50ce2b92a..9244c6fcd8be3e60a211609160c0f320726df594 100644 (file)
@@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061)      += pl061.o
 obj-$(CONFIG_GPIO_TWL4030)     += twl4030-gpio.o
 obj-$(CONFIG_GPIO_XILINX)      += xilinx_gpio.o
 obj-$(CONFIG_GPIO_BT8XX)       += bt8xxgpio.o
+obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c
new file mode 100644 (file)
index 0000000..b70e061
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *     Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+#define GIUIOSELL      0x00
+#define GIUIOSELH      0x02
+#define GIUPIODL       0x04
+#define GIUPIODH       0x06
+#define GIUINTSTATL    0x08
+#define GIUINTSTATH    0x0a
+#define GIUINTENL      0x0c
+#define GIUINTENH      0x0e
+#define GIUINTTYPL     0x10
+#define GIUINTTYPH     0x12
+#define GIUINTALSELL   0x14
+#define GIUINTALSELH   0x16
+#define GIUINTHTSELL   0x18
+#define GIUINTHTSELH   0x1a
+#define GIUPODATL      0x1c
+#define GIUPODATEN     0x1c
+#define GIUPODATH      0x1e
+ #define PIOEN0                0x0100
+ #define PIOEN1                0x0200
+#define GIUPODAT       0x1e
+#define GIUFEDGEINHL   0x20
+#define GIUFEDGEINHH   0x22
+#define GIUREDGEINHL   0x24
+#define GIUREDGEINHH   0x26
+
+#define GIUUSEUPDN     0x1e0
+#define GIUTERMUPDN    0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO         0x0001
+#define GPIO_HAS_OUTPUT_ENABLE         0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
+
+enum {
+       GPIO_INPUT,
+       GPIO_OUTPUT,
+};
+
+static DEFINE_SPINLOCK(giu_lock);
+static unsigned long giu_flags;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)               readw(giu_base + (offset))
+#define giu_write(offset, value)       writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)   ((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET     16
+#define GIUINT_HIGH_MAX                32
+
+static inline u16 giu_set(u16 offset, u16 set)
+{
+       u16 data;
+
+       data = giu_read(offset);
+       data |= set;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static inline u16 giu_clear(u16 offset, u16 clear)
+{
+       u16 data;
+
+       data = giu_read(offset);
+       data &= ~clear;
+       giu_write(offset, data);
+
+       return data;
+}
+
+static void ack_giuint_low(unsigned int irq)
+{
+       giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void mask_giuint_low(unsigned int irq)
+{
+       giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void mask_ack_giuint_low(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq);
+       giu_clear(GIUINTENL, 1 << pin);
+       giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void unmask_giuint_low(unsigned int irq)
+{
+       giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct irq_chip giuint_low_irq_chip = {
+       .name           = "GIUINTL",
+       .ack            = ack_giuint_low,
+       .mask           = mask_giuint_low,
+       .mask_ack       = mask_ack_giuint_low,
+       .unmask         = unmask_giuint_low,
+};
+
+static void ack_giuint_high(unsigned int irq)
+{
+       giu_write(GIUINTSTATH,
+                 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_giuint_high(unsigned int irq)
+{
+       giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_ack_giuint_high(unsigned int irq)
+{
+       unsigned int pin;
+
+       pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+       giu_clear(GIUINTENH, 1 << pin);
+       giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void unmask_giuint_high(unsigned int irq)
+{
+       giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct irq_chip giuint_high_irq_chip = {
+       .name           = "GIUINTH",
+       .ack            = ack_giuint_high,
+       .mask           = mask_giuint_high,
+       .mask_ack       = mask_ack_giuint_high,
+       .unmask         = unmask_giuint_high,
+};
+
+static int giu_get_irq(unsigned int irq)
+{
+       u16 pendl, pendh, maskl, maskh;
+       int i;
+
+       pendl = giu_read(GIUINTSTATL);
+       pendh = giu_read(GIUINTSTATH);
+       maskl = giu_read(GIUINTENL);
+       maskh = giu_read(GIUINTENH);
+
+       maskl &= pendl;
+       maskh &= pendh;
+
+       if (maskl) {
+               for (i = 0; i < 16; i++) {
+                       if (maskl & (1 << i))
+                               return GIU_IRQ(i);
+               }
+       } else if (maskh) {
+               for (i = 0; i < 16; i++) {
+                       if (maskh & (1 << i))
+                               return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+               }
+       }
+
+       printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+              maskl, pendl, maskh, pendh);
+
+       atomic_inc(&irq_err_count);
+
+       return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+                           irq_signal_t signal)
+{
+       u16 mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPL, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELL, mask);
+                       else
+                               giu_clear(GIUINTHTSELL, mask);
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_clear(GIUREDGEINHL, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHL, mask);
+                                       giu_set(GIUREDGEINHL, mask);
+                                       break;
+                               }
+                       }
+                       set_irq_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_low_irq_chip,
+                                                handle_edge_irq);
+               } else {
+                       giu_clear(GIUINTTYPL, mask);
+                       giu_clear(GIUINTHTSELL, mask);
+                       set_irq_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_low_irq_chip,
+                                                handle_level_irq);
+               }
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (trigger != IRQ_TRIGGER_LEVEL) {
+                       giu_set(GIUINTTYPH, mask);
+                       if (signal == IRQ_SIGNAL_HOLD)
+                               giu_set(GIUINTHTSELH, mask);
+                       else
+                               giu_clear(GIUINTHTSELH, mask);
+                       if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+                               switch (trigger) {
+                               case IRQ_TRIGGER_EDGE_FALLING:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_clear(GIUREDGEINHH, mask);
+                                       break;
+                               case IRQ_TRIGGER_EDGE_RISING:
+                                       giu_clear(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               default:
+                                       giu_set(GIUFEDGEINHH, mask);
+                                       giu_set(GIUREDGEINHH, mask);
+                                       break;
+                               }
+                       }
+                       set_irq_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_high_irq_chip,
+                                                handle_edge_irq);
+               } else {
+                       giu_clear(GIUINTTYPH, mask);
+                       giu_clear(GIUINTHTSELH, mask);
+                       set_irq_chip_and_handler(GIU_IRQ(pin),
+                                                &giuint_high_irq_chip,
+                                                handle_level_irq);
+               }
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+       u16 mask;
+
+       if (pin < GIUINT_HIGH_OFFSET) {
+               mask = 1 << pin;
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELL, mask);
+               else
+                       giu_clear(GIUINTALSELL, mask);
+               giu_write(GIUINTSTATL, mask);
+       } else if (pin < GIUINT_HIGH_MAX) {
+               mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+               if (level == IRQ_LEVEL_HIGH)
+                       giu_set(GIUINTALSELH, mask);
+               else
+                       giu_clear(GIUINTALSELH, mask);
+               giu_write(GIUINTSTATH, mask);
+       }
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
+{
+       u16 offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= chip->ngpio)
+               return -EINVAL;
+
+       if (pin < 16) {
+               offset = GIUIOSELL;
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               offset = GIUIOSELH;
+               mask = 1 << (pin - 16);
+       } else {
+               if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+                       offset = GIUPODATEN;
+                       mask = 1 << (pin - 32);
+               } else {
+                       switch (pin) {
+                       case 48:
+                               offset = GIUPODATH;
+                               mask = PIOEN0;
+                               break;
+                       case 49:
+                               offset = GIUPODATH;
+                               mask = PIOEN1;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (dir == GPIO_OUTPUT)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+       u16 reg, mask;
+       unsigned long flags;
+
+       if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+               return -EPERM;
+
+       if (pin >= 15)
+               return -EINVAL;
+
+       mask = 1 << pin;
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+               reg = giu_read(GIUTERMUPDN);
+               if (pull == GPIO_PULL_UP)
+                       reg |= mask;
+               else
+                       reg &= ~mask;
+               giu_write(GIUTERMUPDN, reg);
+
+               reg = giu_read(GIUUSEUPDN);
+               reg |= mask;
+               giu_write(GIUUSEUPDN, reg);
+       } else {
+               reg = giu_read(GIUUSEUPDN);
+               reg &= ~mask;
+               giu_write(GIUUSEUPDN, reg);
+       }
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+       u16 reg, mask;
+
+       if (pin >= chip->ngpio)
+               return -EINVAL;
+
+       if (pin < 16) {
+               reg = giu_read(GIUPIODL);
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               reg = giu_read(GIUPIODH);
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               reg = giu_read(GIUPODATL);
+               mask = 1 << (pin - 32);
+       } else {
+               reg = giu_read(GIUPODATH);
+               mask = 1 << (pin - 48);
+       }
+
+       if (reg & mask)
+               return 1;
+
+       return 0;
+}
+
+static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
+                           int value)
+{
+       u16 offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= chip->ngpio)
+               return;
+
+       if (pin < 16) {
+               offset = GIUPIODL;
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               offset = GIUPIODH;
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               offset = GIUPODATL;
+               mask = 1 << (pin - 32);
+       } else {
+               offset = GIUPODATH;
+               mask = 1 << (pin - 48);
+       }
+
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (value)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
+}
+
+
+static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return giu_set_direction(chip, offset, GPIO_INPUT);
+}
+
+static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                               int value)
+{
+       vr41xx_gpio_set(chip, offset, value);
+
+       return giu_set_direction(chip, offset, GPIO_OUTPUT);
+}
+
+static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       if (offset >= chip->ngpio)
+               return -EINVAL;
+
+       return GIU_IRQ_BASE + offset;
+}
+
+static struct gpio_chip vr41xx_gpio_chip = {
+       .label                  = "vr41xx",
+       .owner                  = THIS_MODULE,
+       .direction_input        = vr41xx_gpio_direction_input,
+       .get                    = vr41xx_gpio_get,
+       .direction_output       = vr41xx_gpio_direction_output,
+       .set                    = vr41xx_gpio_set,
+       .to_irq                 = vr41xx_gpio_to_irq,
+};
+
+static int __devinit giu_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       unsigned int trigger, i, pin;
+       struct irq_chip *chip;
+       int irq, retval;
+
+       switch (pdev->id) {
+       case GPIO_50PINS_PULLUPDOWN:
+               giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+               vr41xx_gpio_chip.ngpio = 50;
+               break;
+       case GPIO_36PINS:
+               vr41xx_gpio_chip.ngpio = 36;
+               break;
+       case GPIO_48PINS_EDGE_SELECT:
+               giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+               vr41xx_gpio_chip.ngpio = 48;
+               break;
+       default:
+               dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EBUSY;
+
+       giu_base = ioremap(res->start, res->end - res->start + 1);
+       if (!giu_base)
+               return -ENOMEM;
+
+       vr41xx_gpio_chip.dev = &pdev->dev;
+
+       retval = gpiochip_add(&vr41xx_gpio_chip);
+
+       giu_write(GIUINTENL, 0);
+       giu_write(GIUINTENH, 0);
+
+       trigger = giu_read(GIUINTTYPH) << 16;
+       trigger |= giu_read(GIUINTTYPL);
+       for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+               pin = GPIO_PIN_OF_IRQ(i);
+               if (pin < GIUINT_HIGH_OFFSET)
+                       chip = &giuint_low_irq_chip;
+               else
+                       chip = &giuint_high_irq_chip;
+
+               if (trigger & (1 << pin))
+                       set_irq_chip_and_handler(i, chip, handle_edge_irq);
+               else
+                       set_irq_chip_and_handler(i, chip, handle_level_irq);
+
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0 || irq >= nr_irqs)
+               return -EBUSY;
+
+       return cascade_irq(irq, giu_get_irq);
+}
+
+static int __devexit giu_remove(struct platform_device *pdev)
+{
+       if (giu_base) {
+               iounmap(giu_base);
+               giu_base = NULL;
+       }
+
+       return 0;
+}
+
+static struct platform_driver giu_device_driver = {
+       .probe          = giu_probe,
+       .remove         = __devexit_p(giu_remove),
+       .driver         = {
+               .name   = "GIU",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init vr41xx_giu_init(void)
+{
+       return platform_driver_register(&giu_device_driver);
+}
+
+static void __exit vr41xx_giu_exit(void)
+{
+       platform_driver_unregister(&giu_device_driver);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
index 2adf9cb265da69fd67b6d1b8bec3fa3841e95ec2..d114d3a9e1e94b7129870642943d7ac91a368cac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt button interface driver.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
        return 0;
 }
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("Cobalt button interface driver");
 MODULE_LICENSE("GPL");
 /* work with hotplug and coldplug */
index ff0e8c3fbf9b79d61365d456d1d78f314390402e..5f1ce810815f51cb150c7f4c2b203505d10447a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  LEDs driver for the Cobalt Raq series.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 420afa887283709d7f65806310e8553d78868ff9..53075424a4349c0efdbbb24a22ba0f7226aa21d3 100644 (file)
 #define MAX_AGAW_WIDTH 64
 
 #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+#define DOMAIN_MAX_PFN(gaw)  ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
 
 #define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT)
 #define DMA_32BIT_PFN          IOVA_PFN(DMA_BIT_MASK(32))
 #define DMA_64BIT_PFN          IOVA_PFN(DMA_BIT_MASK(64))
 
-#ifndef PHYSICAL_PAGE_MASK
-#define PHYSICAL_PAGE_MASK PAGE_MASK
-#endif
+
+/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
+   are never going to work. */
+static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
+{
+       return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+
+static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
+{
+       return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+static inline unsigned long page_to_dma_pfn(struct page *pg)
+{
+       return mm_to_dma_pfn(page_to_pfn(pg));
+}
+static inline unsigned long virt_to_dma_pfn(void *p)
+{
+       return page_to_dma_pfn(virt_to_page(p));
+}
 
 /* global iommu list, set NULL for ignored DMAR units */
 static struct intel_iommu **g_iommus;
@@ -204,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
 
 static inline u64 dma_pte_addr(struct dma_pte *pte)
 {
-       return (pte->val & VTD_PAGE_MASK);
+#ifdef CONFIG_64BIT
+       return pte->val & VTD_PAGE_MASK;
+#else
+       /* Must have a full atomic 64-bit read */
+       return  __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK;
+#endif
 }
 
-static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr)
+static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn)
 {
-       pte->val |= (addr & VTD_PAGE_MASK);
+       pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT;
 }
 
 static inline bool dma_pte_present(struct dma_pte *pte)
@@ -217,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte)
        return (pte->val & 3) != 0;
 }
 
+static inline int first_pte_in_page(struct dma_pte *pte)
+{
+       return !((unsigned long)pte & ~VTD_PAGE_MASK);
+}
+
 /*
  * This domain is a statically identity mapping domain.
  *     1. This domain creats a static 1:1 mapping to all usable memory.
@@ -244,7 +272,6 @@ struct dmar_domain {
        struct iova_domain iovad;       /* iova's that belong to this domain */
 
        struct dma_pte  *pgd;           /* virtual address */
-       spinlock_t      mapping_lock;   /* page table lock */
        int             gaw;            /* max guest address width */
 
        /* adjusted guest address width, 0 is level 2 30-bit */
@@ -648,80 +675,78 @@ static inline int width_to_agaw(int width)
 
 static inline unsigned int level_to_offset_bits(int level)
 {
-       return (12 + (level - 1) * LEVEL_STRIDE);
+       return (level - 1) * LEVEL_STRIDE;
 }
 
-static inline int address_level_offset(u64 addr, int level)
+static inline int pfn_level_offset(unsigned long pfn, int level)
 {
-       return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK);
+       return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
 }
 
-static inline u64 level_mask(int level)
+static inline unsigned long level_mask(int level)
 {
-       return ((u64)-1 << level_to_offset_bits(level));
+       return -1UL << level_to_offset_bits(level);
 }
 
-static inline u64 level_size(int level)
+static inline unsigned long level_size(int level)
 {
-       return ((u64)1 << level_to_offset_bits(level));
+       return 1UL << level_to_offset_bits(level);
 }
 
-static inline u64 align_to_level(u64 addr, int level)
+static inline unsigned long align_to_level(unsigned long pfn, int level)
 {
-       return ((addr + level_size(level) - 1) & level_mask(level));
+       return (pfn + level_size(level) - 1) & level_mask(level);
 }
 
-static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
+static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
+                                     unsigned long pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
        struct dma_pte *parent, *pte = NULL;
        int level = agaw_to_level(domain->agaw);
        int offset;
-       unsigned long flags;
 
        BUG_ON(!domain->pgd);
-
-       addr &= (((u64)1) << addr_width) - 1;
+       BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
        parent = domain->pgd;
 
-       spin_lock_irqsave(&domain->mapping_lock, flags);
        while (level > 0) {
                void *tmp_page;
 
-               offset = address_level_offset(addr, level);
+               offset = pfn_level_offset(pfn, level);
                pte = &parent[offset];
                if (level == 1)
                        break;
 
                if (!dma_pte_present(pte)) {
+                       uint64_t pteval;
+
                        tmp_page = alloc_pgtable_page();
 
-                       if (!tmp_page) {
-                               spin_unlock_irqrestore(&domain->mapping_lock,
-                                       flags);
+                       if (!tmp_page)
                                return NULL;
+
+                       domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
+                       pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
+                       if (cmpxchg64(&pte->val, 0ULL, pteval)) {
+                               /* Someone else set it while we were thinking; use theirs. */
+                               free_pgtable_page(tmp_page);
+                       } else {
+                               dma_pte_addr(pte);
+                               domain_flush_cache(domain, pte, sizeof(*pte));
                        }
-                       domain_flush_cache(domain, tmp_page, PAGE_SIZE);
-                       dma_set_pte_addr(pte, virt_to_phys(tmp_page));
-                       /*
-                        * high level table always sets r/w, last level page
-                        * table control read/write
-                        */
-                       dma_set_pte_readable(pte);
-                       dma_set_pte_writable(pte);
-                       domain_flush_cache(domain, pte, sizeof(*pte));
                }
                parent = phys_to_virt(dma_pte_addr(pte));
                level--;
        }
 
-       spin_unlock_irqrestore(&domain->mapping_lock, flags);
        return pte;
 }
 
 /* return address's pte at specific level */
-static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
-               int level)
+static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
+                                        unsigned long pfn,
+                                        int level)
 {
        struct dma_pte *parent, *pte = NULL;
        int total = agaw_to_level(domain->agaw);
@@ -729,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
 
        parent = domain->pgd;
        while (level <= total) {
-               offset = address_level_offset(addr, total);
+               offset = pfn_level_offset(pfn, total);
                pte = &parent[offset];
                if (level == total)
                        return pte;
@@ -742,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
        return NULL;
 }
 
-/* clear one page's page table */
-static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
-{
-       struct dma_pte *pte = NULL;
-
-       /* get last level pte */
-       pte = dma_addr_level_pte(domain, addr, 1);
-
-       if (pte) {
-               dma_clear_pte(pte);
-               domain_flush_cache(domain, pte, sizeof(*pte));
-       }
-}
-
 /* clear last level pte, a tlb flush should be followed */
-static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end)
+static void dma_pte_clear_range(struct dmar_domain *domain,
+                               unsigned long start_pfn,
+                               unsigned long last_pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
-       int npages;
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       struct dma_pte *first_pte, *pte;
+
+       BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+       BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
 
-       start &= (((u64)1) << addr_width) - 1;
-       end &= (((u64)1) << addr_width) - 1;
-       /* in case it's partial page */
-       start &= PAGE_MASK;
-       end = PAGE_ALIGN(end);
-       npages = (end - start) / VTD_PAGE_SIZE;
+       /* we don't need lock here; nobody else touches the iova range */
+       while (start_pfn <= last_pfn) {
+               first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1);
+               if (!pte) {
+                       start_pfn = align_to_level(start_pfn + 1, 2);
+                       continue;
+               }
+               do { 
+                       dma_clear_pte(pte);
+                       start_pfn++;
+                       pte++;
+               } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
 
-       /* we don't need lock here, nobody else touches the iova range */
-       while (npages--) {
-               dma_pte_clear_one(domain, start);
-               start += VTD_PAGE_SIZE;
+               domain_flush_cache(domain, first_pte,
+                                  (void *)pte - (void *)first_pte);
        }
 }
 
 /* free page table pages. last level pte should already be cleared */
 static void dma_pte_free_pagetable(struct dmar_domain *domain,
-       u64 start, u64 end)
+                                  unsigned long start_pfn,
+                                  unsigned long last_pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
-       struct dma_pte *pte;
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       struct dma_pte *first_pte, *pte;
        int total = agaw_to_level(domain->agaw);
        int level;
-       u64 tmp;
+       unsigned long tmp;
 
-       start &= (((u64)1) << addr_width) - 1;
-       end &= (((u64)1) << addr_width) - 1;
+       BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+       BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
 
-       /* we don't need lock here, nobody else touches the iova range */
+       /* We don't need lock here; nobody else touches the iova range */
        level = 2;
        while (level <= total) {
-               tmp = align_to_level(start, level);
-               if (tmp >= end || (tmp + level_size(level) > end))
+               tmp = align_to_level(start_pfn, level);
+
+               /* If we can't even clear one PTE at this level, we're done */
+               if (tmp + level_size(level) - 1 > last_pfn)
                        return;
 
-               while (tmp < end) {
-                       pte = dma_addr_level_pte(domain, tmp, level);
-                       if (pte) {
-                               free_pgtable_page(
-                                       phys_to_virt(dma_pte_addr(pte)));
-                               dma_clear_pte(pte);
-                               domain_flush_cache(domain, pte, sizeof(*pte));
+               while (tmp + level_size(level) - 1 <= last_pfn) {
+                       first_pte = pte = dma_pfn_level_pte(domain, tmp, level);
+                       if (!pte) {
+                               tmp = align_to_level(tmp + 1, level + 1);
+                               continue;
                        }
-                       tmp += level_size(level);
+                       do {
+                               if (dma_pte_present(pte)) {
+                                       free_pgtable_page(phys_to_virt(dma_pte_addr(pte)));
+                                       dma_clear_pte(pte);
+                               }
+                               pte++;
+                               tmp += level_size(level);
+                       } while (!first_pte_in_page(pte) &&
+                                tmp + level_size(level) - 1 <= last_pfn);
+
+                       domain_flush_cache(domain, first_pte,
+                                          (void *)pte - (void *)first_pte);
+                       
                }
                level++;
        }
        /* free pgd */
-       if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) {
+       if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
                free_pgtable_page(domain->pgd);
                domain->pgd = NULL;
        }
@@ -1035,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
 }
 
 static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
-                                 u64 addr, unsigned int pages)
+                                 unsigned long pfn, unsigned int pages)
 {
        unsigned int mask = ilog2(__roundup_pow_of_two(pages));
+       uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
 
-       BUG_ON(addr & (~VTD_PAGE_MASK));
        BUG_ON(pages == 0);
 
        /*
@@ -1054,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
        else
                iommu->flush.flush_iotlb(iommu, did, addr, mask,
                                                DMA_TLB_PSI_FLUSH);
-       if (did)
+
+       /*
+        * In caching mode, domain ID 0 is reserved for non-present to present
+        * mapping flush. Device IOTLB doesn't need to be flushed in this case.
+        */
+       if (!cap_caching_mode(iommu->cap) || did)
                iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
 }
 
@@ -1279,7 +1317,6 @@ static void dmar_init_reserved_ranges(void)
        struct pci_dev *pdev = NULL;
        struct iova *iova;
        int i;
-       u64 addr, size;
 
        init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
 
@@ -1302,12 +1339,9 @@ static void dmar_init_reserved_ranges(void)
                        r = &pdev->resource[i];
                        if (!r->flags || !(r->flags & IORESOURCE_MEM))
                                continue;
-                       addr = r->start;
-                       addr &= PHYSICAL_PAGE_MASK;
-                       size = r->end - addr;
-                       size = PAGE_ALIGN(size);
-                       iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr),
-                               IOVA_PFN(size + addr) - 1);
+                       iova = reserve_iova(&reserved_iova_list,
+                                           IOVA_PFN(r->start),
+                                           IOVA_PFN(r->end));
                        if (!iova)
                                printk(KERN_ERR "Reserve iova failed\n");
                }
@@ -1341,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
        unsigned long sagaw;
 
        init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-       spin_lock_init(&domain->mapping_lock);
        spin_lock_init(&domain->iommu_lock);
 
        domain_reserve_special_ranges(domain);
@@ -1388,7 +1421,6 @@ static void domain_exit(struct dmar_domain *domain)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
-       u64 end;
 
        /* Domain 0 is reserved, so dont process it */
        if (!domain)
@@ -1397,14 +1429,12 @@ static void domain_exit(struct dmar_domain *domain)
        domain_remove_dev_info(domain);
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
-       end = DOMAIN_MAX_ADDR(domain->gaw);
-       end = end & (~PAGE_MASK);
 
        /* clear ptes */
-       dma_pte_clear_range(domain, 0, end);
+       dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        /* free page tables */
-       dma_pte_free_pagetable(domain, 0, end);
+       dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        for_each_active_iommu(iommu, drhd)
                if (test_bit(iommu->seq_id, &domain->iommu_bmp))
@@ -1618,42 +1648,86 @@ static int domain_context_mapped(struct pci_dev *pdev)
                                             tmp->devfn);
 }
 
-static int
-domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
-                       u64 hpa, size_t size, int prot)
+static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                           struct scatterlist *sg, unsigned long phys_pfn,
+                           unsigned long nr_pages, int prot)
 {
-       u64 start_pfn, end_pfn;
-       struct dma_pte *pte;
-       int index;
-       int addr_width = agaw_to_width(domain->agaw);
+       struct dma_pte *first_pte = NULL, *pte = NULL;
+       phys_addr_t uninitialized_var(pteval);
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       unsigned long sg_res;
 
-       hpa &= (((u64)1) << addr_width) - 1;
+       BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
 
        if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
                return -EINVAL;
-       iova &= PAGE_MASK;
-       start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT;
-       end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT;
-       index = 0;
-       while (start_pfn < end_pfn) {
-               pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index);
-               if (!pte)
-                       return -ENOMEM;
+
+       prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
+
+       if (sg)
+               sg_res = 0;
+       else {
+               sg_res = nr_pages + 1;
+               pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
+       }
+
+       while (nr_pages--) {
+               uint64_t tmp;
+
+               if (!sg_res) {
+                       sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT;
+                       sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
+                       sg->dma_length = sg->length;
+                       pteval = page_to_phys(sg_page(sg)) | prot;
+               }
+               if (!pte) {
+                       first_pte = pte = pfn_to_dma_pte(domain, iov_pfn);
+                       if (!pte)
+                               return -ENOMEM;
+               }
                /* We don't need lock here, nobody else
                 * touches the iova range
                 */
-               BUG_ON(dma_pte_addr(pte));
-               dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT);
-               dma_set_pte_prot(pte, prot);
-               if (prot & DMA_PTE_SNP)
-                       dma_set_pte_snp(pte);
-               domain_flush_cache(domain, pte, sizeof(*pte));
-               start_pfn++;
-               index++;
+               tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
+               if (tmp) {
+                       static int dumps = 5;
+                       printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
+                              iov_pfn, tmp, (unsigned long long)pteval);
+                       if (dumps) {
+                               dumps--;
+                               debug_dma_dump_mappings(NULL);
+                       }
+                       WARN_ON(1);
+               }
+               pte++;
+               if (!nr_pages || first_pte_in_page(pte)) {
+                       domain_flush_cache(domain, first_pte,
+                                          (void *)pte - (void *)first_pte);
+                       pte = NULL;
+               }
+               iov_pfn++;
+               pteval += VTD_PAGE_SIZE;
+               sg_res--;
+               if (!sg_res)
+                       sg = sg_next(sg);
        }
        return 0;
 }
 
+static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                                   struct scatterlist *sg, unsigned long nr_pages,
+                                   int prot)
+{
+       return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
+}
+
+static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                                    unsigned long phys_pfn, unsigned long nr_pages,
+                                    int prot)
+{
+       return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
+}
+
 static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
 {
        if (!iommu)
@@ -1844,58 +1918,61 @@ error:
 
 static int iommu_identity_mapping;
 
+static int iommu_domain_identity_map(struct dmar_domain *domain,
+                                    unsigned long long start,
+                                    unsigned long long end)
+{
+       unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
+       unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
+
+       if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
+                         dma_to_mm_pfn(last_vpfn))) {
+               printk(KERN_ERR "IOMMU: reserve iova failed\n");
+               return -ENOMEM;
+       }
+
+       pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
+                start, end, domain->id);
+       /*
+        * RMRR range might have overlap with physical memory range,
+        * clear it first
+        */
+       dma_pte_clear_range(domain, first_vpfn, last_vpfn);
+
+       return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
+                                 last_vpfn - first_vpfn + 1,
+                                 DMA_PTE_READ|DMA_PTE_WRITE);
+}
+
 static int iommu_prepare_identity_map(struct pci_dev *pdev,
                                      unsigned long long start,
                                      unsigned long long end)
 {
        struct dmar_domain *domain;
-       unsigned long size;
-       unsigned long long base;
        int ret;
 
        printk(KERN_INFO
-               "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
-               pci_name(pdev), start, end);
-       if (iommu_identity_mapping)
-               domain = si_domain;
-       else
-               /* page table init */
-               domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+              "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
+              pci_name(pdev), start, end);
+
+       domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
        if (!domain)
                return -ENOMEM;
 
-       /* The address might not be aligned */
-       base = start & PAGE_MASK;
-       size = end - base;
-       size = PAGE_ALIGN(size);
-       if (!reserve_iova(&domain->iovad, IOVA_PFN(base),
-                       IOVA_PFN(base + size) - 1)) {
-               printk(KERN_ERR "IOMMU: reserve iova failed\n");
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       pr_debug("Mapping reserved region %lx@%llx for %s\n",
-               size, base, pci_name(pdev));
-       /*
-        * RMRR range might have overlap with physical memory range,
-        * clear it first
-        */
-       dma_pte_clear_range(domain, base, base + size);
-
-       ret = domain_page_mapping(domain, base, base, size,
-               DMA_PTE_READ|DMA_PTE_WRITE);
+       ret = iommu_domain_identity_map(domain, start, end);
        if (ret)
                goto error;
 
        /* context entry init */
        ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-       if (!ret)
-               return 0;
-error:
+       if (ret)
+               goto error;
+
+       return 0;
+
+ error:
        domain_exit(domain);
        return ret;
-
 }
 
 static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
@@ -1907,64 +1984,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
                rmrr->end_address + 1);
 }
 
-struct iommu_prepare_data {
-       struct pci_dev *pdev;
-       int ret;
-};
-
-static int __init iommu_prepare_work_fn(unsigned long start_pfn,
-                                        unsigned long end_pfn, void *datax)
-{
-       struct iommu_prepare_data *data;
-
-       data = (struct iommu_prepare_data *)datax;
-
-       data->ret = iommu_prepare_identity_map(data->pdev,
-                               start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
-       return data->ret;
-
-}
-
-static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev)
-{
-       int nid;
-       struct iommu_prepare_data data;
-
-       data.pdev = pdev;
-       data.ret = 0;
-
-       for_each_online_node(nid) {
-               work_with_active_regions(nid, iommu_prepare_work_fn, &data);
-               if (data.ret)
-                       return data.ret;
-       }
-       return data.ret;
-}
-
-#ifdef CONFIG_DMAR_GFX_WA
-static void __init iommu_prepare_gfx_mapping(void)
-{
-       struct pci_dev *pdev = NULL;
-       int ret;
-
-       for_each_pci_dev(pdev) {
-               if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO ||
-                               !IS_GFX_DEVICE(pdev))
-                       continue;
-               printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
-                       pci_name(pdev));
-               ret = iommu_prepare_with_active_regions(pdev);
-               if (ret)
-                       printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
-       }
-}
-#else /* !CONFIG_DMAR_GFX_WA */
-static inline void iommu_prepare_gfx_mapping(void)
-{
-       return;
-}
-#endif
-
 #ifdef CONFIG_DMAR_FLOPPY_WA
 static inline void iommu_prepare_isa(void)
 {
@@ -1975,12 +1994,12 @@ static inline void iommu_prepare_isa(void)
        if (!pdev)
                return;
 
-       printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n");
+       printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
        ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024);
 
        if (ret)
-               printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, "
-                       "floppy might not work\n");
+               printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
+                      "floppy might not work\n");
 
 }
 #else
@@ -2008,16 +2027,30 @@ static int __init init_context_pass_through(void)
 }
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
+
+static int __init si_domain_work_fn(unsigned long start_pfn,
+                                   unsigned long end_pfn, void *datax)
+{
+       int *ret = datax;
+
+       *ret = iommu_domain_identity_map(si_domain,
+                                        (uint64_t)start_pfn << PAGE_SHIFT,
+                                        (uint64_t)end_pfn << PAGE_SHIFT);
+       return *ret;
+
+}
+
 static int si_domain_init(void)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
-       int ret = 0;
+       int nid, ret = 0;
 
        si_domain = alloc_domain();
        if (!si_domain)
                return -EFAULT;
 
+       pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
 
        for_each_active_iommu(iommu, drhd) {
                ret = iommu_attach_domain(si_domain, iommu);
@@ -2034,6 +2067,12 @@ static int si_domain_init(void)
 
        si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
 
+       for_each_online_node(nid) {
+               work_with_active_regions(nid, si_domain_work_fn, &ret);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -2087,13 +2126,14 @@ static int iommu_prepare_static_identity_mapping(void)
        if (ret)
                return -EFAULT;
 
-       printk(KERN_INFO "IOMMU: Setting identity map:\n");
        for_each_pci_dev(pdev) {
-               ret = iommu_prepare_with_active_regions(pdev);
-               if (ret) {
-                       printk(KERN_INFO "1:1 mapping to one domain failed.\n");
-                       return -EFAULT;
-               }
+               printk(KERN_INFO "IOMMU: identity mapping for device %s\n",
+                      pci_name(pdev));
+
+               ret = domain_context_mapping(si_domain, pdev,
+                                            CONTEXT_TT_MULTI_LEVEL);
+               if (ret)
+                       return ret;
                ret = domain_add_dev_info(si_domain, pdev);
                if (ret)
                        return ret;
@@ -2284,8 +2324,6 @@ int __init init_dmars(void)
                        }
                }
 
-               iommu_prepare_gfx_mapping();
-
                iommu_prepare_isa();
        }
 
@@ -2330,50 +2368,40 @@ error:
        return ret;
 }
 
-static inline u64 aligned_size(u64 host_addr, size_t size)
-{
-       u64 addr;
-       addr = (host_addr & (~PAGE_MASK)) + size;
-       return PAGE_ALIGN(addr);
-}
-
-struct iova *
-iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end)
+static inline unsigned long aligned_nrpages(unsigned long host_addr,
+                                           size_t size)
 {
-       struct iova *piova;
+       host_addr &= ~PAGE_MASK;
+       host_addr += size + PAGE_SIZE - 1;
 
-       /* Make sure it's in range */
-       end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end);
-       if (!size || (IOVA_START_ADDR + size > end))
-               return NULL;
-
-       piova = alloc_iova(&domain->iovad,
-                       size >> PAGE_SHIFT, IOVA_PFN(end), 1);
-       return piova;
+       return host_addr >> VTD_PAGE_SHIFT;
 }
 
-static struct iova *
-__intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
-                  size_t size, u64 dma_mask)
+static struct iova *intel_alloc_iova(struct device *dev,
+                                    struct dmar_domain *domain,
+                                    unsigned long nrpages, uint64_t dma_mask)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct iova *iova = NULL;
 
-       if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac)
-               iova = iommu_alloc_iova(domain, size, dma_mask);
-       else {
+       /* Restrict dma_mask to the width that the iommu can handle */
+       dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
+
+       if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
                /*
                 * First try to allocate an io virtual address in
                 * DMA_BIT_MASK(32) and if that fails then try allocating
                 * from higher range
                 */
-               iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32));
-               if (!iova)
-                       iova = iommu_alloc_iova(domain, size, dma_mask);
-       }
-
-       if (!iova) {
-               printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev));
+               iova = alloc_iova(&domain->iovad, nrpages,
+                                 IOVA_PFN(DMA_BIT_MASK(32)), 1);
+               if (iova)
+                       return iova;
+       }
+       iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
+       if (unlikely(!iova)) {
+               printk(KERN_ERR "Allocating %ld-page iova for %s failed",
+                      nrpages, pci_name(pdev));
                return NULL;
        }
 
@@ -2476,14 +2504,12 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
                return 0;
 
        iommu = domain_get_iommu(domain);
-       size = aligned_size((u64)paddr, size);
+       size = aligned_nrpages(paddr, size);
 
-       iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
+       iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
        if (!iova)
                goto error;
 
-       start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
-
        /*
         * Check if DMAR supports zero-length reads on write only
         * mappings..
@@ -2499,20 +2525,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
         * might have two guest_addr mapping to the same host paddr, but this
         * is not a big problem
         */
-       ret = domain_page_mapping(domain, start_paddr,
-                                 ((u64)paddr) & PHYSICAL_PAGE_MASK,
-                                 size, prot);
+       ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
+                                paddr >> VTD_PAGE_SHIFT, size, prot);
        if (ret)
                goto error;
 
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, start_paddr,
-                                     size >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size);
        else
                iommu_flush_write_buffer(iommu);
 
-       return start_paddr + ((u64)paddr & (~PAGE_MASK));
+       start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
+       start_paddr += paddr & ~PAGE_MASK;
+       return start_paddr;
 
 error:
        if (iova)
@@ -2605,7 +2631,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_pfn, last_pfn;
        struct iova *iova;
        struct intel_iommu *iommu;
 
@@ -2618,22 +2644,25 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
        iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
-       if (!iova)
+       if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
+                     (unsigned long long)dev_addr))
                return;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
-       size = aligned_size((u64)dev_addr, size);
+       start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+       last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
 
-       pr_debug("Device %s unmapping: %zx@%llx\n",
-               pci_name(pdev), size, (unsigned long long)start_addr);
+       pr_debug("Device %s unmapping: pfn %lx-%lx\n",
+                pci_name(pdev), start_pfn, last_pfn);
 
        /*  clear the whole page */
-       dma_pte_clear_range(domain, start_addr, start_addr + size);
+       dma_pte_clear_range(domain, start_pfn, last_pfn);
+
        /* free page tables */
-       dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+       dma_pte_free_pagetable(domain, start_pfn, last_pfn);
+
        if (intel_iommu_strict) {
-               iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
-                                     size >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+                                     last_pfn - start_pfn + 1);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
@@ -2691,14 +2720,10 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
                           int nelems, enum dma_data_direction dir,
                           struct dma_attrs *attrs)
 {
-       int i;
        struct pci_dev *pdev = to_pci_dev(hwdev);
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_pfn, last_pfn;
        struct iova *iova;
-       size_t size = 0;
-       phys_addr_t addr;
-       struct scatterlist *sg;
        struct intel_iommu *iommu;
 
        if (iommu_no_mapping(pdev))
@@ -2710,22 +2735,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
        iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
-       if (!iova)
+       if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
+                     (unsigned long long)sglist[0].dma_address))
                return;
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size += aligned_size((u64)addr, sg->length);
-       }
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
+       start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+       last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
 
        /*  clear the whole page */
-       dma_pte_clear_range(domain, start_addr, start_addr + size);
+       dma_pte_clear_range(domain, start_pfn, last_pfn);
+
        /* free page tables */
-       dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+       dma_pte_free_pagetable(domain, start_pfn, last_pfn);
 
-       iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
-                             size >> VTD_PAGE_SHIFT);
+       iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+                             (last_pfn - start_pfn + 1));
 
        /* free iova */
        __free_iova(&domain->iovad, iova);
@@ -2748,17 +2772,16 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
                        enum dma_data_direction dir, struct dma_attrs *attrs)
 {
-       phys_addr_t addr;
        int i;
        struct pci_dev *pdev = to_pci_dev(hwdev);
        struct dmar_domain *domain;
        size_t size = 0;
        int prot = 0;
-       size_t offset = 0;
+       size_t offset_pfn = 0;
        struct iova *iova = NULL;
        int ret;
        struct scatterlist *sg;
-       unsigned long start_addr;
+       unsigned long start_vpfn;
        struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
@@ -2771,12 +2794,10 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 
        iommu = domain_get_iommu(domain);
 
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size += aligned_size((u64)addr, sg->length);
-       }
+       for_each_sg(sglist, sg, nelems, i)
+               size += aligned_nrpages(sg->offset, sg->length);
 
-       iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
+       iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
        if (!iova) {
                sglist->dma_length = 0;
                return 0;
@@ -2792,35 +2813,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
-       offset = 0;
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size = aligned_size((u64)addr, sg->length);
-               ret = domain_page_mapping(domain, start_addr + offset,
-                                         ((u64)addr) & PHYSICAL_PAGE_MASK,
-                                         size, prot);
-               if (ret) {
-                       /*  clear the page */
-                       dma_pte_clear_range(domain, start_addr,
-                                 start_addr + offset);
-                       /* free page tables */
-                       dma_pte_free_pagetable(domain, start_addr,
-                                 start_addr + offset);
-                       /* free iova */
-                       __free_iova(&domain->iovad, iova);
-                       return 0;
-               }
-               sg->dma_address = start_addr + offset +
-                               ((u64)addr & (~PAGE_MASK));
-               sg->dma_length = sg->length;
-               offset += size;
+       start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
+
+       ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot);
+       if (unlikely(ret)) {
+               /*  clear the page */
+               dma_pte_clear_range(domain, start_vpfn,
+                                   start_vpfn + size - 1);
+               /* free page tables */
+               dma_pte_free_pagetable(domain, start_vpfn,
+                                      start_vpfn + size - 1);
+               /* free iova */
+               __free_iova(&domain->iovad, iova);
+               return 0;
        }
 
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, start_addr,
-                                     offset >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn);
        else
                iommu_flush_write_buffer(iommu);
 
@@ -3325,7 +3335,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
        int adjust_width;
 
        init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-       spin_lock_init(&domain->mapping_lock);
        spin_lock_init(&domain->iommu_lock);
 
        domain_reserve_special_ranges(domain);
@@ -3379,8 +3388,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain)
 
 static void vm_domain_exit(struct dmar_domain *domain)
 {
-       u64 end;
-
        /* Domain 0 is reserved, so dont process it */
        if (!domain)
                return;
@@ -3388,14 +3395,12 @@ static void vm_domain_exit(struct dmar_domain *domain)
        vm_domain_remove_all_dev_info(domain);
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
-       end = DOMAIN_MAX_ADDR(domain->gaw);
-       end = end & (~VTD_PAGE_MASK);
 
        /* clear ptes */
-       dma_pte_clear_range(domain, 0, end);
+       dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        /* free page tables */
-       dma_pte_free_pagetable(domain, 0, end);
+       dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        iommu_free_vm_domain(domain);
        free_domain_mem(domain);
@@ -3504,7 +3509,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
        if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
                prot |= DMA_PTE_SNP;
 
-       max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size);
+       max_addr = iova + size;
        if (dmar_domain->max_addr < max_addr) {
                int min_agaw;
                u64 end;
@@ -3522,8 +3527,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
                }
                dmar_domain->max_addr = max_addr;
        }
-
-       ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot);
+       /* Round up size to next multiple of PAGE_SIZE, if it and
+          the low bits of hpa would take us onto the next page */
+       size = aligned_nrpages(hpa, size);
+       ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
+                                hpa >> VTD_PAGE_SHIFT, size, prot);
        return ret;
 }
 
@@ -3531,15 +3539,12 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain,
                                    unsigned long iova, size_t size)
 {
        struct dmar_domain *dmar_domain = domain->priv;
-       dma_addr_t base;
 
-       /* The address might not be aligned */
-       base = iova & VTD_PAGE_MASK;
-       size = VTD_PAGE_ALIGN(size);
-       dma_pte_clear_range(dmar_domain, base, base + size);
+       dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
+                           (iova + size - 1) >> VTD_PAGE_SHIFT);
 
-       if (dmar_domain->max_addr == base + size)
-               dmar_domain->max_addr = base;
+       if (dmar_domain->max_addr == iova + size)
+               dmar_domain->max_addr = iova;
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -3549,7 +3554,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
        struct dma_pte *pte;
        u64 phys = 0;
 
-       pte = addr_to_dma_pte(dmar_domain, iova);
+       pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT);
        if (pte)
                phys = dma_pte_addr(pte);
 
index 659421d0ca46aeab37fac76aefdee41cc6a5562d..d4ad50d737b060392fdf2c82bc80a211a57f5be1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
  *
- * Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@
 #include "i82365.h"
 
 MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_LICENSE("GPL");
 
 #define CARD_MAX_SLOTS         2
index 812f038e9bdaeea761c66dc978b583bc571bf9b0..9b3c15827e5c763208a82b212eb7ab6cc2e9919f 100644 (file)
@@ -6,7 +6,7 @@
  *     NEC VRC4173 CARDU driver for Socket Services
  *     (This device doesn't support CardBus. it is supporting only 16bit PC Card.)
  *
- * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -41,7 +41,7 @@
 #include "vrc4173_cardu.h"
 
 MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_LICENSE("GPL");
 
 static int vrc4173_cardu_slots;
index 7d77c74120c1cb646fef6af93b80aa35bc964c01..a7d96018ed8d4c471a493b62dc732dd9d79e1d19 100644 (file)
@@ -5,7 +5,7 @@
  * BRIEF MODULE DESCRIPTION
  *     Include file for NEC VRC4173 CARDU.
  *
- * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
index f11297aff854a3bf680d84c382581083e853df5d..2c839d0d21bd2011a82514b31807d2d3d6b591fc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Real Time Clock unit.
  *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
 MODULE_LICENSE("GPL v2");
 
index 25a2032bfa2615c466de3dc9bcc1f2fbd56e0ec6..70d060b7ff4f6e36ed4d090a030baf7c7da1ece9 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
 
 cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
index 74369a3f963b66bdbdbaa0b71bdd6f848a074048..c399f485aa7d1228c415c703c85ceddafcbdc0cf 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/inet.h>
 #include <linux/crypto.h>
+#include <linux/if_vlan.h>
 #include <net/dst.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
@@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
        struct cxgb3i_adapter *snic;
        int i;
 
+       if (ndev->priv_flags & IFF_802_1Q_VLAN)
+               ndev = vlan_dev_real_dev(ndev);
+
        read_lock(&cxgb3i_snic_rwlock);
        list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
                for (i = 0; i < snic->hba_cnt; i++) {
index a84072865fc2615a7a9fcce47c48b94fe05f4592..2c266c01dc5ad2848abc5df36bd3b05b1afa5f5f 100644 (file)
@@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
         * limitation for the device.  Try 40-bit first, and
         * fail to 32-bit.
         */
-       err = pci_set_dma_mask(pdev, DMA_40BIT_MASK);
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
        if (err) {
-               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "No usable DMA configuration "
                                     "aborting\n");
                        goto err_out_release_regions;
                }
-               err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "Unable to obtain 32-bit DMA "
@@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
                        goto err_out_release_regions;
                }
        } else {
-               err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "Unable to obtain 40-bit DMA "
index eabf365028568437be0fbd3acbe81abf9dc932c6..bfc996971b814009ac996b295414eacc668c5fe9 100644 (file)
@@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
                                          struct vnic_wq_copy *wq,
                                          struct fnic_io_req *io_req,
                                          struct scsi_cmnd *sc,
-                                         u32 sg_count)
+                                         int sg_count)
 {
        struct scatterlist *sg;
        struct fc_rport *rport = starget_to_rport(scsi_target(sc->device));
@@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
        char msg[2];
 
        if (sg_count) {
-               BUG_ON(sg_count < 0);
-               BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT);
-
                /* For each SGE, create a device desc entry */
                desc = io_req->sgl_list;
                for_each_sg(scsi_sglist(sc), sg, sg_count, i) {
@@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
        struct fnic *fnic;
        struct vnic_wq_copy *wq;
        int ret;
-       u32 sg_count;
+       int sg_count;
        unsigned long flags;
        unsigned long ptr;
 
index 869a11bdccbdf3cf63773b2bebc1ff1358d623a8..9928704e235f4f1d5d35c48fd877781297f78a50 100644 (file)
@@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
                                MAX_INDIRECT_BUFS);
                        hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
                }
+
+               if (hostdata->madapter_info.os_type == 3) {
+                       enable_fast_fail(hostdata);
+                       return;
+               }
        }
 
-       enable_fast_fail(hostdata);
+       send_srp_login(hostdata);
 }
 
 /**
index 2eee9e6e4fe8f975eb580329cd4814244b482a0b..292c02f810d04a4bc7d66f27a77209a302fe5e14 100644 (file)
@@ -3670,13 +3670,14 @@ static void
 fc_bsg_goose_queue(struct fc_rport *rport)
 {
        int flagset;
+       unsigned long flags;
 
        if (!rport->rqst_q)
                return;
 
        get_device(&rport->dev);
 
-       spin_lock(rport->rqst_q->queue_lock);
+       spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
        flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
                  !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
        if (flagset)
@@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport)
        __blk_run_queue(rport->rqst_q);
        if (flagset)
                queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
-       spin_unlock(rport->rqst_q->queue_lock);
+       spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
 
        put_device(&rport->dev);
 }
index 97f3158fa7b546700ab670f3373598c5895cb546..27e84e4b1fa98857d571f3abafdfe9f4b03cf7ad 100644 (file)
@@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev)
 
        host = ncr_attach(&zalon7xx_template, unit, &device);
        if (!host)
-               goto fail;
+               return -ENODEV;
 
        if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
          dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
index 0573f3b5175e463f1675e4d4bdd5b0dceb17c47c..dac550e57c29c192e60ec351f191adad98e2f4da 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2004-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  Based on drivers/serial/8250.c, by Russell King.
  *
index 3fd3e3b412b6598d0c32a70bc691ced97769a596..3c6feed46f6ea48b12d3083e1d95f1c33921029e 100644 (file)
@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = {
 
 static inline u32 ssb_irqflag(struct ssb_device *dev)
 {
-       return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+       u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
+       if (tpsflag)
+               return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+       else
+               /* not irq supported */
+               return 0x3f;
+}
+
+static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
+{
+       struct ssb_bus *bus = rdev->bus;
+       int i;
+       for (i = 0; i < bus->nr_devices; i++) {
+               struct ssb_device *dev;
+               dev = &(bus->devices[i]);
+               if (ssb_irqflag(dev) == irqflag)
+                       return dev;
+       }
+       return NULL;
 }
 
 /* Get the MIPS IRQ assignment for a specified device.
  * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ * If not supported, 6 is returned.
  */
 unsigned int ssb_mips_irq(struct ssb_device *dev)
 {
        struct ssb_bus *bus = dev->bus;
+       struct ssb_device *mdev = bus->mipscore.dev;
        u32 irqflag;
        u32 ipsflag;
        u32 tmp;
        unsigned int irq;
 
        irqflag = ssb_irqflag(dev);
+       if (irqflag == 0x3f)
+               return 6;
        ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
        for (irq = 1; irq <= 4; irq++) {
                tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]);
                if (tmp == irqflag)
                        break;
        }
-       if (irq == 5)
-               irq = 0;
+       if (irq == 5) {
+               if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))
+                       irq = 0;
+       }
 
        return irq;
 }
@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
        struct ssb_device *mdev = bus->mipscore.dev;
        u32 irqflag = ssb_irqflag(dev);
 
+       BUG_ON(oldirq == 6);
+
        dev->irq = irq + 2;
 
-       ssb_dprintk(KERN_INFO PFX
-                   "set_irq: core 0x%04x, irq %d => %d\n",
-                   dev->id.coreid, oldirq, irq);
        /* clear the old irq */
        if (oldirq == 0)
                ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)));
-       else
+       else if (oldirq != 5)
                clear_irq(bus, oldirq);
 
        /* assign the new one */
        if (irq == 0) {
                ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC)));
        } else {
+               u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG);
+               if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) {
+                       u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq];
+                       struct ssb_device *olddev = find_device(dev, oldipsflag);
+                       if (olddev)
+                               set_irq(olddev, 0);
+               }
                irqflag <<= ipsflag_irq_shift[irq];
-               irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]);
+               irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
                ssb_write32(mdev, SSB_IPSFLAG, irqflag);
        }
+       ssb_dprintk(KERN_INFO PFX
+                   "set_irq: core 0x%04x, irq %d => %d\n",
+                   dev->id.coreid, oldirq+2, irq+2);
+}
+
+static void print_irq(struct ssb_device *dev, unsigned int irq)
+{
+       int i;
+       static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+       ssb_dprintk(KERN_INFO PFX
+               "core 0x%04x, irq :", dev->id.coreid);
+       for (i = 0; i <= 6; i++) {
+               ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
+       }
+       ssb_dprintk("\n");
+}
+
+static void dump_irq(struct ssb_bus *bus)
+{
+       int i;
+       for (i = 0; i < bus->nr_devices; i++) {
+               struct ssb_device *dev;
+               dev = &(bus->devices[i]);
+               print_irq(dev, ssb_mips_irq(dev));
+       }
 }
 
 static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
@@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 
        /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
        for (irq = 2, i = 0; i < bus->nr_devices; i++) {
+               int mips_irq;
                dev = &(bus->devices[i]);
-               dev->irq = ssb_mips_irq(dev) + 2;
+               mips_irq = ssb_mips_irq(dev);
+               if (mips_irq > 4)
+                       dev->irq = 0;
+               else
+                       dev->irq = mips_irq + 2;
+               if (dev->irq > 5)
+                       continue;
                switch (dev->id.coreid) {
                case SSB_DEV_USB11_HOST:
                        /* shouldn't need a separate irq line for non-4710, most of them have a proper
                         * external usb controller on the pci */
                        if ((bus->chip_id == 0x4710) && (irq <= 4)) {
                                set_irq(dev, irq++);
-                               break;
                        }
+                       break;
                        /* fallthrough */
                case SSB_DEV_PCI:
                case SSB_DEV_ETHERNET:
@@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
                        }
                }
        }
+       ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
+       dump_irq(bus);
 
        ssb_mips_serial_init(mcore);
        ssb_mips_flash_detect(mcore);
index 7bad24ed04ef5eb2dc8a1e2bec9a56c902e45f7a..108b89e09a80dbdd8c8593f5977a6b8b1a1b7586 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt server LCD frame buffer driver.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 7f88628a1a72e3808c6f96d47bc0ba9e363ade4c..6e4f6c50a120dfcb78eb5f26dc4301936589cd0f 100644 (file)
@@ -299,8 +299,8 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
                                           "btrfs-%s-%d", workers->name,
                                           workers->num_workers + i);
                if (IS_ERR(worker->task)) {
-                       kfree(worker);
                        ret = PTR_ERR(worker->task);
+                       kfree(worker);
                        goto fail;
                }
 
index 2779c2f5360ac6ea4678db5e14aa135c93507b4c..98a87383871722fbddc36590cae9e60a512ef53a 100644 (file)
@@ -2074,8 +2074,7 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
-int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
-                       *root);
+int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref);
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
index edc7d208c5ce6032fc7de520f5f4a00739755fec..a5aca3997d426da09c87e33642916284eca135b6 100644 (file)
@@ -990,15 +990,13 @@ static inline int extent_ref_type(u64 parent, u64 owner)
        return type;
 }
 
-static int find_next_key(struct btrfs_path *path, struct btrfs_key *key)
+static int find_next_key(struct btrfs_path *path, int level,
+                        struct btrfs_key *key)
 
 {
-       int level;
-       BUG_ON(!path->keep_locks);
-       for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
+       for (; level < BTRFS_MAX_LEVEL; level++) {
                if (!path->nodes[level])
                        break;
-               btrfs_assert_tree_locked(path->nodes[level]);
                if (path->slots[level] + 1 >=
                    btrfs_header_nritems(path->nodes[level]))
                        continue;
@@ -1158,7 +1156,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
                 * For simplicity, we just do not add new inline back
                 * ref if there is any kind of item for this block
                 */
-               if (find_next_key(path, &key) == 0 && key.objectid == bytenr &&
+               if (find_next_key(path, 0, &key) == 0 &&
+                   key.objectid == bytenr &&
                    key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) {
                        err = -EAGAIN;
                        goto out;
@@ -2697,7 +2696,7 @@ again:
 
                printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
                       ", %llu bytes_used, %llu bytes_reserved, "
-                      "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
+                      "%llu bytes_pinned, %llu bytes_readonly, %llu may use "
                       "%llu total\n", (unsigned long long)bytes,
                       (unsigned long long)data_sinfo->bytes_delalloc,
                       (unsigned long long)data_sinfo->bytes_used,
@@ -4128,6 +4127,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
        return buf;
 }
 
+#if 0
 int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root, struct extent_buffer *leaf)
 {
@@ -4171,8 +4171,6 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-#if 0
-
 static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root,
                                        struct btrfs_leaf_ref *ref)
@@ -4553,262 +4551,471 @@ out:
 }
 #endif
 
+struct walk_control {
+       u64 refs[BTRFS_MAX_LEVEL];
+       u64 flags[BTRFS_MAX_LEVEL];
+       struct btrfs_key update_progress;
+       int stage;
+       int level;
+       int shared_level;
+       int update_ref;
+       int keep_locks;
+};
+
+#define DROP_REFERENCE 1
+#define UPDATE_BACKREF 2
+
 /*
- * helper function for drop_subtree, this function is similar to
- * walk_down_tree. The main difference is that it checks reference
- * counts while tree blocks are locked.
+ * hepler to process tree block while walking down the tree.
+ *
+ * when wc->stage == DROP_REFERENCE, this function checks
+ * reference count of the block. if the block is shared and
+ * we need update back refs for the subtree rooted at the
+ * block, this function changes wc->stage to UPDATE_BACKREF
+ *
+ * when wc->stage == UPDATE_BACKREF, this function updates
+ * back refs for pointers in the block.
+ *
+ * NOTE: return value 1 means we should stop walking down.
  */
-static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
+static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
-                                  struct btrfs_path *path, int *level)
+                                  struct btrfs_path *path,
+                                  struct walk_control *wc)
 {
-       struct extent_buffer *next;
-       struct extent_buffer *cur;
-       struct extent_buffer *parent;
-       u64 bytenr;
-       u64 ptr_gen;
-       u64 refs;
-       u64 flags;
-       u32 blocksize;
+       int level = wc->level;
+       struct extent_buffer *eb = path->nodes[level];
+       struct btrfs_key key;
+       u64 flag = BTRFS_BLOCK_FLAG_FULL_BACKREF;
        int ret;
 
-       cur = path->nodes[*level];
-       ret = btrfs_lookup_extent_info(trans, root, cur->start, cur->len,
-                                      &refs, &flags);
-       BUG_ON(ret);
-       if (refs > 1)
-               goto out;
+       if (wc->stage == UPDATE_BACKREF &&
+           btrfs_header_owner(eb) != root->root_key.objectid)
+               return 1;
 
-       BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
+       /*
+        * when reference count of tree block is 1, it won't increase
+        * again. once full backref flag is set, we never clear it.
+        */
+       if ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) ||
+           (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag))) {
+               BUG_ON(!path->locks[level]);
+               ret = btrfs_lookup_extent_info(trans, root,
+                                              eb->start, eb->len,
+                                              &wc->refs[level],
+                                              &wc->flags[level]);
+               BUG_ON(ret);
+               BUG_ON(wc->refs[level] == 0);
+       }
 
-       while (*level >= 0) {
-               cur = path->nodes[*level];
-               if (*level == 0) {
-                       ret = btrfs_drop_leaf_ref(trans, root, cur);
-                       BUG_ON(ret);
-                       clean_tree_block(trans, root, cur);
-                       break;
-               }
-               if (path->slots[*level] >= btrfs_header_nritems(cur)) {
-                       clean_tree_block(trans, root, cur);
-                       break;
+       if (wc->stage == DROP_REFERENCE &&
+           wc->update_ref && wc->refs[level] > 1) {
+               BUG_ON(eb == root->node);
+               BUG_ON(path->slots[level] > 0);
+               if (level == 0)
+                       btrfs_item_key_to_cpu(eb, &key, path->slots[level]);
+               else
+                       btrfs_node_key_to_cpu(eb, &key, path->slots[level]);
+               if (btrfs_header_owner(eb) == root->root_key.objectid &&
+                   btrfs_comp_cpu_keys(&key, &wc->update_progress) >= 0) {
+                       wc->stage = UPDATE_BACKREF;
+                       wc->shared_level = level;
                }
+       }
 
-               bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
-               blocksize = btrfs_level_size(root, *level - 1);
-               ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
+       if (wc->stage == DROP_REFERENCE) {
+               if (wc->refs[level] > 1)
+                       return 1;
 
-               next = read_tree_block(root, bytenr, blocksize, ptr_gen);
-               btrfs_tree_lock(next);
-               btrfs_set_lock_blocking(next);
+               if (path->locks[level] && !wc->keep_locks) {
+                       btrfs_tree_unlock(eb);
+                       path->locks[level] = 0;
+               }
+               return 0;
+       }
 
-               ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
-                                              &refs, &flags);
+       /* wc->stage == UPDATE_BACKREF */
+       if (!(wc->flags[level] & flag)) {
+               BUG_ON(!path->locks[level]);
+               ret = btrfs_inc_ref(trans, root, eb, 1);
                BUG_ON(ret);
-               if (refs > 1) {
-                       parent = path->nodes[*level];
-                       ret = btrfs_free_extent(trans, root, bytenr,
-                                               blocksize, parent->start,
-                                               btrfs_header_owner(parent),
-                                               *level - 1, 0);
+               ret = btrfs_dec_ref(trans, root, eb, 0);
+               BUG_ON(ret);
+               ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
+                                                 eb->len, flag, 0);
+               BUG_ON(ret);
+               wc->flags[level] |= flag;
+       }
+
+       /*
+        * the block is shared by multiple trees, so it's not good to
+        * keep the tree lock
+        */
+       if (path->locks[level] && level > 0) {
+               btrfs_tree_unlock(eb);
+               path->locks[level] = 0;
+       }
+       return 0;
+}
+
+/*
+ * hepler to process tree block while walking up the tree.
+ *
+ * when wc->stage == DROP_REFERENCE, this function drops
+ * reference count on the block.
+ *
+ * when wc->stage == UPDATE_BACKREF, this function changes
+ * wc->stage back to DROP_REFERENCE if we changed wc->stage
+ * to UPDATE_BACKREF previously while processing the block.
+ *
+ * NOTE: return value 1 means we should stop walking up.
+ */
+static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct btrfs_path *path,
+                                struct walk_control *wc)
+{
+       int ret = 0;
+       int level = wc->level;
+       struct extent_buffer *eb = path->nodes[level];
+       u64 parent = 0;
+
+       if (wc->stage == UPDATE_BACKREF) {
+               BUG_ON(wc->shared_level < level);
+               if (level < wc->shared_level)
+                       goto out;
+
+               BUG_ON(wc->refs[level] <= 1);
+               ret = find_next_key(path, level + 1, &wc->update_progress);
+               if (ret > 0)
+                       wc->update_ref = 0;
+
+               wc->stage = DROP_REFERENCE;
+               wc->shared_level = -1;
+               path->slots[level] = 0;
+
+               /*
+                * check reference count again if the block isn't locked.
+                * we should start walking down the tree again if reference
+                * count is one.
+                */
+               if (!path->locks[level]) {
+                       BUG_ON(level == 0);
+                       btrfs_tree_lock(eb);
+                       btrfs_set_lock_blocking(eb);
+                       path->locks[level] = 1;
+
+                       ret = btrfs_lookup_extent_info(trans, root,
+                                                      eb->start, eb->len,
+                                                      &wc->refs[level],
+                                                      &wc->flags[level]);
                        BUG_ON(ret);
-                       path->slots[*level]++;
-                       btrfs_tree_unlock(next);
-                       free_extent_buffer(next);
-                       continue;
+                       BUG_ON(wc->refs[level] == 0);
+                       if (wc->refs[level] == 1) {
+                               btrfs_tree_unlock(eb);
+                               path->locks[level] = 0;
+                               return 1;
+                       }
+               } else {
+                       BUG_ON(level != 0);
                }
+       }
 
-               BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
+       /* wc->stage == DROP_REFERENCE */
+       BUG_ON(wc->refs[level] > 1 && !path->locks[level]);
 
-               *level = btrfs_header_level(next);
-               path->nodes[*level] = next;
-               path->slots[*level] = 0;
-               path->locks[*level] = 1;
-               cond_resched();
+       if (wc->refs[level] == 1) {
+               if (level == 0) {
+                       if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                               ret = btrfs_dec_ref(trans, root, eb, 1);
+                       else
+                               ret = btrfs_dec_ref(trans, root, eb, 0);
+                       BUG_ON(ret);
+               }
+               /* make block locked assertion in clean_tree_block happy */
+               if (!path->locks[level] &&
+                   btrfs_header_generation(eb) == trans->transid) {
+                       btrfs_tree_lock(eb);
+                       btrfs_set_lock_blocking(eb);
+                       path->locks[level] = 1;
+               }
+               clean_tree_block(trans, root, eb);
+       }
+
+       if (eb == root->node) {
+               if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                       parent = eb->start;
+               else
+                       BUG_ON(root->root_key.objectid !=
+                              btrfs_header_owner(eb));
+       } else {
+               if (wc->flags[level + 1] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                       parent = path->nodes[level + 1]->start;
+               else
+                       BUG_ON(root->root_key.objectid !=
+                              btrfs_header_owner(path->nodes[level + 1]));
        }
-out:
-       if (path->nodes[*level] == root->node)
-               parent = path->nodes[*level];
-       else
-               parent = path->nodes[*level + 1];
-       bytenr = path->nodes[*level]->start;
-       blocksize = path->nodes[*level]->len;
 
-       ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent->start,
-                               btrfs_header_owner(parent), *level, 0);
+       ret = btrfs_free_extent(trans, root, eb->start, eb->len, parent,
+                               root->root_key.objectid, level, 0);
        BUG_ON(ret);
+out:
+       wc->refs[level] = 0;
+       wc->flags[level] = 0;
+       return ret;
+}
+
+static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
+                                  struct btrfs_root *root,
+                                  struct btrfs_path *path,
+                                  struct walk_control *wc)
+{
+       struct extent_buffer *next;
+       struct extent_buffer *cur;
+       u64 bytenr;
+       u64 ptr_gen;
+       u32 blocksize;
+       int level = wc->level;
+       int ret;
+
+       while (level >= 0) {
+               cur = path->nodes[level];
+               BUG_ON(path->slots[level] >= btrfs_header_nritems(cur));
 
-       if (path->locks[*level]) {
-               btrfs_tree_unlock(path->nodes[*level]);
-               path->locks[*level] = 0;
+               ret = walk_down_proc(trans, root, path, wc);
+               if (ret > 0)
+                       break;
+
+               if (level == 0)
+                       break;
+
+               bytenr = btrfs_node_blockptr(cur, path->slots[level]);
+               blocksize = btrfs_level_size(root, level - 1);
+               ptr_gen = btrfs_node_ptr_generation(cur, path->slots[level]);
+
+               next = read_tree_block(root, bytenr, blocksize, ptr_gen);
+               btrfs_tree_lock(next);
+               btrfs_set_lock_blocking(next);
+
+               level--;
+               BUG_ON(level != btrfs_header_level(next));
+               path->nodes[level] = next;
+               path->slots[level] = 0;
+               path->locks[level] = 1;
+               wc->level = level;
        }
-       free_extent_buffer(path->nodes[*level]);
-       path->nodes[*level] = NULL;
-       *level += 1;
-       cond_resched();
        return 0;
 }
 
-/*
- * helper for dropping snapshots.  This walks back up the tree in the path
- * to find the first node higher up where we haven't yet gone through
- * all the slots
- */
 static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 struct btrfs_path *path,
-                                int *level, int max_level)
+                                struct walk_control *wc, int max_level)
 {
-       struct btrfs_root_item *root_item = &root->root_item;
-       int i;
-       int slot;
+       int level = wc->level;
        int ret;
 
-       for (i = *level; i < max_level && path->nodes[i]; i++) {
-               slot = path->slots[i];
-               if (slot + 1 < btrfs_header_nritems(path->nodes[i])) {
-                       /*
-                        * there is more work to do in this level.
-                        * Update the drop_progress marker to reflect
-                        * the work we've done so far, and then bump
-                        * the slot number
-                        */
-                       path->slots[i]++;
-                       WARN_ON(*level == 0);
-                       if (max_level == BTRFS_MAX_LEVEL) {
-                               btrfs_node_key(path->nodes[i],
-                                              &root_item->drop_progress,
-                                              path->slots[i]);
-                               root_item->drop_level = i;
-                       }
-                       *level = i;
+       path->slots[level] = btrfs_header_nritems(path->nodes[level]);
+       while (level < max_level && path->nodes[level]) {
+               wc->level = level;
+               if (path->slots[level] + 1 <
+                   btrfs_header_nritems(path->nodes[level])) {
+                       path->slots[level]++;
                        return 0;
                } else {
-                       struct extent_buffer *parent;
-
-                       /*
-                        * this whole node is done, free our reference
-                        * on it and go up one level
-                        */
-                       if (path->nodes[*level] == root->node)
-                               parent = path->nodes[*level];
-                       else
-                               parent = path->nodes[*level + 1];
+                       ret = walk_up_proc(trans, root, path, wc);
+                       if (ret > 0)
+                               return 0;
 
-                       clean_tree_block(trans, root, path->nodes[i]);
-                       ret = btrfs_free_extent(trans, root,
-                                               path->nodes[i]->start,
-                                               path->nodes[i]->len,
-                                               parent->start,
-                                               btrfs_header_owner(parent),
-                                               *level, 0);
-                       BUG_ON(ret);
-                       if (path->locks[*level]) {
-                               btrfs_tree_unlock(path->nodes[i]);
-                               path->locks[i] = 0;
+                       if (path->locks[level]) {
+                               btrfs_tree_unlock(path->nodes[level]);
+                               path->locks[level] = 0;
                        }
-                       free_extent_buffer(path->nodes[i]);
-                       path->nodes[i] = NULL;
-                       *level = i + 1;
+                       free_extent_buffer(path->nodes[level]);
+                       path->nodes[level] = NULL;
+                       level++;
                }
        }
        return 1;
 }
 
 /*
- * drop the reference count on the tree rooted at 'snap'.  This traverses
- * the tree freeing any blocks that have a ref count of zero after being
- * decremented.
+ * drop a subvolume tree.
+ *
+ * this function traverses the tree freeing any blocks that only
+ * referenced by the tree.
+ *
+ * when a shared tree block is found. this function decreases its
+ * reference count by one. if update_ref is true, this function
+ * also make sure backrefs for the shared block and all lower level
+ * blocks are properly updated.
  */
-int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
-                       *root)
+int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref)
 {
-       int ret = 0;
-       int wret;
-       int level;
        struct btrfs_path *path;
-       int update_count;
+       struct btrfs_trans_handle *trans;
+       struct btrfs_root *tree_root = root->fs_info->tree_root;
        struct btrfs_root_item *root_item = &root->root_item;
+       struct walk_control *wc;
+       struct btrfs_key key;
+       int err = 0;
+       int ret;
+       int level;
 
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
-       level = btrfs_header_level(root->node);
+       wc = kzalloc(sizeof(*wc), GFP_NOFS);
+       BUG_ON(!wc);
+
+       trans = btrfs_start_transaction(tree_root, 1);
+
        if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) {
+               level = btrfs_header_level(root->node);
                path->nodes[level] = btrfs_lock_root_node(root);
                btrfs_set_lock_blocking(path->nodes[level]);
                path->slots[level] = 0;
                path->locks[level] = 1;
+               memset(&wc->update_progress, 0,
+                      sizeof(wc->update_progress));
        } else {
-               struct btrfs_key key;
-               struct btrfs_disk_key found_key;
-               struct extent_buffer *node;
-
                btrfs_disk_key_to_cpu(&key, &root_item->drop_progress);
+               memcpy(&wc->update_progress, &key,
+                      sizeof(wc->update_progress));
+
                level = root_item->drop_level;
+               BUG_ON(level == 0);
                path->lowest_level = level;
-               wret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-               if (wret < 0) {
-                       ret = wret;
+               ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+               path->lowest_level = 0;
+               if (ret < 0) {
+                       err = ret;
                        goto out;
                }
-               node = path->nodes[level];
-               btrfs_node_key(node, &found_key, path->slots[level]);
-               WARN_ON(memcmp(&found_key, &root_item->drop_progress,
-                              sizeof(found_key)));
+               btrfs_node_key_to_cpu(path->nodes[level], &key,
+                                     path->slots[level]);
+               WARN_ON(memcmp(&key, &wc->update_progress, sizeof(key)));
+
                /*
                 * unlock our path, this is safe because only this
                 * function is allowed to delete this snapshot
                 */
                btrfs_unlock_up_safe(path, 0);
+
+               level = btrfs_header_level(root->node);
+               while (1) {
+                       btrfs_tree_lock(path->nodes[level]);
+                       btrfs_set_lock_blocking(path->nodes[level]);
+
+                       ret = btrfs_lookup_extent_info(trans, root,
+                                               path->nodes[level]->start,
+                                               path->nodes[level]->len,
+                                               &wc->refs[level],
+                                               &wc->flags[level]);
+                       BUG_ON(ret);
+                       BUG_ON(wc->refs[level] == 0);
+
+                       if (level == root_item->drop_level)
+                               break;
+
+                       btrfs_tree_unlock(path->nodes[level]);
+                       WARN_ON(wc->refs[level] != 1);
+                       level--;
+               }
        }
+
+       wc->level = level;
+       wc->shared_level = -1;
+       wc->stage = DROP_REFERENCE;
+       wc->update_ref = update_ref;
+       wc->keep_locks = 0;
+
        while (1) {
-               unsigned long update;
-               wret = walk_down_tree(trans, root, path, &level);
-               if (wret > 0)
+               ret = walk_down_tree(trans, root, path, wc);
+               if (ret < 0) {
+                       err = ret;
                        break;
-               if (wret < 0)
-                       ret = wret;
+               }
 
-               wret = walk_up_tree(trans, root, path, &level,
-                                   BTRFS_MAX_LEVEL);
-               if (wret > 0)
+               ret = walk_up_tree(trans, root, path, wc, BTRFS_MAX_LEVEL);
+               if (ret < 0) {
+                       err = ret;
                        break;
-               if (wret < 0)
-                       ret = wret;
-               if (trans->transaction->in_commit ||
-                   trans->transaction->delayed_refs.flushing) {
-                       ret = -EAGAIN;
+               }
+
+               if (ret > 0) {
+                       BUG_ON(wc->stage != DROP_REFERENCE);
                        break;
                }
-               for (update_count = 0; update_count < 16; update_count++) {
+
+               if (wc->stage == DROP_REFERENCE) {
+                       level = wc->level;
+                       btrfs_node_key(path->nodes[level],
+                                      &root_item->drop_progress,
+                                      path->slots[level]);
+                       root_item->drop_level = level;
+               }
+
+               BUG_ON(wc->level == 0);
+               if (trans->transaction->in_commit ||
+                   trans->transaction->delayed_refs.flushing) {
+                       ret = btrfs_update_root(trans, tree_root,
+                                               &root->root_key,
+                                               root_item);
+                       BUG_ON(ret);
+
+                       btrfs_end_transaction(trans, tree_root);
+                       trans = btrfs_start_transaction(tree_root, 1);
+               } else {
+                       unsigned long update;
                        update = trans->delayed_ref_updates;
                        trans->delayed_ref_updates = 0;
                        if (update)
-                               btrfs_run_delayed_refs(trans, root, update);
-                       else
-                               break;
+                               btrfs_run_delayed_refs(trans, tree_root,
+                                                      update);
                }
        }
+       btrfs_release_path(root, path);
+       BUG_ON(err);
+
+       ret = btrfs_del_root(trans, tree_root, &root->root_key);
+       BUG_ON(ret);
+
+       free_extent_buffer(root->node);
+       free_extent_buffer(root->commit_root);
+       kfree(root);
 out:
+       btrfs_end_transaction(trans, tree_root);
+       kfree(wc);
        btrfs_free_path(path);
-       return ret;
+       return err;
 }
 
+/*
+ * drop subtree rooted at tree block 'node'.
+ *
+ * NOTE: this function will unlock and release tree block 'node'
+ */
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
                        struct extent_buffer *parent)
 {
        struct btrfs_path *path;
+       struct walk_control *wc;
        int level;
        int parent_level;
        int ret = 0;
        int wret;
 
+       BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID);
+
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
+       wc = kzalloc(sizeof(*wc), GFP_NOFS);
+       BUG_ON(!wc);
+
        btrfs_assert_tree_locked(parent);
        parent_level = btrfs_header_level(parent);
        extent_buffer_get(parent);
@@ -4817,24 +5024,33 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 
        btrfs_assert_tree_locked(node);
        level = btrfs_header_level(node);
-       extent_buffer_get(node);
        path->nodes[level] = node;
        path->slots[level] = 0;
+       path->locks[level] = 1;
+
+       wc->refs[parent_level] = 1;
+       wc->flags[parent_level] = BTRFS_BLOCK_FLAG_FULL_BACKREF;
+       wc->level = level;
+       wc->shared_level = -1;
+       wc->stage = DROP_REFERENCE;
+       wc->update_ref = 0;
+       wc->keep_locks = 1;
 
        while (1) {
-               wret = walk_down_tree(trans, root, path, &level);
-               if (wret < 0)
+               wret = walk_down_tree(trans, root, path, wc);
+               if (wret < 0) {
                        ret = wret;
-               if (wret != 0)
                        break;
+               }
 
-               wret = walk_up_tree(trans, root, path, &level, parent_level);
+               wret = walk_up_tree(trans, root, path, wc, parent_level);
                if (wret < 0)
                        ret = wret;
                if (wret != 0)
                        break;
        }
 
+       kfree(wc);
        btrfs_free_path(path);
        return ret;
 }
index 126477eaecf56f074a03581c17079d6b985caa81..7c3cd248d8d6151ce5a89d876c2541b2abf73179 100644 (file)
@@ -151,7 +151,10 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans,
        }
        if (end_pos > isize) {
                i_size_write(inode, end_pos);
-               btrfs_update_inode(trans, root, inode);
+               /* we've only changed i_size in ram, and we haven't updated
+                * the disk i_size.  There is no need to log the inode
+                * at this time.
+                */
        }
        err = btrfs_end_transaction(trans, root);
 out_unlock:
index dbe1aabf96cd918d43e31160e5953621f8835983..7ffa3d34ea1949ed97c77cb343bb8e32283bb12f 100644 (file)
@@ -3580,12 +3580,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                owner = 1;
        BTRFS_I(inode)->block_group =
                        btrfs_find_block_group(root, 0, alloc_hint, owner);
-       if ((mode & S_IFREG)) {
-               if (btrfs_test_opt(root, NODATASUM))
-                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-               if (btrfs_test_opt(root, NODATACOW))
-                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
-       }
 
        key[0].objectid = objectid;
        btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
@@ -3640,6 +3634,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 
        btrfs_inherit_iflags(inode, dir);
 
+       if ((mode & S_IFREG)) {
+               if (btrfs_test_opt(root, NODATASUM))
+                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
+               if (btrfs_test_opt(root, NODATACOW))
+                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
+       }
+
        insert_inode_hash(inode);
        inode_tree_add(inode);
        return inode;
@@ -5082,6 +5083,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
        struct extent_map *em;
        struct btrfs_trans_handle *trans;
+       struct btrfs_root *root;
        int ret;
 
        alloc_start = offset & ~mask;
@@ -5100,6 +5102,13 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                        goto out;
        }
 
+       root = BTRFS_I(inode)->root;
+
+       ret = btrfs_check_data_free_space(root, inode,
+                                         alloc_end - alloc_start);
+       if (ret)
+               goto out;
+
        locked_end = alloc_end - 1;
        while (1) {
                struct btrfs_ordered_extent *ordered;
@@ -5107,7 +5116,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
                if (!trans) {
                        ret = -EIO;
-                       goto out;
+                       goto out_free;
                }
 
                /* the extent lock is ordered inside the running
@@ -5168,6 +5177,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                      GFP_NOFS);
 
        btrfs_end_transaction(trans, BTRFS_I(inode)->root);
+out_free:
+       btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
 out:
        mutex_unlock(&inode->i_mutex);
        return ret;
index eff18f5b53620f20a392f9c57a80c8897c61d317..9f4db848db10dcb24c40ebe2529b3ff609c9cc1b 100644 (file)
@@ -1028,7 +1028,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                                struct btrfs_file_extent_item);
                        comp = btrfs_file_extent_compression(leaf, extent);
                        type = btrfs_file_extent_type(leaf, extent);
-                       if (type == BTRFS_FILE_EXTENT_REG) {
+                       if (type == BTRFS_FILE_EXTENT_REG ||
+                           type == BTRFS_FILE_EXTENT_PREALLOC) {
                                disko = btrfs_file_extent_disk_bytenr(leaf,
                                                                      extent);
                                diskl = btrfs_file_extent_disk_num_bytes(leaf,
@@ -1051,7 +1052,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                        new_key.objectid = inode->i_ino;
                        new_key.offset = key.offset + destoff - off;
 
-                       if (type == BTRFS_FILE_EXTENT_REG) {
+                       if (type == BTRFS_FILE_EXTENT_REG ||
+                           type == BTRFS_FILE_EXTENT_PREALLOC) {
                                ret = btrfs_insert_empty_item(trans, root, path,
                                                              &new_key, size);
                                if (ret)
index b23dc209ae103192bf4eea8ab6ca70f27adda11e..008397934778d457f7d90c3fbd03955fab230639 100644 (file)
@@ -1788,7 +1788,7 @@ static void merge_func(struct btrfs_work *work)
                btrfs_end_transaction(trans, root);
        }
 
-       btrfs_drop_dead_root(reloc_root);
+       btrfs_drop_snapshot(reloc_root, 0);
 
        if (atomic_dec_and_test(async->num_pending))
                complete(async->done);
@@ -2075,9 +2075,6 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 
                        ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
                        BUG_ON(ret);
-
-                       btrfs_tree_unlock(eb);
-                       free_extent_buffer(eb);
                }
                if (!lowest) {
                        btrfs_tree_unlock(upper->eb);
index 4e83457ea253e798ccfc8cb1d493ad7e48daa2bd..2dbf1c1f56ee41b73068c54ee7c345a969b7f38e 100644 (file)
@@ -593,6 +593,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
        return 0;
 }
 
+#if 0
 /*
  * when dropping snapshots, we generate a ton of delayed refs, and it makes
  * sense not to join the transaction while it is trying to flush the current
@@ -681,6 +682,7 @@ int btrfs_drop_dead_root(struct btrfs_root *root)
        btrfs_btree_balance_dirty(tree_root, nr);
        return ret;
 }
+#endif
 
 /*
  * new snapshots need to be created at a very specific time in the
@@ -1081,7 +1083,7 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)
        while (!list_empty(&list)) {
                root = list_entry(list.next, struct btrfs_root, root_list);
                list_del_init(&root->root_list);
-               btrfs_drop_dead_root(root);
+               btrfs_drop_snapshot(root, 0);
        }
        return 0;
 }
index 4145083dcf8817ed883652939cac1faa4dfd7cac..23341c1063bcd05fb2841dc6b49d0a91eef36293 100644 (file)
@@ -678,7 +678,6 @@ __be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                        int access, struct file **filp)
 {
-       const struct cred *cred = current_cred();
        struct dentry   *dentry;
        struct inode    *inode;
        int             flags = O_RDONLY|O_LARGEFILE;
@@ -733,7 +732,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                vfs_dq_init(inode);
        }
        *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
-                           flags, cred);
+                           flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
        else
index ff231ad23895ea179a5507ace2e4ca5c54db1470..ff27a2965844cbc20ea56279cc419ea1c584faf5 100644 (file)
@@ -296,12 +296,15 @@ static int inotify_fasync(int fd, struct file *file, int on)
 static int inotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
+       struct user_struct *user = group->inotify_data.user;
 
        fsnotify_clear_marks_by_group(group);
 
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
        fsnotify_put_group(group);
 
+       atomic_dec(&user->inotify_devs);
+
        return 0;
 }
 
index dccdbed05848f8a1a47a6834f713bbc8c76922a1..a553f1041cf1e1fe7210c92e5be2e5159975a65d 100644 (file)
        . = ALIGN(align);                                               \
        *(.data.cacheline_aligned)
 
-#define INIT_TASK(align)                                               \
+#define INIT_TASK_DATA(align)                                          \
        . = ALIGN(align);                                               \
        *(.data.init_task)
 
 /*
  * Init task
  */
-#define INIT_TASK_DATA(align)                                          \
+#define INIT_TASK_DATA_SECTION(align)                                  \
        . = ALIGN(align);                                               \
        .data.init_task : {                                             \
-               INIT_TASK                                               \
+               INIT_TASK_DATA(align)                                   \
        }
 
 #ifdef CONFIG_CONSTRUCTORS
  * matches the requirment of PAGE_ALIGNED_DATA.
  *
  * use 0 as page_align if page_aligned data is not used */
-#define RW_DATA_SECTION(cacheline, nosave, pagealigned, inittask)      \
+#define RW_DATA_SECTION(cacheline, pagealigned, inittask)              \
        . = ALIGN(PAGE_SIZE);                                           \
        .data : AT(ADDR(.data) - LOAD_OFFSET) {                         \
-               INIT_TASK(inittask)                                     \
+               INIT_TASK_DATA(inittask)                                \
                CACHELINE_ALIGNED_DATA(cacheline)                       \
                READ_MOSTLY_DATA(cacheline)                             \
                DATA_DATA                                               \
                CONSTRUCTORS                                            \
-               NOSAVE_DATA(nosave)                                     \
+               NOSAVE_DATA                                             \
                PAGE_ALIGNED_DATA(pagealigned)                          \
        }
 
index 5368fbdc78018c573c9f20a1dab76adbc8cb0f24..7fc01b13be43cfdd7b089b2e8498971f6440d253 100644 (file)
@@ -183,5 +183,8 @@ extern struct cred init_cred;
        LIST_HEAD_INIT(cpu_timers[2]),                                  \
 }
 
+/* Attach to the init_task data structure for proper alignment */
+#define __init_task_data __attribute__((__section__(".data.init_task")))
+
 
 #endif
index fee9e59649c12faee1a8bb573b51fa5758ca884b..691f59171c6c722e52faaeaed4e086d46f646eb2 100644 (file)
 #define __page_aligned_data    __section(.data.page_aligned) __aligned(PAGE_SIZE)
 #define __page_aligned_bss     __section(.bss.page_aligned) __aligned(PAGE_SIZE)
 
+/*
+ * For assembly routines.
+ *
+ * Note when using these that you must specify the appropriate
+ * alignment directives yourself
+ */
+#define __PAGE_ALIGNED_DATA    .section ".data.page_aligned", "aw"
+#define __PAGE_ALIGNED_BSS     .section ".bss.page_aligned", "aw"
+
 /*
  * This is used by architectures to keep arguments on the stack
  * untouched by the compiler by keeping them live until the end.
index b939fbd0119539f38b6c4f34e211223d9d8b4a45..52cab46ae35a3be5a6a1869ce2b01aa9c4e06190 100644 (file)
@@ -7,3 +7,4 @@ pnmtologo
 bin2c
 unifdef
 binoffset
+ihex2fw
index 01c2d13dd0204367b9655ee1c202f0a437ed2398..b19f1f4962e3dfdb852a4059bf3d1c6122963779 100644 (file)
@@ -16,6 +16,8 @@ create_package() {
        local pname="$1" pdir="$2"
 
        cp debian/copyright "$pdir/usr/share/doc/$pname/"
+       cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
+       gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
 
        # Fix ownership and permissions
        chown -R root:root "$pdir"
index 462e2cedaa6af6807fbee41fdc9f0fa6140389af..26d255de6bebb73b6fa51b39b740132b7c0b609c 100644 (file)
@@ -3470,10 +3470,16 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
                }
                mutex_lock(&codec->spdif_mutex);
                if (mout->share_spdif) {
-                       runtime->hw.rates &= mout->spdif_rates;
-                       runtime->hw.formats &= mout->spdif_formats;
-                       if (mout->spdif_maxbps < hinfo->maxbps)
-                               hinfo->maxbps = mout->spdif_maxbps;
+                       if ((runtime->hw.rates & mout->spdif_rates) &&
+                           (runtime->hw.formats & mout->spdif_formats)) {
+                               runtime->hw.rates &= mout->spdif_rates;
+                               runtime->hw.formats &= mout->spdif_formats;
+                               if (mout->spdif_maxbps < hinfo->maxbps)
+                                       hinfo->maxbps = mout->spdif_maxbps;
+                       } else {
+                               mout->share_spdif = 0;
+                               /* FIXME: need notify? */
+                       }
                }
                mutex_unlock(&codec->spdif_mutex);
        }
index 4e9ea70802701247ef09f6d1a6ce4a68164a216f..1877d95d4aa6725807f4b77690dce7ab2f6c80d0 100644 (file)
@@ -1454,6 +1454,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                mutex_unlock(&chip->open_mutex);
                return err;
        }
+       snd_pcm_limit_hw_rates(runtime);
        spin_lock_irqsave(&chip->reg_lock, flags);
        azx_dev->substream = substream;
        azx_dev->running = 0;
@@ -1463,6 +1464,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
        mutex_unlock(&chip->open_mutex);
 
+       if (snd_BUG_ON(!runtime->hw.channels_min || !runtime->hw.channels_max))
+               return -EINVAL;
+       if (snd_BUG_ON(!runtime->hw.formats))
+               return -EINVAL;
+       if (snd_BUG_ON(!runtime->hw.rates))
+               return -EINVAL;
        return 0;
 }
 
index 1988582d1ab8f09ea115aa1369c75cd6aa535e9e..be7d25fa7f35a3e164cf858aa7f5c4b67afd9ac6 100644 (file)
@@ -3746,9 +3746,30 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
        { } /* end */
 };
 
+static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+       int mute = (!ucontrol->value.integer.value[0] &&
+                   !ucontrol->value.integer.value[1]);
+       /* toggle GPIO1 according to the mute state */
+       snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+                           mute ? 0x02 : 0x0);
+       return ret;
+}
+
 static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
        HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Master Playback Switch",
+               .info = snd_hda_mixer_amp_switch_info,
+               .get = snd_hda_mixer_amp_switch_get,
+               .put = ad1884a_mobile_master_sw_put,
+               .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+       },
        HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
        HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
@@ -3869,6 +3890,10 @@ static struct hda_verb ad1884a_mobile_verbs[] = {
        /* unsolicited event for pin-sense */
        {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
+       /* allow to touch GPIO1 (for mute control) */
+       {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+       {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
        { } /* end */
 };
 
@@ -3978,6 +4003,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
        SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
+       SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP),
        SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
        SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
index 392d108c355878791fa1b21700e055203e7566a9..019ca7cb56d7d54631a425cb8f079099ef2ef11a 100644 (file)
@@ -510,7 +510,7 @@ static int ca0110_parse_auto_config(struct hda_codec *codec)
 }
 
 
-int patch_ca0110(struct hda_codec *codec)
+static int patch_ca0110(struct hda_codec *codec)
 {
        struct ca0110_spec *spec;
        int err;
index 3a8e58c483dfdd6e3ffa1c2af5f571280f145f33..e661b21354beda752a926421ee64b729f412ec43 100644 (file)
@@ -12876,20 +12876,11 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
        { }
 };
 
-/* bind volumes of both NID 0x0c and 0x0d */
-static struct hda_bind_ctls alc269_epc_bind_vol = {
-       .ops = &snd_hda_bind_vol,
-       .values = {
-               HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
-               HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
-               0
-       },
-};
-
 static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
-       HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol),
-       HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
        { } /* end */
 };
 
@@ -12902,12 +12893,7 @@ static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
 };
 
 /* FSC amilo */
-static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
-       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-       HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol),
-       { } /* end */
-};
+#define alc269_fujitsu_mixer   alc269_eeepc_mixer
 
 static struct hda_verb alc269_quanta_fl1_verbs[] = {
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
index bf971f7cfdc652984d4824576306e96aaa88b4d6..6ebcb6bdd7129eb8dd04daf344aad880aabf8ce9 100644 (file)
@@ -635,6 +635,8 @@ static void xonar_d2_resume(struct oxygen *chip)
 
 static void xonar_d1_resume(struct oxygen *chip)
 {
+       oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
+       msleep(1);
        cs43xx_init(chip);
        xonar_enable_output(chip);
 }
index 5dbebf82249ca735776d942ed9e3335e7b300b09..8cb65ccad35fb8cfcf96caac60cd2b0e1adb468e 100644 (file)
@@ -33,7 +33,7 @@ config SND_SOC_MPC5200_I2S
 config SND_SOC_MPC5200_AC97
        tristate "Freescale MPC5200 PSC in AC97 mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
-       select AC97_BUS
+       select SND_SOC_AC97_BUS
        select SND_MPC52xx_DMA
        select PPC_BESTCOMM_GEN_BD
        help
@@ -41,7 +41,7 @@ config SND_SOC_MPC5200_AC97
 
 config SND_MPC52xx_SOC_PCM030
        tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712"
-       depends on PPC_MPC5200_SIMPLE && BROKEN
+       depends on PPC_MPC5200_SIMPLE
        select SND_SOC_MPC5200_AC97
        select SND_SOC_WM9712
        help
@@ -50,7 +50,7 @@ config SND_MPC52xx_SOC_PCM030
 
 config SND_MPC52xx_SOC_EFIKA
        tristate "SoC AC97 Audio support for bbplan Efika and STAC9766"
-       depends on PPC_EFIKA && BROKEN
+       depends on PPC_EFIKA
        select SND_SOC_MPC5200_AC97
        select SND_SOC_STAC9766
        help
index 6454e15f7d28cb274bf3e21abe76b9b1ee6f06ee..84a1950880ebc96143a749cd2c5c819b08575508 100644 (file)
@@ -216,12 +216,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
        dma_addr_t ptr;
        snd_pcm_uframes_t offset;
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               ptr = omap_get_dma_src_pos(prtd->dma_ch);
-       else
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
                ptr = omap_get_dma_dst_pos(prtd->dma_ch);
+               offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+       } else if (!(cpu_is_omap1510())) {
+               ptr = omap_get_dma_src_pos(prtd->dma_ch);
+               offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+       } else
+               offset = prtd->period_index * runtime->period_size;
 
-       offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
        if (offset >= runtime->buffer_size)
                offset = 0;
 
index 4743e262895d9f1068260762ca6c4f64df5dd17d..6b8f655d1ad826d7556317b17e1f1074fa7e49f3 100644 (file)
@@ -167,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
 
        BUG_ON(IS_ERR(clk_i2s));
        clk_enable(clk_i2s);
+       dai->private_data = dai;
        pxa_i2s_wait();
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -255,7 +256,10 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
        if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
                SACR0 &= ~SACR0_ENB;
                pxa_i2s_wait();
-               clk_disable(clk_i2s);
+               if (dai->private_data != NULL) {
+                       clk_disable(clk_i2s);
+                       dai->private_data = NULL;
+               }
        }
 }
 
@@ -336,6 +340,7 @@ static int pxa2xx_i2s_probe(struct platform_device *dev)
                return PTR_ERR(clk_i2s);
 
        pxa_i2s_dai.dev = &dev->dev;
+       pxa_i2s_dai.private_data = NULL;
        ret = snd_soc_register_dai(&pxa_i2s_dai);
        if (ret != 0)
                clk_put(clk_i2s);
index 12522e6913d92d068676f4b3916571b03dae2d87..a41f8b127f49cceb1432183c4943482d6f61997f 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
 #include <sound/core.h>
 
 #ifdef CONFIG_SOUND_OSS_CORE
@@ -29,6 +31,8 @@ MODULE_LICENSE("GPL");
 
 static char *sound_nodename(struct device *dev)
 {
+       if (MAJOR(dev->devt) == SOUND_MAJOR)
+               return NULL;
        return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
 }
 
@@ -104,7 +108,6 @@ module_exit(cleanup_soundcore);
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sound.h>
-#include <linux/major.h>
 #include <linux/kmod.h>
 
 #define SOUND_STEP 16
index 0e5db719de244c1ba6da224ac316b8a37106109c..de38108f0b283ab4653693cbe9ac77698de299a1 100644 (file)
@@ -35,7 +35,7 @@
 #include "input.h"
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.17");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.18");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
@@ -349,7 +349,9 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
                log("Unable to set up control system (ret=%d)\n", ret);
 }
 
-static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
+static int create_card(struct usb_device *usb_dev,
+                      struct usb_interface *intf,
+                      struct snd_card **cardp)
 {
        int devnum;
        int err;
@@ -374,7 +376,7 @@ static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
        dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
                                  le16_to_cpu(usb_dev->descriptor.idProduct));
        spin_lock_init(&dev->spinlock);
-       snd_card_set_dev(card, &usb_dev->dev);
+       snd_card_set_dev(card, &intf->dev);
 
        *cardp = card;
        return 0;
@@ -461,7 +463,7 @@ static int __devinit snd_probe(struct usb_interface *intf,
        struct snd_card *card;
        struct usb_device *device = interface_to_usbdev(intf);
 
-       ret = create_card(device, &card);
+       ret = create_card(device, intf, &card);
 
        if (ret < 0)
                return ret;
index a5aae9d67f31707e585de8de10689d8099df5f1c..fd44946ce4b3a21aa4bae548144fcf6b66df676b 100644 (file)
@@ -514,7 +514,6 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
                US122L(card)->chip.dev->bus->busnum,
                US122L(card)->chip.dev->devnum
                );
-       snd_card_set_dev(card, &device->dev);
        *cardp = card;
        return 0;
 }
@@ -531,6 +530,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
        if (err < 0)
                return err;
 
+       snd_card_set_dev(card, &intf->dev);
        if (!us122l_create_card(card)) {
                snd_card_free(card);
                return -EINVAL;
index 5ce0da23ee96fd22752b53ffcab1d7f8057672b9..cb4bb8373ca2989732459c70b14df5e2d2ad423d 100644 (file)
@@ -364,7 +364,6 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
                0,//us428(card)->usbmidi.ifnum,
                usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
                );
-       snd_card_set_dev(card, &device->dev);
        *cardp = card;
        return 0;
 }
@@ -388,6 +387,7 @@ static int usX2Y_usb_probe(struct usb_device *device,
        err = usX2Y_create_card(device, &card);
        if (err < 0)
                return err;
+       snd_card_set_dev(card, &intf->dev);
        if ((err = usX2Y_hwdep_new(card, device)) < 0  ||
            (err = snd_card_register(card)) < 0) {
                snd_card_free(card);