Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Aug 2014 15:47:00 +0000 (08:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Aug 2014 15:47:00 +0000 (08:47 -0700)
Pull MIPS updates from Ralf Baechle:
 "This is the main pull request for 3.17.  It contains:

   - misc Cavium Octeon, BCM47xx, BCM63xx and Alchemy  updates
   - MIPS ptrace updates and cleanups
   - various fixes that will also go to -stable
   - a number of cleanups and small non-critical fixes.
   - NUMA support for the Loongson 3.
   - more support for MSA
   - support for MAAR
   - various FP enhancements and fixes"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (139 commits)
  MIPS: jz4740: remove unnecessary null test before debugfs_remove
  MIPS: Octeon: remove unnecessary null test before debugfs_remove_recursive
  MIPS: ZBOOT: implement stack protector in compressed boot phase
  MIPS: mipsreg: remove duplicate MIPS_CONF4_FTLBSETS_SHIFT
  MIPS: Bonito64: remove a duplicate define
  MIPS: Malta: initialise MAARs
  MIPS: Initialise MAARs
  MIPS: detect presence of MAARs
  MIPS: define MAAR register accessors & bits
  MIPS: mark MSA experimental
  MIPS: Don't build MSA support unless it can be used
  MIPS: consistently clear MSA flags when starting & copying threads
  MIPS: 16 byte align MSA vector context
  MIPS: disable preemption whilst initialising MSA
  MIPS: ensure MSA gets disabled during boot
  MIPS: fix read_msa_* & write_msa_* functions on non-MSA toolchains
  MIPS: fix MSA context for tasks which don't use FP first
  MIPS: init upper 64b of vector registers when MSA is first used
  MIPS: save/disable MSA in lose_fpu
  MIPS: preserve scalar FP CSR when switching vector context
  ...

156 files changed:
Documentation/kernel-parameters.txt
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/alchemy/board-mtx1.c
arch/mips/alchemy/board-xxs1500.c
arch/mips/alchemy/common/Makefile
arch/mips/alchemy/common/clock.c [new file with mode: 0644]
arch/mips/alchemy/common/clocks.c [deleted file]
arch/mips/alchemy/common/dbdma.c
arch/mips/alchemy/common/dma.c
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/common/power.c
arch/mips/alchemy/common/setup.c
arch/mips/alchemy/common/time.c
arch/mips/alchemy/common/usb.c
arch/mips/alchemy/devboards/db1000.c
arch/mips/alchemy/devboards/db1200.c
arch/mips/alchemy/devboards/db1300.c
arch/mips/alchemy/devboards/db1550.c
arch/mips/alchemy/devboards/pm.c
arch/mips/bcm47xx/Kconfig
arch/mips/bcm47xx/bcm47xx_private.h
arch/mips/bcm47xx/board.c
arch/mips/bcm47xx/buttons.c
arch/mips/bcm47xx/leds.c
arch/mips/bcm47xx/prom.c
arch/mips/bcm47xx/setup.c
arch/mips/bcm47xx/sprom.c
arch/mips/bcm63xx/cpu.c
arch/mips/bcm63xx/dev-enet.c
arch/mips/bcm63xx/dev-spi.c
arch/mips/bcm63xx/gpio.c
arch/mips/bcm63xx/irq.c
arch/mips/bcm63xx/reset.c
arch/mips/boot/compressed/decompress.c
arch/mips/cavium-octeon/executive/cvmx-helper-board.c
arch/mips/cavium-octeon/oct_ilm.c
arch/mips/cavium-octeon/smp.c
arch/mips/configs/loongson3_defconfig
arch/mips/include/asm/Kbuild
arch/mips/include/asm/addrspace.h
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/bitops.h
arch/mips/include/asm/cop2.h
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/maar.h [new file with mode: 0644]
arch/mips/include/asm/mach-au1x00/au1000.h
arch/mips/include/asm/mach-au1x00/au1000_dma.h
arch/mips/include/asm/mach-au1x00/gpio-au1000.h
arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
arch/mips/include/asm/mach-loongson/boot_param.h
arch/mips/include/asm/mach-loongson/kernel-entry-init.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/loongson.h
arch/mips/include/asm/mach-loongson/machine.h
arch/mips/include/asm/mach-loongson/mmzone.h [new file with mode: 0644]
arch/mips/include/asm/mach-loongson/topology.h [new file with mode: 0644]
arch/mips/include/asm/mach-malta/irq.h
arch/mips/include/asm/mach-sead3/irq.h
arch/mips/include/asm/mips-boards/bonito64.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/msa.h
arch/mips/include/asm/octeon/cvmx-bootinfo.h
arch/mips/include/asm/pgtable-32.h
arch/mips/include/asm/pgtable.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/reg.h
arch/mips/include/asm/smp-cps.h
arch/mips/include/asm/smp.h
arch/mips/include/asm/sparsemem.h
arch/mips/include/asm/user.h [deleted file]
arch/mips/include/uapi/asm/ptrace.h
arch/mips/include/uapi/asm/reg.h [new file with mode: 0644]
arch/mips/jz4740/clock-debugfs.c
arch/mips/jz4740/platform.c
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/ftrace.c
arch/mips/kernel/irq-gic.c
arch/mips/kernel/mcount.S
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/pm-cps.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/rtlx-cmp.c
arch/mips/kernel/rtlx-mt.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/setup.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/loongson/Kconfig
arch/mips/loongson/Platform
arch/mips/loongson/common/env.c
arch/mips/loongson/common/init.c
arch/mips/loongson/common/pm.c
arch/mips/loongson/lemote-2f/clock.c
arch/mips/loongson/lemote-2f/reset.c
arch/mips/loongson/loongson-3/Makefile
arch/mips/loongson/loongson-3/cop2-ex.c [new file with mode: 0644]
arch/mips/loongson/loongson-3/irq.c
arch/mips/loongson/loongson-3/numa.c [new file with mode: 0644]
arch/mips/loongson/loongson-3/smp.c
arch/mips/loongson/loongson-3/smp.h
arch/mips/math-emu/cp1emu.c
arch/mips/mm/c-r4k.c
arch/mips/mm/init.c
arch/mips/mm/tlb-r3k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-memory.c
arch/mips/pci/Makefile
arch/mips/pci/ops-tx4927.c
arch/mips/pci/pci-alchemy.c
arch/mips/ralink/of.c
arch/mips/rb532/devices.c
arch/mips/sgi-ip22/ip22-gio.c
arch/mips/txx9/generic/7segled.c
arch/mips/txx9/generic/pci.c
arch/mips/txx9/generic/setup.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/mmc/host/au1xmmc.c
drivers/mtd/nand/au1550nd.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/irda/au1k_ir.c
drivers/rtc/rtc-au1xxx.c
drivers/spi/spi-au1550.c
drivers/video/fbdev/au1100fb.c
drivers/video/fbdev/au1100fb.h
drivers/video/fbdev/au1200fb.c
drivers/watchdog/octeon-wdt-main.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/au1x/psc.h

index 21ae0e4..664fd88 100644 (file)
@@ -571,6 +571,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        trust validation.
                        format: { id:<keyid> | builtin }
 
+       cca=            [MIPS] Override the kernel pages' cache coherency
+                       algorithm.  Accepted values range from 0 to 7
+                       inclusive. See arch/mips/include/asm/pgtable-bits.h
+                       for platform specific values (SB1, Loongson3 and
+                       others).
+
        ccw_timeout_log [S390]
                        See Documentation/s390/CommonIO for details.
 
index 10f270b..900c7e5 100644 (file)
@@ -71,6 +71,7 @@ config MIPS_ALCHEMY
        select SYS_SUPPORTS_APM_EMULATION
        select ARCH_REQUIRE_GPIOLIB
        select SYS_SUPPORTS_ZBOOT
+       select COMMON_CLK
 
 config AR7
        bool "Texas Instruments AR7"
@@ -129,6 +130,8 @@ config BCM47XX
        select SYS_SUPPORTS_MIPS16
        select SYS_HAS_EARLY_PRINTK
        select USE_GENERIC_EARLY_PRINTK_8250
+       select GPIOLIB
+       select LEDS_GPIO_REGISTER
        help
         Support for BCM47XX based boards
 
@@ -137,6 +140,7 @@ config BCM63XX
        select BOOT_RAW
        select CEVT_R4K
        select CSRC_R4K
+       select SYNC_R4K
        select DMA_NONCOHERENT
        select IRQ_CPU
        select SYS_SUPPORTS_32BIT_KERNEL
@@ -2056,6 +2060,7 @@ config MIPS_CPS
          support is unavailable.
 
 config MIPS_CPS_PM
+       select MIPS_CPC
        bool
 
 config MIPS_GIC_IPI
@@ -2109,9 +2114,9 @@ config CPU_MICROMIPS
          microMIPS ISA
 
 config CPU_HAS_MSA
-       bool "Support for the MIPS SIMD Architecture"
+       bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
        depends on CPU_SUPPORTS_MSA
-       default y
+       depends on 64BIT || MIPS_O32_FP64_SUPPORT
        help
          MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
          and a set of SIMD instructions to operate on them. When this option
index a8521de..9336509 100644 (file)
@@ -151,8 +151,10 @@ cflags-$(CONFIG_CPU_NEVADA)        += $(call cc-option,-march=rm5200,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)    += $(call cc-option,-march=rm7000,-march=r5000) \
                        -Wa,--trap
-cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-march=sb1,-march=r5000) \
                        -Wa,--trap
+cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-mno-mdmx)
+cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-mno-mips3d)
 cflags-$(CONFIG_CPU_R8000)     += -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)    += $(call cc-option,-march=r10000,-march=r8000) \
                        -Wa,--trap
index 25a59a2..1e3b102 100644 (file)
@@ -85,10 +85,10 @@ void __init board_setup(void)
 #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
 
        /* Initialize sys_pinfunc */
-       au_writel(SYS_PF_NI2, SYS_PINFUNC);
+       alchemy_wrsys(SYS_PF_NI2, AU1000_SYS_PINFUNC);
 
        /* Initialize GPIO */
-       au_writel(~0, KSEG1ADDR(AU1000_SYS_PHYS_ADDR) + SYS_TRIOUTCLR);
+       alchemy_wrsys(~0, AU1000_SYS_TRIOUTCLR);
        alchemy_gpio_direction_output(0, 0);    /* Disable M66EN (PCI 66MHz) */
        alchemy_gpio_direction_output(3, 1);    /* Disable PCI CLKRUN# */
        alchemy_gpio_direction_output(1, 1);    /* Enable EXT_IO3 */
index 3fb814b..0fc53e0 100644 (file)
@@ -87,9 +87,9 @@ void __init board_setup(void)
        alchemy_gpio2_enable();
 
        /* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
-       pin_func  = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
+       pin_func  = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PF_UR3;
        pin_func |= SYS_PF_UR3;
-       au_writel(pin_func, SYS_PINFUNC);
+       alchemy_wrsys(pin_func, AU1000_SYS_PINFUNC);
 
        /* Enable UART */
        alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
index cb83d8d..f64744f 100644 (file)
@@ -5,8 +5,8 @@
 # Makefile for the Alchemy Au1xx0 CPUs, generic files.
 #
 
-obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-       sleeper.o dma.o dbdma.o vss.o irq.o usb.o
+obj-y += prom.o time.o clock.o platform.o power.o \
+        setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
new file mode 100644 (file)
index 0000000..d7557cd
--- /dev/null
@@ -0,0 +1,1094 @@
+/*
+ * Alchemy clocks.
+ *
+ * Exposes all configurable internal clock sources to the clk framework.
+ *
+ * We have:
+ *  - Root source, usually 12MHz supplied by an external crystal
+ *  - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
+ *
+ * Dividers:
+ *  - 6 clock dividers with:
+ *   * selectable source [one of the PLLs],
+ *   * output divided between [2 .. 512 in steps of 2] (!Au1300)
+ *     or [1 .. 256 in steps of 1] (Au1300),
+ *   * can be enabled individually.
+ *
+ * - up to 6 "internal" (fixed) consumers which:
+ *   * take either AUXPLL or one of the above 6 dividers as input,
+ *   * divide this input by 1, 2, or 4 (and 3 on Au1300).
+ *   * can be disabled separately.
+ *
+ * Misc clocks:
+ * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
+ *    depends on board design and should be set by bootloader, read-only.
+ * - peripheral clock: half the rate of sysbus clock, source for a lot
+ *    of peripheral blocks, read-only.
+ * - memory clock: clk rate to main memory chips, depends on board
+ *    design and is read-only,
+ * - lrclk: the static bus clock signal for synchronous operation.
+ *    depends on board design, must be set by bootloader,
+ *    but may be required to correctly configure devices attached to
+ *    the static bus. The Au1000/1500/1100 manuals call it LCLK, on
+ *    later models it's called RCLK.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* Base clock: 12MHz is the default in all databooks, and I haven't
+ * found any board yet which uses a different rate.
+ */
+#define ALCHEMY_ROOTCLK_RATE   12000000
+
+/*
+ * the internal sources which can be driven by the PLLs and dividers.
+ * Names taken from the databooks, refer to them for more information,
+ * especially which ones are share a clock line.
+ */
+static const char * const alchemy_au1300_intclknames[] = {
+       "lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
+       "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1200_intclknames[] = {
+       "lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1550_intclknames[] = {
+       "usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
+       "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1100_intclknames[] = {
+       "usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1500_intclknames[] = {
+       NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1000_intclknames[] = {
+       "irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
+       "EXTCLK1"
+};
+
+/* aliases for a few on-chip sources which are either shared
+ * or have gone through name changes.
+ */
+static struct clk_aliastable {
+       char *alias;
+       char *base;
+       int cputype;
+} alchemy_clk_aliases[] __initdata = {
+       { "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+       { "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+       { "irda_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+       { "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+       { "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+       { "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
+       { "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
+       { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
+       { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
+       { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+       { "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+       { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+       { "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+
+       { NULL, NULL, 0 },
+};
+
+#define IOMEM(x)       ((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
+
+/* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
+static spinlock_t alchemy_clk_fg0_lock;
+static spinlock_t alchemy_clk_fg1_lock;
+static spinlock_t alchemy_clk_csrc_lock;
+
+/* CPU Core clock *****************************************************/
+
+static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       unsigned long t;
+
+       /*
+        * On early Au1000, sys_cpupll was write-only. Since these
+        * silicon versions of Au1000 are not sold, we don't bend
+        * over backwards trying to determine the frequency.
+        */
+       if (unlikely(au1xxx_cpu_has_pll_wo()))
+               t = 396000000;
+       else {
+               t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
+               t *= parent_rate;
+       }
+
+       return t;
+}
+
+static struct clk_ops alchemy_clkops_cpu = {
+       .recalc_rate    = alchemy_clk_cpu_recalc,
+};
+
+static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
+                                               int ctype)
+{
+       struct clk_init_data id;
+       struct clk_hw *h;
+
+       h = kzalloc(sizeof(*h), GFP_KERNEL);
+       if (!h)
+               return ERR_PTR(-ENOMEM);
+
+       id.name = ALCHEMY_CPU_CLK;
+       id.parent_names = &parent_name;
+       id.num_parents = 1;
+       id.flags = CLK_IS_BASIC;
+       id.ops = &alchemy_clkops_cpu;
+       h->init = &id;
+
+       return clk_register(NULL, h);
+}
+
+/* AUXPLLs ************************************************************/
+
+struct alchemy_auxpll_clk {
+       struct clk_hw hw;
+       unsigned long reg;      /* au1300 has also AUXPLL2 */
+       int maxmult;            /* max multiplier */
+};
+#define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
+
+static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+
+       return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
+}
+
+static int alchemy_clk_aux_setr(struct clk_hw *hw,
+                               unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+       unsigned long d = rate;
+
+       if (rate)
+               d /= parent_rate;
+       else
+               d = 0;
+
+       /* minimum is 84MHz, max is 756-1032 depending on variant */
+       if (((d < 7) && (d != 0)) || (d > a->maxmult))
+               return -EINVAL;
+
+       alchemy_wrsys(d, a->reg);
+       return 0;
+}
+
+static long alchemy_clk_aux_roundr(struct clk_hw *hw,
+                                           unsigned long rate,
+                                           unsigned long *parent_rate)
+{
+       struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+       unsigned long mult;
+
+       if (!rate || !*parent_rate)
+               return 0;
+
+       mult = rate / (*parent_rate);
+
+       if (mult && (mult < 7))
+               mult = 7;
+       if (mult > a->maxmult)
+               mult = a->maxmult;
+
+       return (*parent_rate) * mult;
+}
+
+static struct clk_ops alchemy_clkops_aux = {
+       .recalc_rate    = alchemy_clk_aux_recalc,
+       .set_rate       = alchemy_clk_aux_setr,
+       .round_rate     = alchemy_clk_aux_roundr,
+};
+
+static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
+                                               char *name, int maxmult,
+                                               unsigned long reg)
+{
+       struct clk_init_data id;
+       struct clk *c;
+       struct alchemy_auxpll_clk *a;
+
+       a = kzalloc(sizeof(*a), GFP_KERNEL);
+       if (!a)
+               return ERR_PTR(-ENOMEM);
+
+       id.name = name;
+       id.parent_names = &parent_name;
+       id.num_parents = 1;
+       id.flags = CLK_GET_RATE_NOCACHE;
+       id.ops = &alchemy_clkops_aux;
+
+       a->reg = reg;
+       a->maxmult = maxmult;
+       a->hw.init = &id;
+
+       c = clk_register(NULL, &a->hw);
+       if (!IS_ERR(c))
+               clk_register_clkdev(c, name, NULL);
+       else
+               kfree(a);
+
+       return c;
+}
+
+/* sysbus_clk *********************************************************/
+
+static struct clk __init  *alchemy_clk_setup_sysbus(const char *pn)
+{
+       unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
+       struct clk *c;
+
+       c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
+                                     pn, 0, 1, v);
+       if (!IS_ERR(c))
+               clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
+       return c;
+}
+
+/* Peripheral Clock ***************************************************/
+
+static struct clk __init *alchemy_clk_setup_periph(const char *pn)
+{
+       /* Peripheral clock runs at half the rate of sysbus clk */
+       struct clk *c;
+
+       c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
+                                     pn, 0, 1, 2);
+       if (!IS_ERR(c))
+               clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
+       return c;
+}
+
+/* mem clock **********************************************************/
+
+static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
+{
+       void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
+       unsigned long v;
+       struct clk *c;
+       int div;
+
+       switch (ct) {
+       case ALCHEMY_CPU_AU1550:
+       case ALCHEMY_CPU_AU1200:
+               v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+               div = (v & (1 << 15)) ? 1 : 2;
+               break;
+       case ALCHEMY_CPU_AU1300:
+               v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+               div = (v & (1 << 31)) ? 1 : 2;
+               break;
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1100:
+       default:
+               div = 2;
+               break;
+       }
+
+       c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
+                                     0, 1, div);
+       if (!IS_ERR(c))
+               clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
+       return c;
+}
+
+/* lrclk: external synchronous static bus clock ***********************/
+
+static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
+{
+       /* MEM_STCFG0[15:13] = divisor.
+        * L/RCLK = periph_clk / (divisor + 1)
+        * On Au1000, Au1500, Au1100 it's called LCLK,
+        * on later models it's called RCLK, but it's the same thing.
+        */
+       struct clk *c;
+       unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
+
+       v = (v & 7) + 1;
+       c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
+                                     pn, 0, 1, v);
+       if (!IS_ERR(c))
+               clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
+       return c;
+}
+
+/* Clock dividers and muxes *******************************************/
+
+/* data for fgen and csrc mux-dividers */
+struct alchemy_fgcs_clk {
+       struct clk_hw hw;
+       spinlock_t *reglock;    /* register lock                  */
+       unsigned long reg;      /* SYS_FREQCTRL0/1                */
+       int shift;              /* offset in register             */
+       int parent;             /* parent before disable [Au1300] */
+       int isen;               /* is it enabled?                 */
+       int *dt;                /* dividertable for csrc          */
+};
+#define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
+
+static long alchemy_calc_div(unsigned long rate, unsigned long prate,
+                              int scale, int maxdiv, unsigned long *rv)
+{
+       long div1, div2;
+
+       div1 = prate / rate;
+       if ((prate / div1) > rate)
+               div1++;
+
+       if (scale == 2) {       /* only div-by-multiple-of-2 possible */
+               if (div1 & 1)
+                       div1++; /* stay <=prate */
+       }
+
+       div2 = (div1 / scale) - 1;      /* value to write to register */
+
+       if (div2 > maxdiv)
+               div2 = maxdiv;
+       if (rv)
+               *rv = div2;
+
+       div1 = ((div2 + 1) * scale);
+       return div1;
+}
+
+static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk,
+                                       int scale, int maxdiv)
+{
+       struct clk *pc, *bpc, *free;
+       long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
+       int j;
+
+       lastdiff = INT_MAX;
+       bpr = 0;
+       bpc = NULL;
+       br = -EINVAL;
+       free = NULL;
+
+       /* look at the rates each enabled parent supplies and select
+        * the one that gets closest to but not over the requested rate.
+        */
+       for (j = 0; j < 7; j++) {
+               pc = clk_get_parent_by_index(hw->clk, j);
+               if (!pc)
+                       break;
+
+               /* if this parent is currently unused, remember it.
+                * XXX: I know it's a layering violation, but it works
+                * so well.. (if (!clk_has_active_children(pc)) )
+                */
+               if (pc->prepare_count == 0) {
+                       if (!free)
+                               free = pc;
+               }
+
+               pr = clk_get_rate(pc);
+               if (pr < rate)
+                       continue;
+
+               /* what can hardware actually provide */
+               tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+               nr = pr / tdv;
+               diff = rate - nr;
+               if (nr > rate)
+                       continue;
+
+               if (diff < lastdiff) {
+                       lastdiff = diff;
+                       bpr = pr;
+                       bpc = pc;
+                       br = nr;
+               }
+               if (diff == 0)
+                       break;
+       }
+
+       /* if we couldn't get the exact rate we wanted from the enabled
+        * parents, maybe we can tell an available disabled/inactive one
+        * to give us a rate we can divide down to the requested rate.
+        */
+       if (lastdiff && free) {
+               for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
+                       tpr = rate * j;
+                       if (tpr < 0)
+                               break;
+                       pr = clk_round_rate(free, tpr);
+
+                       tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+                       nr = pr / tdv;
+                       diff = rate - nr;
+                       if (nr > rate)
+                               continue;
+                       if (diff < lastdiff) {
+                               lastdiff = diff;
+                               bpr = pr;
+                               bpc = free;
+                               br = nr;
+                       }
+                       if (diff == 0)
+                               break;
+               }
+       }
+
+       *best_parent_rate = bpr;
+       *best_parent_clk = bpc;
+       return br;
+}
+
+static int alchemy_clk_fgv1_en(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v, flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v |= (1 << 1) << c->shift;
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
+
+       return v & 1;
+}
+
+static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v, flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~((1 << 1) << c->shift);
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v, flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       if (index)
+               v |= (1 << c->shift);
+       else
+               v &= ~(1 << c->shift);
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+       return (alchemy_rdsys(c->reg) >> c->shift) & 1;
+}
+
+static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long div, v, flags, ret;
+       int sh = c->shift + 2;
+
+       if (!rate || !parent_rate || rate > (parent_rate / 2))
+               return -EINVAL;
+       ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~(0xff << sh);
+       v |= div << sh;
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
+
+       v = ((v & 0xff) + 1) * 2;
+       return parent_rate / v;
+}
+
+static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk)
+{
+       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+                                    best_parent_clk, 2, 512);
+}
+
+/* Au1000, Au1100, Au15x0, Au12x0 */
+static struct clk_ops alchemy_clkops_fgenv1 = {
+       .recalc_rate    = alchemy_clk_fgv1_recalc,
+       .determine_rate = alchemy_clk_fgv1_detr,
+       .set_rate       = alchemy_clk_fgv1_setr,
+       .set_parent     = alchemy_clk_fgv1_setp,
+       .get_parent     = alchemy_clk_fgv1_getp,
+       .enable         = alchemy_clk_fgv1_en,
+       .disable        = alchemy_clk_fgv1_dis,
+       .is_enabled     = alchemy_clk_fgv1_isen,
+};
+
+static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
+{
+       unsigned long v = alchemy_rdsys(c->reg);
+
+       v &= ~(3 << c->shift);
+       v |= (c->parent & 3) << c->shift;
+       alchemy_wrsys(v, c->reg);
+       c->isen = 1;
+}
+
+static int alchemy_clk_fgv2_en(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long flags;
+
+       /* enable by setting the previous parent clock */
+       spin_lock_irqsave(c->reglock, flags);
+       __alchemy_clk_fgv2_en(c);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+       return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
+}
+
+static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v, flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~(3 << c->shift);  /* set input mux to "disabled" state */
+       alchemy_wrsys(v, c->reg);
+       c->isen = 0;
+       spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       c->parent = index + 1;  /* value to write to register */
+       if (c->isen)
+               __alchemy_clk_fgv2_en(c);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long flags, v;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = c->parent - 1;
+       spin_unlock_irqrestore(c->reglock, flags);
+       return v;
+}
+
+/* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
+ * dividers behave exactly as on previous models (dividers are multiples
+ * of 2); with the bit set, dividers are multiples of 1, halving their
+ * range, but making them also much more flexible.
+ */
+static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       int sh = c->shift + 2;
+       unsigned long div, v, flags, ret;
+
+       if (!rate || !parent_rate || rate > parent_rate)
+               return -EINVAL;
+
+       v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */
+       ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
+                              v ? 256 : 512, &div);
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~(0xff << sh);
+       v |= (div & 0xff) << sh;
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       int sh = c->shift + 2;
+       unsigned long v, t;
+
+       v = alchemy_rdsys(c->reg);
+       t = parent_rate / (((v >> sh) & 0xff) + 1);
+       if ((v & (1 << 30)) == 0)               /* test scale bit */
+               t /= 2;
+
+       return t;
+}
+
+static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       int scale, maxdiv;
+
+       if (alchemy_rdsys(c->reg) & (1 << 30)) {
+               scale = 1;
+               maxdiv = 256;
+       } else {
+               scale = 2;
+               maxdiv = 512;
+       }
+
+       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+                                    best_parent_clk, scale, maxdiv);
+}
+
+/* Au1300 larger input mux, no separate disable bit, flexible divider */
+static struct clk_ops alchemy_clkops_fgenv2 = {
+       .recalc_rate    = alchemy_clk_fgv2_recalc,
+       .determine_rate = alchemy_clk_fgv2_detr,
+       .set_rate       = alchemy_clk_fgv2_setr,
+       .set_parent     = alchemy_clk_fgv2_setp,
+       .get_parent     = alchemy_clk_fgv2_getp,
+       .enable         = alchemy_clk_fgv2_en,
+       .disable        = alchemy_clk_fgv2_dis,
+       .is_enabled     = alchemy_clk_fgv2_isen,
+};
+
+static const char * const alchemy_clk_fgv1_parents[] = {
+       ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgv2_parents[] = {
+       ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgen_names[] = {
+       ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+       ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
+
+static int __init alchemy_clk_init_fgens(int ctype)
+{
+       struct clk *c;
+       struct clk_init_data id;
+       struct alchemy_fgcs_clk *a;
+       unsigned long v;
+       int i, ret;
+
+       switch (ctype) {
+       case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+               id.ops = &alchemy_clkops_fgenv1;
+               id.parent_names = (const char **)alchemy_clk_fgv1_parents;
+               id.num_parents = 2;
+               break;
+       case ALCHEMY_CPU_AU1300:
+               id.ops = &alchemy_clkops_fgenv2;
+               id.parent_names = (const char **)alchemy_clk_fgv2_parents;
+               id.num_parents = 3;
+               break;
+       default:
+               return -ENODEV;
+       }
+       id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+       a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+       if (!a)
+               return -ENOMEM;
+
+       spin_lock_init(&alchemy_clk_fg0_lock);
+       spin_lock_init(&alchemy_clk_fg1_lock);
+       ret = 0;
+       for (i = 0; i < 6; i++) {
+               id.name = alchemy_clk_fgen_names[i];
+               a->shift = 10 * (i < 3 ? i : i - 3);
+               if (i > 2) {
+                       a->reg = AU1000_SYS_FREQCTRL1;
+                       a->reglock = &alchemy_clk_fg1_lock;
+               } else {
+                       a->reg = AU1000_SYS_FREQCTRL0;
+                       a->reglock = &alchemy_clk_fg0_lock;
+               }
+
+               /* default to first parent if bootloader has set
+                * the mux to disabled state.
+                */
+               if (ctype == ALCHEMY_CPU_AU1300) {
+                       v = alchemy_rdsys(a->reg);
+                       a->parent = (v >> a->shift) & 3;
+                       if (!a->parent) {
+                               a->parent = 1;
+                               a->isen = 0;
+                       } else
+                               a->isen = 1;
+               }
+
+               a->hw.init = &id;
+               c = clk_register(NULL, &a->hw);
+               if (IS_ERR(c))
+                       ret++;
+               else
+                       clk_register_clkdev(c, id.name, NULL);
+               a++;
+       }
+
+       return ret;
+}
+
+/* internal sources muxes *********************************************/
+
+static int alchemy_clk_csrc_isen(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v = alchemy_rdsys(c->reg);
+
+       return (((v >> c->shift) >> 2) & 7) != 0;
+}
+
+static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
+{
+       unsigned long v = alchemy_rdsys(c->reg);
+
+       v &= ~((7 << 2) << c->shift);
+       v |= ((c->parent & 7) << 2) << c->shift;
+       alchemy_wrsys(v, c->reg);
+       c->isen = 1;
+}
+
+static int alchemy_clk_csrc_en(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long flags;
+
+       /* enable by setting the previous parent clock */
+       spin_lock_irqsave(c->reglock, flags);
+       __alchemy_clk_csrc_en(c);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static void alchemy_clk_csrc_dis(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v, flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~((3 << 2) << c->shift);   /* mux to "disabled" state */
+       alchemy_wrsys(v, c->reg);
+       c->isen = 0;
+       spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long flags;
+
+       spin_lock_irqsave(c->reglock, flags);
+       c->parent = index + 1;  /* value to write to register */
+       if (c->isen)
+               __alchemy_clk_csrc_en(c);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+       return c->parent - 1;
+}
+
+static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
+
+       return parent_rate / c->dt[v];
+}
+
+static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       unsigned long d, v, flags;
+       int i;
+
+       if (!rate || !parent_rate || rate > parent_rate)
+               return -EINVAL;
+
+       d = (parent_rate + (rate / 2)) / rate;
+       if (d > 4)
+               return -EINVAL;
+       if ((d == 3) && (c->dt[2] != 3))
+               d = 4;
+
+       for (i = 0; i < 4; i++)
+               if (c->dt[i] == d)
+                       break;
+
+       if (i >= 4)
+               return -EINVAL; /* oops */
+
+       spin_lock_irqsave(c->reglock, flags);
+       v = alchemy_rdsys(c->reg);
+       v &= ~(3 << c->shift);
+       v |= (i & 3) << c->shift;
+       alchemy_wrsys(v, c->reg);
+       spin_unlock_irqrestore(c->reglock, flags);
+
+       return 0;
+}
+
+static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk)
+{
+       struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+       int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
+
+       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+                                    best_parent_clk, scale, 4);
+}
+
+static struct clk_ops alchemy_clkops_csrc = {
+       .recalc_rate    = alchemy_clk_csrc_recalc,
+       .determine_rate = alchemy_clk_csrc_detr,
+       .set_rate       = alchemy_clk_csrc_setr,
+       .set_parent     = alchemy_clk_csrc_setp,
+       .get_parent     = alchemy_clk_csrc_getp,
+       .enable         = alchemy_clk_csrc_en,
+       .disable        = alchemy_clk_csrc_dis,
+       .is_enabled     = alchemy_clk_csrc_isen,
+};
+
+static const char * const alchemy_clk_csrc_parents[] = {
+       /* disabled at index 0 */ ALCHEMY_AUXPLL_CLK,
+       ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+       ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
+};
+
+/* divider tables */
+static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 };        /* rest */
+static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 };        /* Au1300 */
+
+static int __init alchemy_clk_setup_imux(int ctype)
+{
+       struct alchemy_fgcs_clk *a;
+       const char * const *names;
+       struct clk_init_data id;
+       unsigned long v;
+       int i, ret, *dt;
+       struct clk *c;
+
+       id.ops = &alchemy_clkops_csrc;
+       id.parent_names = (const char **)alchemy_clk_csrc_parents;
+       id.num_parents = 7;
+       id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+       dt = alchemy_csrc_dt1;
+       switch (ctype) {
+       case ALCHEMY_CPU_AU1000:
+               names = alchemy_au1000_intclknames;
+               break;
+       case ALCHEMY_CPU_AU1500:
+               names = alchemy_au1500_intclknames;
+               break;
+       case ALCHEMY_CPU_AU1100:
+               names = alchemy_au1100_intclknames;
+               break;
+       case ALCHEMY_CPU_AU1550:
+               names = alchemy_au1550_intclknames;
+               break;
+       case ALCHEMY_CPU_AU1200:
+               names = alchemy_au1200_intclknames;
+               break;
+       case ALCHEMY_CPU_AU1300:
+               dt = alchemy_csrc_dt2;
+               names = alchemy_au1300_intclknames;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+       if (!a)
+               return -ENOMEM;
+
+       spin_lock_init(&alchemy_clk_csrc_lock);
+       ret = 0;
+
+       for (i = 0; i < 6; i++) {
+               id.name = names[i];
+               if (!id.name)
+                       goto next;
+
+               a->shift = i * 5;
+               a->reg = AU1000_SYS_CLKSRC;
+               a->reglock = &alchemy_clk_csrc_lock;
+               a->dt = dt;
+
+               /* default to first parent clock if mux is initially
+                * set to disabled state.
+                */
+               v = alchemy_rdsys(a->reg);
+               a->parent = ((v >> a->shift) >> 2) & 7;
+               if (!a->parent) {
+                       a->parent = 1;
+                       a->isen = 0;
+               } else
+                       a->isen = 1;
+
+               a->hw.init = &id;
+               c = clk_register(NULL, &a->hw);
+               if (IS_ERR(c))
+                       ret++;
+               else
+                       clk_register_clkdev(c, id.name, NULL);
+next:
+               a++;
+       }
+
+       return ret;
+}
+
+
+/**********************************************************************/
+
+
+#define ERRCK(x)                                               \
+       if (IS_ERR(x)) {                                        \
+               ret = PTR_ERR(x);                               \
+               goto out;                                       \
+       }
+
+static int __init alchemy_clk_init(void)
+{
+       int ctype = alchemy_get_cputype(), ret, i;
+       struct clk_aliastable *t = alchemy_clk_aliases;
+       struct clk *c;
+
+       /* Root of the Alchemy clock tree: external 12MHz crystal osc */
+       c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
+                                          CLK_IS_ROOT,
+                                          ALCHEMY_ROOTCLK_RATE);
+       ERRCK(c)
+
+       /* CPU core clock */
+       c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
+       ERRCK(c)
+
+       /* AUXPLLs: max 1GHz on Au1300, 748MHz on older models */
+       i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
+       c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
+                                 i, AU1000_SYS_AUXPLL);
+       ERRCK(c)
+
+       if (ctype == ALCHEMY_CPU_AU1300) {
+               c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
+                                         ALCHEMY_AUXPLL2_CLK, i,
+                                         AU1300_SYS_AUXPLL2);
+               ERRCK(c)
+       }
+
+       /* sysbus clock: cpu core clock divided by 2, 3 or 4 */
+       c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
+       ERRCK(c)
+
+       /* peripheral clock: runs at half rate of sysbus clk */
+       c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
+       ERRCK(c)
+
+       /* SDR/DDR memory clock */
+       c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
+       ERRCK(c)
+
+       /* L/RCLK: external static bus clock for synchronous mode */
+       c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
+       ERRCK(c)
+
+       /* Frequency dividers 0-5 */
+       ret = alchemy_clk_init_fgens(ctype);
+       if (ret) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* diving muxes for internal sources */
+       ret = alchemy_clk_setup_imux(ctype);
+       if (ret) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* set up aliases drivers might look for */
+       while (t->base) {
+               if (t->cputype == ctype)
+                       clk_add_alias(t->alias, NULL, t->base, NULL);
+               t++;
+       }
+
+       pr_info("Alchemy clocktree installed\n");
+       return 0;
+
+out:
+       return ret;
+}
+postcore_initcall(alchemy_clk_init);
diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c
deleted file mode 100644 (file)
index f38298a..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Simple Au1xx0 clocks routines.
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  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  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/time.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK 12000000
-
-static unsigned int au1x00_clock; /*  Hz */
-static unsigned long uart_baud_base;
-
-/*
- * Set the au1000_clock
- */
-void set_au1x00_speed(unsigned int new_freq)
-{
-       au1x00_clock = new_freq;
-}
-
-unsigned int get_au1x00_speed(void)
-{
-       return au1x00_clock;
-}
-EXPORT_SYMBOL(get_au1x00_speed);
-
-/*
- * The UART baud base is not known at compile time ... if
- * we want to be able to use the same code on different
- * speed CPUs.
- */
-unsigned long get_au1x00_uart_baud_base(void)
-{
-       return uart_baud_base;
-}
-
-void set_au1x00_uart_baud_base(unsigned long new_baud_base)
-{
-       uart_baud_base = new_baud_base;
-}
-
-/*
- * We read the real processor speed from the PLL.  This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists.  If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly.  This function is further convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register.                    -- Dan
- */
-unsigned long au1xxx_calc_clock(void)
-{
-       unsigned long cpu_speed;
-
-       /*
-        * On early Au1000, sys_cpupll was write-only. Since these
-        * silicon versions of Au1000 are not sold by AMD, we don't bend
-        * over backwards trying to determine the frequency.
-        */
-       if (au1xxx_cpu_has_pll_wo())
-               cpu_speed = 396000000;
-       else
-               cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
-
-       /* On Alchemy CPU:counter ratio is 1:1 */
-       mips_hpt_frequency = cpu_speed;
-       /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
-       set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
-                                                         & 0x03) + 2) * 16));
-
-       set_au1x00_speed(cpu_speed);
-
-       return cpu_speed;
-}
index 19d5642..745695d 100644 (file)
@@ -341,7 +341,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
                        (dtp->dev_flags & DEV_FLAGS_SYNC))
                                i |= DDMA_CFG_SYNC;
                cp->ddma_cfg = i;
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                /*
                 * Return a non-zero value that can be used to find the channel
@@ -631,7 +631,7 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
         */
        dma_cache_wback_inv((unsigned long)buf, nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
-       au_sync();
+       wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
 
@@ -693,7 +693,7 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
         */
        dma_cache_inv((unsigned long)buf, nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
-       au_sync();
+       wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
 
@@ -760,7 +760,7 @@ void au1xxx_dbdma_stop(u32 chanid)
 
        cp = ctp->chan_ptr;
        cp->ddma_cfg &= ~DDMA_CFG_EN;   /* Disable channel */
-       au_sync();
+       wmb(); /* drain writebuffer */
        while (!(cp->ddma_stat & DDMA_STAT_H)) {
                udelay(1);
                halt_timeout++;
@@ -771,7 +771,7 @@ void au1xxx_dbdma_stop(u32 chanid)
        }
        /* clear current desc valid and doorbell */
        cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_stop);
 
@@ -789,9 +789,9 @@ void au1xxx_dbdma_start(u32 chanid)
        cp = ctp->chan_ptr;
        cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
        cp->ddma_cfg |= DDMA_CFG_EN;    /* Enable channel */
-       au_sync();
+       wmb(); /* drain writebuffer */
        cp->ddma_dbell = 0;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_start);
 
@@ -832,7 +832,7 @@ u32 au1xxx_get_dma_residue(u32 chanid)
 
        /* This is only valid if the channel is stopped. */
        rv = cp->ddma_bytecnt;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        return rv;
 }
@@ -868,7 +868,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
        au1x_dma_chan_t *cp;
 
        intstat = dbdma_gptr->ddma_intstat;
-       au_sync();
+       wmb(); /* drain writebuffer */
        chan_index = __ffs(intstat);
 
        ctp = chan_tab_ptr[chan_index];
@@ -877,7 +877,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
 
        /* Reset interrupt. */
        cp->ddma_irq = 0;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        if (ctp->chan_callback)
                ctp->chan_callback(irq, ctp->chan_callparam);
@@ -1061,7 +1061,7 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
        dbdma_gptr->ddma_config = 0;
        dbdma_gptr->ddma_throttle = 0;
        dbdma_gptr->ddma_inten = 0xffff;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr);
        if (ret)
index 9b624e2..4fb6207 100644 (file)
@@ -141,17 +141,17 @@ void dump_au1000_dma_channel(unsigned int dmanr)
 
        printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
        printk(KERN_INFO "  mode = 0x%08x\n",
-              au_readl(chan->io + DMA_MODE_SET));
+              __raw_readl(chan->io + DMA_MODE_SET));
        printk(KERN_INFO "  addr = 0x%08x\n",
-              au_readl(chan->io + DMA_PERIPHERAL_ADDR));
+              __raw_readl(chan->io + DMA_PERIPHERAL_ADDR));
        printk(KERN_INFO "  start0 = 0x%08x\n",
-              au_readl(chan->io + DMA_BUFFER0_START));
+              __raw_readl(chan->io + DMA_BUFFER0_START));
        printk(KERN_INFO "  start1 = 0x%08x\n",
-              au_readl(chan->io + DMA_BUFFER1_START));
+              __raw_readl(chan->io + DMA_BUFFER1_START));
        printk(KERN_INFO "  count0 = 0x%08x\n",
-              au_readl(chan->io + DMA_BUFFER0_COUNT));
+              __raw_readl(chan->io + DMA_BUFFER0_COUNT));
        printk(KERN_INFO "  count1 = 0x%08x\n",
-              au_readl(chan->io + DMA_BUFFER1_COUNT));
+              __raw_readl(chan->io + DMA_BUFFER1_COUNT));
 }
 
 /*
@@ -204,7 +204,8 @@ int request_au1000_dma(int dev_id, const char *dev_str,
        }
 
        /* fill it in */
-       chan->io = KSEG1ADDR(AU1000_DMA_PHYS_ADDR) + i * DMA_CHANNEL_LEN;
+       chan->io = (void __iomem *)(KSEG1ADDR(AU1000_DMA_PHYS_ADDR) +
+                       i * DMA_CHANNEL_LEN);
        chan->dev_id = dev_id;
        chan->dev_str = dev_str;
        chan->fifo_addr = dev->fifo_addr;
index 63a7181..6cb60ab 100644 (file)
@@ -389,13 +389,12 @@ static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
                return -EINVAL;
 
        local_irq_save(flags);
-       wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
+       wakemsk = alchemy_rdsys(AU1000_SYS_WAKEMSK);
        if (on)
                wakemsk |= 1 << bit;
        else
                wakemsk &= ~(1 << bit);
-       __raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
-       wmb();
+       alchemy_wrsys(wakemsk, AU1000_SYS_WAKEMSK);
        local_irq_restore(flags);
 
        return 0;
index 9837a13..d77a64f 100644 (file)
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -99,10 +100,20 @@ static struct platform_device au1xx0_uart_device = {
 
 static void __init alchemy_setup_uarts(int ctype)
 {
-       unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
+       long uartclk;
        int s = sizeof(struct plat_serial8250_port);
        int c = alchemy_get_uarts(ctype);
        struct plat_serial8250_port *ports;
+       struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
+
+       if (IS_ERR(clk))
+               return;
+       if (clk_prepare_enable(clk)) {
+               clk_put(clk);
+               return;
+       }
+       uartclk = clk_get_rate(clk);
+       clk_put(clk);
 
        ports = kzalloc(s * (c + 1), GFP_KERNEL);
        if (!ports) {
@@ -420,7 +431,7 @@ static void __init alchemy_setup_macs(int ctype)
                memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
 
        /* Register second MAC if enabled in pinfunc */
-       if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) {
+       if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
                ret = platform_device_register(&au1xxx_eth1_device);
                if (ret)
                        printk(KERN_INFO "Alchemy: failed to register MAC1\n");
index bdb28de..921ed30 100644 (file)
@@ -54,28 +54,28 @@ static unsigned int sleep_static_memctlr[4][3];
 static void save_core_regs(void)
 {
        /* Clocks and PLLs. */
-       sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
-       sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
-       sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
-       sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
-       sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
+       sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
+       sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
+       sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
+       sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
+       sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
 
        /* pin mux config */
-       sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
+       sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
 
        /* Save the static memory controller configuration. */
-       sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
-       sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
-       sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
-       sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
-       sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
-       sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
-       sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
-       sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
-       sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
-       sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
-       sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
-       sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+       sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
+       sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
+       sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
+       sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
+       sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
+       sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
+       sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
+       sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
+       sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
+       sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
+       sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
+       sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
 }
 
 static void restore_core_regs(void)
@@ -85,30 +85,28 @@ static void restore_core_regs(void)
         * one of those Au1000 with a write-only PLL, where we dont
         * have a valid value)
         */
-       au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
-       au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
-       au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
-       au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+       alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
+       alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
+       alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
+       alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
        if (!au1xxx_cpu_has_pll_wo())
-               au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
-       au_sync();
+               alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
 
-       au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
-       au_sync();
+       alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
 
        /* Restore the static memory controller configuration. */
-       au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
-       au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
-       au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
-       au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
-       au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
-       au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
-       au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
-       au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
-       au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
-       au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
-       au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
-       au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+       alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
+       alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
+       alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
+       alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
+       alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
+       alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
+       alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
+       alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
+       alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
+       alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
+       alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
+       alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
 }
 
 void au_sleep(void)
index 8267e3c..ea8f418 100644 (file)
 
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
 
 #include <asm/dma-coherence.h>
 #include <asm/mipsregs.h>
-#include <asm/time.h>
 
 #include <au1000.h>
 
@@ -41,18 +38,6 @@ extern void set_cpuspec(void);
 
 void __init plat_mem_setup(void)
 {
-       unsigned long est_freq;
-
-       /* determine core clock */
-       est_freq = au1xxx_calc_clock();
-       est_freq += 5000;    /* round */
-       est_freq -= est_freq % 10000;
-       printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
-              est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
-
-       /* this is faster than wasting cycles trying to approximate it */
-       preset_lpj = (est_freq >> 1) / HZ;
-
        if (au1xxx_cpu_needs_config_od())
                /* Various early Au1xx0 errata corrected by this */
                set_c0_config(1 << 19); /* Set Config[OD] */
index 93fa586..50e17e1 100644 (file)
@@ -46,7 +46,7 @@
 
 static cycle_t au1x_counter1_read(struct clocksource *cs)
 {
-       return au_readl(SYS_RTCREAD);
+       return alchemy_rdsys(AU1000_SYS_RTCREAD);
 }
 
 static struct clocksource au1x_counter1_clocksource = {
@@ -60,12 +60,11 @@ static struct clocksource au1x_counter1_clocksource = {
 static int au1x_rtcmatch2_set_next_event(unsigned long delta,
                                         struct clock_event_device *cd)
 {
-       delta += au_readl(SYS_RTCREAD);
+       delta += alchemy_rdsys(AU1000_SYS_RTCREAD);
        /* wait for register access */
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+       while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21)
                ;
-       au_writel(delta, SYS_RTCMATCH2);
-       au_sync();
+       alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2);
 
        return 0;
 }
@@ -112,31 +111,29 @@ static int __init alchemy_time_init(unsigned int m2int)
         * (the 32S bit seems to be stuck set to 1 once a single clock-
         * edge is detected, hence the timeouts).
         */
-       if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+       if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK))
                goto cntr_err;
 
        /*
         * setup counter 1 (RTC) to tick at full speed
         */
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
+       while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
 
-       au_writel(0, SYS_RTCTRIM);      /* 32.768 kHz */
-       au_sync();
+       alchemy_wrsys(0, AU1000_SYS_RTCTRIM);   /* 32.768 kHz */
 
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+       while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
-       au_writel(0, SYS_RTCWRITE);
-       au_sync();
+       alchemy_wrsys(0, AU1000_SYS_RTCWRITE);
 
        t = 0xffffff;
-       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+       while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
                asm volatile ("nop");
        if (!t)
                goto cntr_err;
index d193dbe..297805a 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -387,10 +388,25 @@ static inline void au1200_usb_init(void)
        udelay(1000);
 }
 
-static inline void au1000_usb_init(unsigned long rb, int reg)
+static inline int au1000_usb_init(unsigned long rb, int reg)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
        unsigned long r = __raw_readl(base);
+       struct clk *c;
+
+       /* 48MHz check. Don't init if no one can provide it */
+       c = clk_get(NULL, "usbh_clk");
+       if (IS_ERR(c))
+               return -ENODEV;
+       if (clk_round_rate(c, 48000000) != 48000000) {
+               clk_put(c);
+               return -ENODEV;
+       }
+       if (clk_set_rate(c, 48000000)) {
+               clk_put(c);
+               return -ENODEV;
+       }
+       clk_put(c);
 
 #if defined(__BIG_ENDIAN)
        r |= USBHEN_BE;
@@ -400,6 +416,8 @@ static inline void au1000_usb_init(unsigned long rb, int reg)
        __raw_writel(r, base);
        wmb();
        udelay(1000);
+
+       return 0;
 }
 
 
@@ -407,8 +425,15 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
        unsigned long r = __raw_readl(base + creg);
+       struct clk *c = clk_get(NULL, "usbh_clk");
+
+       if (IS_ERR(c))
+               return;
 
        if (enable) {
+               if (clk_prepare_enable(c))
+                       goto out;
+
                __raw_writel(r | USBHEN_CE, base + creg);
                wmb();
                udelay(1000);
@@ -423,7 +448,10 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
        } else {
                __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
                wmb();
+               clk_disable_unprepare(c);
        }
+out:
+       clk_put(c);
 }
 
 static inline int au1000_usb_control(int block, int enable, unsigned long rb,
@@ -457,11 +485,11 @@ int alchemy_usb_control(int block, int enable)
        case ALCHEMY_CPU_AU1500:
        case ALCHEMY_CPU_AU1100:
                ret = au1000_usb_control(block, enable,
-                               AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+                       AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
                break;
        case ALCHEMY_CPU_AU1550:
                ret = au1000_usb_control(block, enable,
-                               AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+                       AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
                break;
        case ALCHEMY_CPU_AU1200:
                ret = au1200_usb_control(block, enable);
@@ -569,14 +597,18 @@ static struct syscore_ops alchemy_usb_pm_ops = {
 
 static int __init alchemy_usb_init(void)
 {
+       int ret = 0;
+
        switch (alchemy_get_cputype()) {
        case ALCHEMY_CPU_AU1000:
        case ALCHEMY_CPU_AU1500:
        case ALCHEMY_CPU_AU1100:
-               au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+               ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
+                                     AU1000_OHCICFG);
                break;
        case ALCHEMY_CPU_AU1550:
-               au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+               ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
+                                     AU1550_OHCICFG);
                break;
        case ALCHEMY_CPU_AU1200:
                au1200_usb_init();
@@ -586,8 +618,9 @@ static int __init alchemy_usb_init(void)
                break;
        }
 
-       register_syscore_ops(&alchemy_usb_pm_ops);
+       if (!ret)
+               register_syscore_ops(&alchemy_usb_pm_ops);
 
-       return 0;
+       return ret;
 }
 arch_initcall(alchemy_usb_init);
index 92dd929..001102e 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
@@ -496,6 +497,7 @@ int __init db1000_dev_setup(void)
        int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
        int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
        unsigned long pfc;
+       struct clk *c, *p;
 
        if (board == BCSR_WHOAMI_DB1500) {
                c0 = AU1500_GPIO2_INT;
@@ -518,14 +520,25 @@ int __init db1000_dev_setup(void)
                gpio_direction_input(20);       /* sd1 cd# */
 
                /* spi_gpio on SSI0 pins */
-               pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
+               pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
                pfc |= (1 << 0);        /* SSI0 pins as GPIOs */
-               __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-               wmb();
+               alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
                spi_register_board_info(db1100_spi_info,
                                        ARRAY_SIZE(db1100_spi_info));
 
+               /* link LCD clock to AUXPLL */
+               p = clk_get(NULL, "auxpll_clk");
+               c = clk_get(NULL, "lcd_intclk");
+               if (!IS_ERR(c) && !IS_ERR(p)) {
+                       clk_set_parent(c, p);
+                       clk_set_rate(c, clk_get_rate(p));
+               }
+               if (!IS_ERR(c))
+                       clk_put(c);
+               if (!IS_ERR(p))
+                       clk_put(p);
+
                platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
                platform_device_register(&db1100_spi_dev);
        } else if (board == BCSR_WHOAMI_DB1000) {
index 9e46667..7761889 100644 (file)
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -129,7 +130,6 @@ static int __init db1200_detect_board(void)
 
 int __init db1200_board_setup(void)
 {
-       unsigned long freq0, clksrc, div, pfc;
        unsigned short whoami;
 
        if (db1200_detect_board())
@@ -149,34 +149,6 @@ int __init db1200_board_setup(void)
                "  Board-ID %d  Daughtercard ID %d\n", get_system_type(),
                (whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
 
-       /* SMBus/SPI on PSC0, Audio on PSC1 */
-       pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
-       pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
-       pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
-       pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
-       __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-       wmb();
-
-       /* Clock configurations: PSC0: ~50MHz via Clkgen0, derived from
-        * CPU clock; all other clock generators off/unused.
-        */
-       div = (get_au1x00_speed() + 25000000) / 50000000;
-       if (div & 1)
-               div++;
-       div = ((div >> 1) - 1) & 0xff;
-
-       freq0 = div << SYS_FC_FRDIV0_BIT;
-       __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-       wmb();
-       freq0 |= SYS_FC_FE0;    /* enable F0 */
-       __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-       wmb();
-
-       /* psc0_intclk comes 1:1 from F0 */
-       clksrc = SYS_CS_MUX_FQ0 << SYS_CS_ME0_BIT;
-       __raw_writel(clksrc, (void __iomem *)SYS_CLKSRC);
-       wmb();
-
        return 0;
 }
 
@@ -250,7 +222,7 @@ static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 
 static int au1200_nand_device_ready(struct mtd_info *mtd)
 {
-       return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+       return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1200_nand_parts[] = {
@@ -847,6 +819,7 @@ int __init db1200_dev_setup(void)
        unsigned long pfc;
        unsigned short sw;
        int swapped, bid;
+       struct clk *c;
 
        bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
        if ((bid == BCSR_WHOAMI_PB1200_DDR1) ||
@@ -859,6 +832,24 @@ int __init db1200_dev_setup(void)
        irq_set_irq_type(AU1200_GPIO7_INT, IRQ_TYPE_LEVEL_LOW);
        bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
 
+       /* SMBus/SPI on PSC0, Audio on PSC1 */
+       pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
+       pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
+       pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
+       pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
+       alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
+
+       /* get 50MHz for I2C driver on PSC0 */
+       c = clk_get(NULL, "psc0_intclk");
+       if (!IS_ERR(c)) {
+               pfc = clk_round_rate(c, 50000000);
+               if ((pfc < 1) || (abs(50000000 - pfc) > 2500000))
+                       pr_warn("DB1200: cant get I2C close to 50MHz\n");
+               else
+                       clk_set_rate(c, pfc);
+               clk_put(c);
+       }
+
        /* insert/eject pairs: one of both is always screaming.  To avoid
         * issues they must not be automatically enabled when initially
         * requested.
@@ -886,7 +877,7 @@ int __init db1200_dev_setup(void)
         * As a result, in SPI mode, OTG simply won't work (PSC0 uses
         * it as an input pin which is pulled high on the boards).
         */
-       pfc = __raw_readl((void __iomem *)SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
+       pfc = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
 
        /* switch off OTG VBUS supply */
        gpio_request(215, "otg-vbus");
@@ -912,8 +903,7 @@ int __init db1200_dev_setup(void)
                printk(KERN_INFO " S6.8 ON : PSC0 mode SPI\n");
                printk(KERN_INFO "   OTG port VBUS supply disabled\n");
        }
-       __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-       wmb();
+       alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
        /* Audio: DIP7 selects I2S(0)/AC97(1), but need I2C for I2S!
         * so: DIP7=1 || DIP8=0 => AC97, DIP7=0 && DIP8=1 => I2S
@@ -932,6 +922,11 @@ int __init db1200_dev_setup(void)
        }
 
        /* Audio PSC clock is supplied externally. (FIXME: platdata!!) */
+       c = clk_get(NULL, "psc1_intclk");
+       if (!IS_ERR(c)) {
+               clk_prepare_enable(c);
+               clk_put(c);
+       }
        __raw_writel(PSC_SEL_CLK_SERCLK,
            (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
        wmb();
index 1aed6be..ef93ee3 100644 (file)
@@ -4,6 +4,7 @@
  * (c) 2009 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
@@ -169,7 +170,7 @@ static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 
 static int au1300_nand_device_ready(struct mtd_info *mtd)
 {
-       return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+       return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1300_nand_parts[] = {
@@ -731,6 +732,7 @@ static struct platform_device *db1300_dev[] __initdata = {
 int __init db1300_dev_setup(void)
 {
        int swapped, cpldirq;
+       struct clk *c;
 
        /* setup CPLD IRQ muxer */
        cpldirq = au1300_gpio_to_irq(AU1300_PIN_EXTCLK1);
@@ -761,6 +763,11 @@ int __init db1300_dev_setup(void)
            (void __iomem *)KSEG1ADDR(AU1300_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET);
        wmb();
        /* I2C uses internal 48MHz EXTCLK1 */
+       c = clk_get(NULL, "psc3_intclk");
+       if (!IS_ERR(c)) {
+               clk_prepare_enable(c);
+               clk_put(c);
+       }
        __raw_writel(PSC_SEL_CLK_INTCLK,
            (void __iomem *)KSEG1ADDR(AU1300_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET);
        wmb();
index bbd8d98..7e89936 100644 (file)
@@ -4,6 +4,7 @@
  * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 static void __init db1550_hw_setup(void)
 {
        void __iomem *base;
+       unsigned long v;
 
        /* complete SPI setup: link psc0_intclk to a 48MHz source,
         * and assign GPIO16 to PSC0_SYNC1 (SPI cs# line) as well as PSC1_SYNC
         * for AC97 on PB1550.
         */
-       base = (void __iomem *)SYS_CLKSRC;
-       __raw_writel(__raw_readl(base) | 0x000001e0, base);
-       base = (void __iomem *)SYS_PINFUNC;
-       __raw_writel(__raw_readl(base) | 1 | SYS_PF_PSC1_S1, base);
-       wmb();
+       v = alchemy_rdsys(AU1000_SYS_CLKSRC);
+       alchemy_wrsys(v | 0x000001e0, AU1000_SYS_CLKSRC);
+       v = alchemy_rdsys(AU1000_SYS_PINFUNC);
+       alchemy_wrsys(v | 1 | SYS_PF_PSC1_S1, AU1000_SYS_PINFUNC);
 
        /* reset the AC97 codec now, the reset time in the psc-ac97 driver
         * is apparently too short although it's ridiculous as it is.
@@ -151,7 +152,7 @@ static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 
 static int au1550_nand_device_ready(struct mtd_info *mtd)
 {
-       return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+       return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1550_nand_parts[] = {
@@ -217,7 +218,7 @@ static struct platform_device pb1550_nand_dev = {
 
 static void __init pb1550_nand_setup(void)
 {
-       int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) |
+       int boot_swapboot = (alchemy_rdsmem(AU1000_MEM_STSTAT) & (0x7 << 1)) |
                            ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
 
        gpio_direction_input(206);      /* de-assert NAND CS# */
@@ -574,6 +575,7 @@ static void __init pb1550_devices(void)
 int __init db1550_dev_setup(void)
 {
        int swapped, id;
+       struct clk *c;
 
        id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550);
 
@@ -582,6 +584,17 @@ int __init db1550_dev_setup(void)
        spi_register_board_info(db1550_spi_devs,
                                ARRAY_SIZE(db1550_i2c_devs));
 
+       c = clk_get(NULL, "psc0_intclk");
+       if (!IS_ERR(c)) {
+               clk_prepare_enable(c);
+               clk_put(c);
+       }
+       c = clk_get(NULL, "psc2_intclk");
+       if (!IS_ERR(c)) {
+               clk_prepare_enable(c);
+               clk_put(c);
+       }
+
        /* Audio PSC clock is supplied by codecs (PSC1, 3) FIXME: platdata!! */
        __raw_writel(PSC_SEL_CLK_SERCLK,
            (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
index 61e90fe..bfeb8f3 100644 (file)
@@ -45,23 +45,20 @@ static int db1x_pm_enter(suspend_state_t state)
        alchemy_gpio1_input_enable();
 
        /* clear and setup wake cause and source */
-       au_writel(0, SYS_WAKEMSK);
-       au_sync();
-       au_writel(0, SYS_WAKESRC);
-       au_sync();
+       alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+       alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 
-       au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
-       au_sync();
+       alchemy_wrsys(db1x_pm_wakemsk, AU1000_SYS_WAKEMSK);
 
        /* setup 1Hz-timer-based wakeup: wait for reg access */
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+       while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
                asm volatile ("nop");
 
-       au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
-       au_sync();
+       alchemy_wrsys(alchemy_rdsys(AU1000_SYS_TOYREAD) + db1x_pm_sleep_secs,
+                     AU1000_SYS_TOYMATCH2);
 
        /* wait for value to really hit the register */
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+       while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
                asm volatile ("nop");
 
        /* ...and now the sandman can come! */
@@ -102,12 +99,10 @@ static void db1x_pm_end(void)
        /* read and store wakeup source, the clear the register. To
         * be able to clear it, WAKEMSK must be cleared first.
         */
-       db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
-
-       au_writel(0, SYS_WAKEMSK);
-       au_writel(0, SYS_WAKESRC);
-       au_sync();
+       db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
+       alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+       alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 }
 
 static const struct platform_suspend_ops db1x_pm_ops = {
@@ -242,17 +237,13 @@ static int __init pm_init(void)
         * for confirmation since there's plenty of time from here to
         * the next suspend cycle.
         */
-       if (au_readl(SYS_TOYTRIM) != 32767) {
-               au_writel(32767, SYS_TOYTRIM);
-               au_sync();
-       }
+       if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767)
+               alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
 
-       db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+       db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
-       au_writel(0, SYS_WAKESRC);
-       au_sync();
-       au_writel(0, SYS_WAKEMSK);
-       au_sync();
+       alchemy_wrsys(0, AU1000_SYS_WAKESRC);
+       alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
 
        suspend_set_ops(&db1x_pm_ops);
 
index 09cb6f7..fc21d36 100644 (file)
@@ -11,8 +11,6 @@ config BCM47XX_SSB
        select SSB_DRIVER_PCICORE if PCI
        select SSB_PCICORE_HOSTMODE if PCI
        select SSB_DRIVER_GPIO
-       select GPIOLIB
-       select LEDS_GPIO_REGISTER
        default y
        help
         Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -22,6 +20,7 @@ config BCM47XX_SSB
 config BCM47XX_BCMA
        bool "BCMA Support for Broadcom BCM47XX"
        select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_HIGHMEM
        select CPU_MIPSR2_IRQ_VI
        select BCMA
        select BCMA_HOST_SOC
@@ -29,8 +28,6 @@ config BCM47XX_BCMA
        select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
        select BCMA_DRIVER_GPIO
-       select GPIOLIB
-       select LEDS_GPIO_REGISTER
        default y
        help
         Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
index 0194c3b..f1cc9d0 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <linux/kernel.h>
 
+/* prom.c */
+void __init bcm47xx_prom_highmem_init(void);
+
 /* buttons.c */
 int __init bcm47xx_buttons_register(void);
 
index 44ab1be..b3ae068 100644 (file)
@@ -58,6 +58,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst =
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
        {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
+       {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
        {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
        {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
        {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
@@ -80,6 +81,14 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initcons
        { {0}, NULL},
 };
 
+/* hardware_version, boardnum */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
+       {{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
+       {{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
+       { {0}, NULL},
+};
+
 /* productid */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
@@ -98,7 +107,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
 /* ModelId */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
-       {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+       {{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
        {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
        {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
        {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
@@ -180,9 +189,9 @@ struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = {
        {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
        {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
        {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
-       {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
-       {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
-       {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+       {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+       {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+       {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
        { {0}, NULL},
 };
 
@@ -237,6 +246,15 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
                }
        }
 
+       if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
+           bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
+               for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+                       if (!strstarts(buf1, e2->value1) &&
+                           !strcmp(buf2, e2->value2))
+                               return &e2->board;
+               }
+       }
+
        if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
                for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
                        if (!strcmp(buf1, e1->value1))
index 49a1ce0..913182b 100644 (file)
@@ -55,6 +55,11 @@ bcm47xx_buttons_asus_wl330ge[] __initconst = {
        BCM47XX_GPIO_KEY(2, KEY_RESTART),
 };
 
+static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500g[] __initconst = {
+       BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
 static const struct gpio_keys_button
 bcm47xx_buttons_asus_wl500gd[] __initconst = {
        BCM47XX_GPIO_KEY(6, KEY_RESTART),
@@ -265,7 +270,7 @@ bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
 };
 
 static const struct gpio_keys_button
-bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
        BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
        BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -288,6 +293,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
        BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
 
+/* Microsoft */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_microsoft_nm700[] __initconst = {
+       BCM47XX_GPIO_KEY(7, KEY_RESTART),
+};
+
 /* Motorola */
 
 static const struct gpio_keys_button
@@ -328,6 +340,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
        BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
 
+static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
+       BCM47XX_GPIO_KEY(4, KEY_RESTART),
+       BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+};
+
 static const struct gpio_keys_button
 bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
        BCM47XX_GPIO_KEY(6, KEY_RESTART),
@@ -395,6 +413,9 @@ int __init bcm47xx_buttons_register(void)
        case BCM47XX_BOARD_ASUS_WL330GE:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
                break;
+       case BCM47XX_BOARD_ASUS_WL500G:
+               err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
+               break;
        case BCM47XX_BOARD_ASUS_WL500GD:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
                break;
@@ -501,12 +522,14 @@ int __init bcm47xx_buttons_register(void)
        case BCM47XX_BOARD_LINKSYS_WRT310NV1:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
                break;
-       case BCM47XX_BOARD_LINKSYS_WRT54G:
-               err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
-               break;
        case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
                break;
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+               err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
+               break;
        case BCM47XX_BOARD_LINKSYS_WRT610NV1:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
                break;
@@ -517,6 +540,10 @@ int __init bcm47xx_buttons_register(void)
                err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
                break;
 
+       case BCM47XX_BOARD_MICROSOFT_MN700:
+               err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
+               break;
+
        case BCM47XX_BOARD_MOTOROLA_WE800G:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
                break;
@@ -536,6 +563,9 @@ int __init bcm47xx_buttons_register(void)
        case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
                break;
+       case BCM47XX_BOARD_NETGEAR_WNR3500L:
+               err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
+               break;
        case BCM47XX_BOARD_NETGEAR_WNR834BV2:
                err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
                break;
index adcb547..903a656 100644 (file)
@@ -34,6 +34,15 @@ bcm47xx_leds_asus_rtn12[] __initconst = {
        BCM47XX_GPIO_LED(7, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
 
+static const struct gpio_led
+bcm47xx_leds_asus_rtn15u[] __initconst = {
+       /* TODO: Add "wlan" LED */
+       BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
 static const struct gpio_led
 bcm47xx_leds_asus_rtn16[] __initconst = {
        BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
@@ -42,8 +51,8 @@ bcm47xx_leds_asus_rtn16[] __initconst = {
 
 static const struct gpio_led
 bcm47xx_leds_asus_rtn66u[] __initconst = {
-       BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-       BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
 };
 
 static const struct gpio_led
@@ -63,6 +72,11 @@ bcm47xx_leds_asus_wl330ge[] __initconst = {
        BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 };
 
+static const struct gpio_led
+bcm47xx_leds_asus_wl500g[] __initconst = {
+       BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
 static const struct gpio_led
 bcm47xx_leds_asus_wl500gd[] __initconst = {
        BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
@@ -216,8 +230,8 @@ bcm47xx_leds_linksys_e1000v1[] __initconst = {
 
 static const struct gpio_led
 bcm47xx_leds_linksys_e1000v21[] __initconst = {
-       BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-       BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
        BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
        BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
@@ -292,7 +306,7 @@ bcm47xx_leds_linksys_wrt310nv1[] __initconst = {
 };
 
 static const struct gpio_led
-bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
        BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
        BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
        BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -306,6 +320,24 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __initconst = {
        BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
 
+/* Verified on: WRT54GS V1.0 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
+       BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Verified on: WRT54GL V1.1 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
+       BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
 static const struct gpio_led
 bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
        BCM47XX_GPIO_LED(0, "unk", "usb",  1, LEDS_GPIO_DEFSTATE_OFF),
@@ -325,11 +357,17 @@ bcm47xx_leds_linksys_wrt610nv2[] __initconst = {
 
 static const struct gpio_led
 bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
-       BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-       BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-       BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-       BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-       BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Microsoft */
+
+static const struct gpio_led
+bcm47xx_leds_microsoft_nm700[] __initconst = {
+       BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 };
 
 /* Motorola */
@@ -376,6 +414,15 @@ bcm47xx_leds_netgear_wndr4500v1[] __initconst = {
        BCM47XX_GPIO_LED(14, "green", "usb2", 1, LEDS_GPIO_DEFSTATE_OFF),
 };
 
+static const struct gpio_led
+bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
+       BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+       BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+       BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
 static const struct gpio_led
 bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
        BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
@@ -417,6 +464,9 @@ void __init bcm47xx_leds_register(void)
        case BCM47XX_BOARD_ASUS_RTN12:
                bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
                break;
+       case BCM47XX_BOARD_ASUS_RTN15U:
+               bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
+               break;
        case BCM47XX_BOARD_ASUS_RTN16:
                bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
                break;
@@ -432,6 +482,9 @@ void __init bcm47xx_leds_register(void)
        case BCM47XX_BOARD_ASUS_WL330GE:
                bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
                break;
+       case BCM47XX_BOARD_ASUS_WL500G:
+               bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
+               break;
        case BCM47XX_BOARD_ASUS_WL500GD:
                bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
                break;
@@ -538,12 +591,18 @@ void __init bcm47xx_leds_register(void)
        case BCM47XX_BOARD_LINKSYS_WRT310NV1:
                bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
                break;
-       case BCM47XX_BOARD_LINKSYS_WRT54G:
-               bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
-               break;
        case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
                bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
                break;
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+               bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
+               break;
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+               bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
+               break;
+       case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+               bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+               break;
        case BCM47XX_BOARD_LINKSYS_WRT610NV1:
                bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
                break;
@@ -554,6 +613,10 @@ void __init bcm47xx_leds_register(void)
                bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
                break;
 
+       case BCM47XX_BOARD_MICROSOFT_MN700:
+               bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
+               break;
+
        case BCM47XX_BOARD_MOTOROLA_WE800G:
                bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
                break;
@@ -570,6 +633,9 @@ void __init bcm47xx_leds_register(void)
        case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
                bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
                break;
+       case BCM47XX_BOARD_NETGEAR_WNR3500L:
+               bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
+               break;
        case BCM47XX_BOARD_NETGEAR_WNR834BV2:
                bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
                break;
index 1a03a2f..1b170bf 100644 (file)
@@ -51,6 +51,8 @@ __init void bcm47xx_set_system_type(u16 chip_id)
                 chip_id);
 }
 
+static unsigned long lowmem __initdata;
+
 static __init void prom_init_mem(void)
 {
        unsigned long mem;
@@ -87,6 +89,7 @@ static __init void prom_init_mem(void)
                if (!memcmp(prom_init, prom_init + mem, 32))
                        break;
        }
+       lowmem = mem;
 
        /* Ignoring the last page when ddr size is 128M. Cached
         * accesses to last page is causing the processor to prefetch
@@ -95,7 +98,6 @@ static __init void prom_init_mem(void)
         */
        if (c->cputype == CPU_74K && (mem == (128  << 20)))
                mem -= 0x1000;
-
        add_memory_region(0, mem, BOOT_MEM_RAM);
 }
 
@@ -114,3 +116,67 @@ void __init prom_init(void)
 void __init prom_free_prom_memory(void)
 {
 }
+
+#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
+
+#define EXTVBASE       0xc0000000
+#define ENTRYLO(x)     ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
+
+#include <asm/tlbflush.h>
+
+/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
+ * dropped. Calling it at this stage causes a hang.
+ */
+void __cpuinit early_tlb_init(void)
+{
+       write_c0_pagemask(PM_DEFAULT_MASK);
+       write_c0_wired(0);
+       temp_tlb_entry = current_cpu_data.tlbsize - 1;
+       local_flush_tlb_all();
+}
+
+void __init bcm47xx_prom_highmem_init(void)
+{
+       unsigned long off = (unsigned long)prom_init;
+       unsigned long extmem = 0;
+       bool highmem_region = false;
+
+       if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
+               return;
+
+       if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
+               highmem_region = true;
+
+       if (lowmem != 128 << 20 || !highmem_region)
+               return;
+
+       early_tlb_init();
+
+       /* Add one temporary TLB entry to map SDRAM Region 2.
+        *      Physical        Virtual
+        *      0x80000000      0xc0000000      (1st: 256MB)
+        *      0x90000000      0xd0000000      (2nd: 256MB)
+        */
+       add_temporary_entry(ENTRYLO(0x80000000),
+                           ENTRYLO(0x80000000 + (256 << 20)),
+                           EXTVBASE, PM_256M);
+
+       off = EXTVBASE + __pa(off);
+       for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
+               if (!memcmp(prom_init, (void *)(off + extmem), 16))
+                       break;
+       }
+       extmem -= lowmem;
+
+       early_tlb_init();
+
+       if (!extmem)
+               return;
+
+       pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
+               extmem >> 20);
+
+       /* TODO: Register extra memory */
+}
+
+#endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */
index 63a4b0e..2b63e7e 100644 (file)
@@ -59,12 +59,12 @@ static void bcm47xx_machine_restart(char *command)
        switch (bcm47xx_bus_type) {
 #ifdef CONFIG_BCM47XX_SSB
        case BCM47XX_BUS_TYPE_SSB:
-               ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+               ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 3);
                break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
        case BCM47XX_BUS_TYPE_BCMA:
-               bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+               bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 3);
                break;
 #endif
        }
@@ -218,6 +218,9 @@ void __init plat_mem_setup(void)
                bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
                bcm47xx_register_bcma();
                bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
+#ifdef CONFIG_HIGHMEM
+               bcm47xx_prom_highmem_init();
+#endif
 #endif
        } else {
                printk(KERN_INFO "bcm47xx: using ssb bus\n");
index da4cdb1..41226b6 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <bcm47xx.h>
 #include <bcm47xx_nvram.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 static void create_key(const char *prefix, const char *postfix,
                       const char *name, char *buf, int len)
@@ -631,6 +633,33 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
        }
 }
 
+static bool bcm47xx_is_valid_mac(u8 *mac)
+{
+       return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
+}
+
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
+{
+       u8 *oui = mac + ETH_ALEN/2 - 1;
+       u8 *p = mac + ETH_ALEN - 1;
+
+       do {
+               (*p) += num;
+               if (*p > num)
+                       break;
+               p--;
+               num = 1;
+       } while (p != oui);
+
+       if (p == oui) {
+               pr_err("unable to fetch mac address\n");
+               return -ENOENT;
+       }
+       return 0;
+}
+
+static int mac_addr_used = 2;
+
 static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
                                        const char *prefix, bool fallback)
 {
@@ -648,6 +677,25 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
 
        nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
        nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+
+       /* The address prefix 00:90:4C is used by Broadcom in their initial
+          configuration. When a mac address with the prefix 00:90:4C is used
+          all devices from the same series are sharing the same mac address.
+          To prevent mac address collisions we replace them with a mac address
+          based on the base address. */
+       if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
+               u8 mac[6];
+
+               nvram_read_macaddr(NULL, "et0macaddr", mac, false);
+               if (bcm47xx_is_valid_mac(mac)) {
+                       int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
+
+                       if (!err) {
+                               ether_addr_copy(sprom->il0mac, mac);
+                               mac_addr_used++;
+                       }
+               }
+       }
 }
 
 static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
index fd4e76c..536f644 100644 (file)
@@ -24,7 +24,9 @@ EXPORT_SYMBOL(bcm63xx_regs_base);
 const int *bcm63xx_irqs;
 EXPORT_SYMBOL(bcm63xx_irqs);
 
-static u16 bcm63xx_cpu_id;
+u16 bcm63xx_cpu_id __read_mostly;
+EXPORT_SYMBOL(bcm63xx_cpu_id);
+
 static u8 bcm63xx_cpu_rev;
 static unsigned int bcm63xx_cpu_freq;
 static unsigned int bcm63xx_memory_size;
@@ -97,13 +99,6 @@ static const int bcm6368_irqs[] = {
 
 };
 
-u16 __bcm63xx_get_cpu_id(void)
-{
-       return bcm63xx_cpu_id;
-}
-
-EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
-
 u8 bcm63xx_get_cpu_rev(void)
 {
        return bcm63xx_cpu_rev;
index 52bc01d..e828477 100644 (file)
@@ -14,7 +14,6 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 static const unsigned long bcm6348_regs_enetdmac[] = {
        [ENETDMAC_CHANCFG]      = ENETDMAC_CHANCFG_REG,
        [ENETDMAC_IR]           = ENETDMAC_IR_REG,
@@ -43,9 +42,6 @@ static __init void bcm63xx_enetdmac_regs_init(void)
        else
                bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
 }
-#else
-static __init void bcm63xx_enetdmac_regs_init(void) { }
-#endif
 
 static struct resource shared_res[] = {
        {
index d12daed..ad448e4 100644 (file)
@@ -18,7 +18,6 @@
 #include <bcm63xx_dev_spi.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 /*
  * register offsets
  */
@@ -41,9 +40,6 @@ static __init void bcm63xx_spi_regs_init(void)
                BCMCPU_IS_6362() || BCMCPU_IS_6368())
                bcm63xx_regs_spi = bcm6358_regs_spi;
 }
-#else
-static __init void bcm63xx_spi_regs_init(void) { }
-#endif
 
 static struct resource spi_resources[] = {
        {
index a6c2135..468bc7b 100644 (file)
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifndef BCMCPU_RUNTIME_DETECT
-#define gpio_out_low_reg       GPIO_DATA_LO_REG
-#ifdef CONFIG_BCM63XX_CPU_6345
-#ifdef gpio_out_low_reg
-#undef gpio_out_low_reg
-#define gpio_out_low_reg       GPIO_DATA_LO_REG_6345
-#endif /* gpio_out_low_reg */
-#endif /* CONFIG_BCM63XX_CPU_6345 */
-
-static inline void bcm63xx_gpio_out_low_reg_init(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
 static u32 gpio_out_low_reg;
 
 static void bcm63xx_gpio_out_low_reg_init(void)
@@ -44,7 +31,6 @@ static void bcm63xx_gpio_out_low_reg_init(void)
                break;
        }
 }
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
 static u32 gpio_out_low, gpio_out_high;
index 1525f8a..37eb2d1 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/spinlock.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <bcm63xx_cpu.h>
 #include <bcm63xx_io.h>
 #include <bcm63xx_irq.h>
 
-static void __dispatch_internal(void) __maybe_unused;
-static void __dispatch_internal_64(void) __maybe_unused;
-static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
-
-#ifndef BCMCPU_RUNTIME_DETECT
-#ifdef CONFIG_BCM63XX_CPU_3368
-#define irq_stat_reg           PERF_IRQSTAT_3368_REG
-#define irq_mask_reg           PERF_IRQMASK_3368_REG
-#define irq_bits               32
-#define is_ext_irq_cascaded    0
-#define ext_irq_start          0
-#define ext_irq_end            0
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_3368
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-#define irq_stat_reg           PERF_IRQSTAT_6328_REG
-#define irq_mask_reg           PERF_IRQMASK_6328_REG
-#define irq_bits               64
-#define is_ext_irq_cascaded    1
-#define ext_irq_start          (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end            (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6328
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-#define irq_stat_reg           PERF_IRQSTAT_6338_REG
-#define irq_mask_reg           PERF_IRQMASK_6338_REG
-#define irq_bits               32
-#define is_ext_irq_cascaded    0
-#define ext_irq_start          0
-#define ext_irq_end            0
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6338
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-#define irq_stat_reg           PERF_IRQSTAT_6345_REG
-#define irq_mask_reg           PERF_IRQMASK_6345_REG
-#define irq_bits               32
-#define is_ext_irq_cascaded    0
-#define ext_irq_start          0
-#define ext_irq_end            0
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6345
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-#define irq_stat_reg           PERF_IRQSTAT_6348_REG
-#define irq_mask_reg           PERF_IRQMASK_6348_REG
-#define irq_bits               32
-#define is_ext_irq_cascaded    0
-#define ext_irq_start          0
-#define ext_irq_end            0
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6348
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-#define irq_stat_reg           PERF_IRQSTAT_6358_REG
-#define irq_mask_reg           PERF_IRQMASK_6358_REG
-#define irq_bits               32
-#define is_ext_irq_cascaded    1
-#define ext_irq_start          (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end            (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6358
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-#define irq_stat_reg           PERF_IRQSTAT_6362_REG
-#define irq_mask_reg           PERF_IRQMASK_6362_REG
-#define irq_bits               64
-#define is_ext_irq_cascaded    1
-#define ext_irq_start          (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end            (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count          4
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6362
-#define ext_irq_cfg_reg2       0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-#define irq_stat_reg           PERF_IRQSTAT_6368_REG
-#define irq_mask_reg           PERF_IRQMASK_6368_REG
-#define irq_bits               64
-#define is_ext_irq_cascaded    1
-#define ext_irq_start          (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end            (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE)
-#define ext_irq_count          6
-#define ext_irq_cfg_reg1       PERF_EXTIRQ_CFG_REG_6368
-#define ext_irq_cfg_reg2       PERF_EXTIRQ_CFG_REG2_6368
-#endif
-
-#if irq_bits == 32
-#define dispatch_internal                      __dispatch_internal
-#define internal_irq_mask                      __internal_irq_mask_32
-#define internal_irq_unmask                    __internal_irq_unmask_32
-#else
-#define dispatch_internal                      __dispatch_internal_64
-#define internal_irq_mask                      __internal_irq_mask_64
-#define internal_irq_unmask                    __internal_irq_unmask_64
-#endif
 
-#define irq_stat_addr  (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
-#define irq_mask_addr  (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
+static DEFINE_SPINLOCK(ipic_lock);
+static DEFINE_SPINLOCK(epic_lock);
 
-static inline void bcm63xx_init_irq(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
-
-static u32 irq_stat_addr, irq_mask_addr;
-static void (*dispatch_internal)(void);
+static u32 irq_stat_addr[2];
+static u32 irq_mask_addr[2];
+static void (*dispatch_internal)(int cpu);
 static int is_ext_irq_cascaded;
 static unsigned int ext_irq_count;
 static unsigned int ext_irq_start, ext_irq_end;
 static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(unsigned int irq);
-static void (*internal_irq_unmask)(unsigned int irq);
+static void (*internal_irq_mask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
 
-static void bcm63xx_init_irq(void)
-{
-       int irq_bits;
-
-       irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
-       irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
-
-       switch (bcm63xx_get_cpu_id()) {
-       case BCM3368_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_3368_REG;
-               irq_mask_addr += PERF_IRQMASK_3368_REG;
-               irq_bits = 32;
-               ext_irq_count = 4;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
-               break;
-       case BCM6328_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6328_REG;
-               irq_mask_addr += PERF_IRQMASK_6328_REG;
-               irq_bits = 64;
-               ext_irq_count = 4;
-               is_ext_irq_cascaded = 1;
-               ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-               ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
-               break;
-       case BCM6338_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6338_REG;
-               irq_mask_addr += PERF_IRQMASK_6338_REG;
-               irq_bits = 32;
-               ext_irq_count = 4;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
-               break;
-       case BCM6345_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6345_REG;
-               irq_mask_addr += PERF_IRQMASK_6345_REG;
-               irq_bits = 32;
-               ext_irq_count = 4;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
-               break;
-       case BCM6348_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6348_REG;
-               irq_mask_addr += PERF_IRQMASK_6348_REG;
-               irq_bits = 32;
-               ext_irq_count = 4;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
-               break;
-       case BCM6358_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6358_REG;
-               irq_mask_addr += PERF_IRQMASK_6358_REG;
-               irq_bits = 32;
-               ext_irq_count = 4;
-               is_ext_irq_cascaded = 1;
-               ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-               ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
-               break;
-       case BCM6362_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6362_REG;
-               irq_mask_addr += PERF_IRQMASK_6362_REG;
-               irq_bits = 64;
-               ext_irq_count = 4;
-               is_ext_irq_cascaded = 1;
-               ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-               ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
-               break;
-       case BCM6368_CPU_ID:
-               irq_stat_addr += PERF_IRQSTAT_6368_REG;
-               irq_mask_addr += PERF_IRQMASK_6368_REG;
-               irq_bits = 64;
-               ext_irq_count = 6;
-               is_ext_irq_cascaded = 1;
-               ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-               ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
-               ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
-               break;
-       default:
-               BUG();
-       }
-
-       if (irq_bits == 32) {
-               dispatch_internal = __dispatch_internal;
-               internal_irq_mask = __internal_irq_mask_32;
-               internal_irq_unmask = __internal_irq_unmask_32;
-       } else {
-               dispatch_internal = __dispatch_internal_64;
-               internal_irq_mask = __internal_irq_mask_64;
-               internal_irq_unmask = __internal_irq_unmask_64;
-       }
-}
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static inline u32 get_ext_irq_perf_reg(int irq)
 {
@@ -252,53 +51,113 @@ static inline void handle_internal(int intbit)
                do_IRQ(intbit + IRQ_INTERNAL_BASE);
 }
 
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+                                    const struct cpumask *m)
+{
+       bool enable = cpu_online(cpu);
+
+#ifdef CONFIG_SMP
+       if (m)
+               enable &= cpu_isset(cpu, *m);
+       else if (irqd_affinity_was_set(d))
+               enable &= cpu_isset(cpu, *d->affinity);
+#endif
+       return enable;
+}
+
 /*
  * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
  * prioritize any interrupt relatively to another. the static counter
  * will resume the loop where it ended the last time we left this
  * function.
  */
-static void __dispatch_internal(void)
-{
-       u32 pending;
-       static int i;
-
-       pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
 
-       if (!pending)
-               return ;
-
-       while (1) {
-               int to_call = i;
-
-               i = (i + 1) & 0x1f;
-               if (pending & (1 << to_call)) {
-                       handle_internal(to_call);
-                       break;
-               }
-       }
+#define BUILD_IPIC_INTERNAL(width)                                     \
+void __dispatch_internal_##width(int cpu)                              \
+{                                                                      \
+       u32 pending[width / 32];                                        \
+       unsigned int src, tgt;                                          \
+       bool irqs_pending = false;                                      \
+       static unsigned int i[2];                                       \
+       unsigned int *next = &i[cpu];                                   \
+       unsigned long flags;                                            \
+                                                                       \
+       /* read registers in reverse order */                           \
+       spin_lock_irqsave(&ipic_lock, flags);                           \
+       for (src = 0, tgt = (width / 32); src < (width / 32); src++) {  \
+               u32 val;                                                \
+                                                                       \
+               val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
+               val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
+               pending[--tgt] = val;                                   \
+                                                                       \
+               if (val)                                                \
+                       irqs_pending = true;                            \
+       }                                                               \
+       spin_unlock_irqrestore(&ipic_lock, flags);                      \
+                                                                       \
+       if (!irqs_pending)                                              \
+               return;                                                 \
+                                                                       \
+       while (1) {                                                     \
+               unsigned int to_call = *next;                           \
+                                                                       \
+               *next = (*next + 1) & (width - 1);                      \
+               if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {  \
+                       handle_internal(to_call);                       \
+                       break;                                          \
+               }                                                       \
+       }                                                               \
+}                                                                      \
+                                                                       \
+static void __internal_irq_mask_##width(struct irq_data *d)            \
+{                                                                      \
+       u32 val;                                                        \
+       unsigned irq = d->irq - IRQ_INTERNAL_BASE;                      \
+       unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
+       unsigned bit = irq & 0x1f;                                      \
+       unsigned long flags;                                            \
+       int cpu;                                                        \
+                                                                       \
+       spin_lock_irqsave(&ipic_lock, flags);                           \
+       for_each_present_cpu(cpu) {                                     \
+               if (!irq_mask_addr[cpu])                                \
+                       break;                                          \
+                                                                       \
+               val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+               val &= ~(1 << bit);                                     \
+               bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+       }                                                               \
+       spin_unlock_irqrestore(&ipic_lock, flags);                      \
+}                                                                      \
+                                                                       \
+static void __internal_irq_unmask_##width(struct irq_data *d,          \
+                                         const struct cpumask *m)      \
+{                                                                      \
+       u32 val;                                                        \
+       unsigned irq = d->irq - IRQ_INTERNAL_BASE;                      \
+       unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
+       unsigned bit = irq & 0x1f;                                      \
+       unsigned long flags;                                            \
+       int cpu;                                                        \
+                                                                       \
+       spin_lock_irqsave(&ipic_lock, flags);                           \
+       for_each_present_cpu(cpu) {                                     \
+               if (!irq_mask_addr[cpu])                                \
+                       break;                                          \
+                                                                       \
+               val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+               if (enable_irq_for_cpu(cpu, d, m))                      \
+                       val |= (1 << bit);                              \
+               else                                                    \
+                       val &= ~(1 << bit);                             \
+               bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+       }                                                               \
+       spin_unlock_irqrestore(&ipic_lock, flags);                      \
 }
 
-static void __dispatch_internal_64(void)
-{
-       u64 pending;
-       static int i;
-
-       pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
-
-       if (!pending)
-               return ;
-
-       while (1) {
-               int to_call = i;
-
-               i = (i + 1) & 0x3f;
-               if (pending & (1ull << to_call)) {
-                       handle_internal(to_call);
-                       break;
-               }
-       }
-}
+BUILD_IPIC_INTERNAL(32);
+BUILD_IPIC_INTERNAL(64);
 
 asmlinkage void plat_irq_dispatch(void)
 {
@@ -317,8 +176,11 @@ asmlinkage void plat_irq_dispatch(void)
                if (cause & CAUSEF_IP1)
                        do_IRQ(1);
                if (cause & CAUSEF_IP2)
-                       dispatch_internal();
-               if (!is_ext_irq_cascaded) {
+                       dispatch_internal(0);
+               if (is_ext_irq_cascaded) {
+                       if (cause & CAUSEF_IP3)
+                               dispatch_internal(1);
+               } else {
                        if (cause & CAUSEF_IP3)
                                do_IRQ(IRQ_EXT_0);
                        if (cause & CAUSEF_IP4)
@@ -335,50 +197,14 @@ asmlinkage void plat_irq_dispatch(void)
  * internal IRQs operations: only mask/unmask on PERF irq mask
  * register.
  */
-static void __internal_irq_mask_32(unsigned int irq)
-{
-       u32 mask;
-
-       mask = bcm_readl(irq_mask_addr);
-       mask &= ~(1 << irq);
-       bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_mask_64(unsigned int irq)
-{
-       u64 mask;
-
-       mask = bcm_readq(irq_mask_addr);
-       mask &= ~(1ull << irq);
-       bcm_writeq(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_32(unsigned int irq)
-{
-       u32 mask;
-
-       mask = bcm_readl(irq_mask_addr);
-       mask |= (1 << irq);
-       bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_64(unsigned int irq)
-{
-       u64 mask;
-
-       mask = bcm_readq(irq_mask_addr);
-       mask |= (1ull << irq);
-       bcm_writeq(mask, irq_mask_addr);
-}
-
 static void bcm63xx_internal_irq_mask(struct irq_data *d)
 {
-       internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
+       internal_irq_mask(d);
 }
 
 static void bcm63xx_internal_irq_unmask(struct irq_data *d)
 {
-       internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
+       internal_irq_unmask(d, NULL);
 }
 
 /*
@@ -389,8 +215,10 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
 {
        unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
        u32 reg, regaddr;
+       unsigned long flags;
 
        regaddr = get_ext_irq_perf_reg(irq);
+       spin_lock_irqsave(&epic_lock, flags);
        reg = bcm_perf_readl(regaddr);
 
        if (BCMCPU_IS_6348())
@@ -399,16 +227,20 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
                reg &= ~EXTIRQ_CFG_MASK(irq % 4);
 
        bcm_perf_writel(reg, regaddr);
+       spin_unlock_irqrestore(&epic_lock, flags);
+
        if (is_ext_irq_cascaded)
-               internal_irq_mask(irq + ext_irq_start);
+               internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
 }
 
 static void bcm63xx_external_irq_unmask(struct irq_data *d)
 {
        unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
        u32 reg, regaddr;
+       unsigned long flags;
 
        regaddr = get_ext_irq_perf_reg(irq);
+       spin_lock_irqsave(&epic_lock, flags);
        reg = bcm_perf_readl(regaddr);
 
        if (BCMCPU_IS_6348())
@@ -417,17 +249,21 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d)
                reg |= EXTIRQ_CFG_MASK(irq % 4);
 
        bcm_perf_writel(reg, regaddr);
+       spin_unlock_irqrestore(&epic_lock, flags);
 
        if (is_ext_irq_cascaded)
-               internal_irq_unmask(irq + ext_irq_start);
+               internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+                                   NULL);
 }
 
 static void bcm63xx_external_irq_clear(struct irq_data *d)
 {
        unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
        u32 reg, regaddr;
+       unsigned long flags;
 
        regaddr = get_ext_irq_perf_reg(irq);
+       spin_lock_irqsave(&epic_lock, flags);
        reg = bcm_perf_readl(regaddr);
 
        if (BCMCPU_IS_6348())
@@ -436,6 +272,7 @@ static void bcm63xx_external_irq_clear(struct irq_data *d)
                reg |= EXTIRQ_CFG_CLEAR(irq % 4);
 
        bcm_perf_writel(reg, regaddr);
+       spin_unlock_irqrestore(&epic_lock, flags);
 }
 
 static int bcm63xx_external_irq_set_type(struct irq_data *d,
@@ -444,6 +281,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
        unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
        u32 reg, regaddr;
        int levelsense, sense, bothedge;
+       unsigned long flags;
 
        flow_type &= IRQ_TYPE_SENSE_MASK;
 
@@ -478,6 +316,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
        }
 
        regaddr = get_ext_irq_perf_reg(irq);
+       spin_lock_irqsave(&epic_lock, flags);
        reg = bcm_perf_readl(regaddr);
        irq %= 4;
 
@@ -522,6 +361,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
        }
 
        bcm_perf_writel(reg, regaddr);
+       spin_unlock_irqrestore(&epic_lock, flags);
 
        irqd_set_trigger_type(d, flow_type);
        if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -532,6 +372,18 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
        return IRQ_SET_MASK_OK_NOCOPY;
 }
 
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+                                        const struct cpumask *dest,
+                                        bool force)
+{
+       if (!irqd_irq_disabled(data))
+               internal_irq_unmask(data, dest);
+
+       return 0;
+}
+#endif
+
 static struct irq_chip bcm63xx_internal_irq_chip = {
        .name           = "bcm63xx_ipic",
        .irq_mask       = bcm63xx_internal_irq_mask,
@@ -554,12 +406,130 @@ static struct irqaction cpu_ip2_cascade_action = {
        .flags          = IRQF_NO_THREAD,
 };
 
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+       .handler        = no_action,
+       .name           = "cascade_ip3",
+       .flags          = IRQF_NO_THREAD,
+};
+#endif
+
 static struct irqaction cpu_ext_cascade_action = {
        .handler        = no_action,
        .name           = "cascade_extirq",
        .flags          = IRQF_NO_THREAD,
 };
 
+static void bcm63xx_init_irq(void)
+{
+       int irq_bits;
+
+       irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
+       irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
+       irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
+       irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+
+       switch (bcm63xx_get_cpu_id()) {
+       case BCM3368_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
+               irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
+               irq_stat_addr[1] = 0;
+               irq_stat_addr[1] = 0;
+               irq_bits = 32;
+               ext_irq_count = 4;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+               break;
+       case BCM6328_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
+               irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+               irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
+               irq_stat_addr[1] += PERF_IRQMASK_6328_REG(1);
+               irq_bits = 64;
+               ext_irq_count = 4;
+               is_ext_irq_cascaded = 1;
+               ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+               ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+               break;
+       case BCM6338_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
+               irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
+               irq_stat_addr[1] = 0;
+               irq_mask_addr[1] = 0;
+               irq_bits = 32;
+               ext_irq_count = 4;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+               break;
+       case BCM6345_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
+               irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
+               irq_stat_addr[1] = 0;
+               irq_mask_addr[1] = 0;
+               irq_bits = 32;
+               ext_irq_count = 4;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+               break;
+       case BCM6348_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
+               irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
+               irq_stat_addr[1] = 0;
+               irq_mask_addr[1] = 0;
+               irq_bits = 32;
+               ext_irq_count = 4;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+               break;
+       case BCM6358_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
+               irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
+               irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
+               irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
+               irq_bits = 32;
+               ext_irq_count = 4;
+               is_ext_irq_cascaded = 1;
+               ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+               ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+               break;
+       case BCM6362_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
+               irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
+               irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
+               irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
+               irq_bits = 64;
+               ext_irq_count = 4;
+               is_ext_irq_cascaded = 1;
+               ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+               ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+               break;
+       case BCM6368_CPU_ID:
+               irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
+               irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
+               irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
+               irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
+               irq_bits = 64;
+               ext_irq_count = 6;
+               is_ext_irq_cascaded = 1;
+               ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+               ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
+               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
+               ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+               break;
+       default:
+               BUG();
+       }
+
+       if (irq_bits == 32) {
+               dispatch_internal = __dispatch_internal_32;
+               internal_irq_mask = __internal_irq_mask_32;
+               internal_irq_unmask = __internal_irq_unmask_32;
+       } else {
+               dispatch_internal = __dispatch_internal_64;
+               internal_irq_mask = __internal_irq_mask_64;
+               internal_irq_unmask = __internal_irq_unmask_64;
+       }
+}
+
 void __init arch_init_irq(void)
 {
        int i;
@@ -580,4 +550,14 @@ void __init arch_init_irq(void)
        }
 
        setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+       if (is_ext_irq_cascaded) {
+               setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+               bcm63xx_internal_irq_chip.irq_set_affinity =
+                       bcm63xx_internal_set_affinity;
+
+               cpumask_clear(irq_default_affinity);
+               cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+       }
+#endif
 }
index acbeb1f..d1fe51e 100644 (file)
 #define BCM6368_RESET_PCIE     0
 #define BCM6368_RESET_PCIE_EXT 0
 
-#ifdef BCMCPU_RUNTIME_DETECT
-
 /*
  * core reset bits
  */
@@ -188,64 +186,6 @@ static int __init bcm63xx_reset_bits_init(void)
 
        return 0;
 }
-#else
-
-#ifdef CONFIG_BCM63XX_CPU_3368
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(3368)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6328
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6328)
-};
-#define reset_reg PERF_SOFTRESET_6328_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6338
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6338)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6345
-static const u32 bcm63xx_reset_bits[] = { };
-#define reset_reg 0
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6348
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6348)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6358
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6358)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6362
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6362)
-};
-#define reset_reg PERF_SOFTRESET_6362_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6368
-static const u32 bcm63xx_reset_bits[] = {
-       __GEN_RESET_BITS_TABLE(6368)
-};
-#define reset_reg PERF_SOFTRESET_6368_REG
-#endif
-
-static int __init bcm63xx_reset_bits_init(void) { return 0; }
-#endif
 
 static DEFINE_SPINLOCK(reset_mutex);
 
index c00c4dd..b49c7ad 100644 (file)
@@ -67,10 +67,24 @@ void error(char *x)
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
+unsigned long __stack_chk_guard;
+
+void __stack_chk_guard_setup(void)
+{
+       __stack_chk_guard = 0x000a0dff;
+}
+
+void __stack_chk_fail(void)
+{
+       error("stack-protector: Kernel stack is corrupted\n");
+}
+
 void decompress_kernel(unsigned long boot_heap_start)
 {
        unsigned long zimage_start, zimage_size;
 
+       __stack_chk_guard_setup();
+
        zimage_start = (unsigned long)(&__image_begin);
        zimage_size = (unsigned long)(&__image_end) -
            (unsigned long)(&__image_begin);
index b764df6..5dfef84 100644 (file)
@@ -186,6 +186,15 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
                        return 7 - ipd_port;
                else
                        return -1;
+       case CVMX_BOARD_TYPE_CUST_DSR1000N:
+               /*
+                * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1)
+                * connect to a switch (BCM53115).
+                */
+               if (ipd_port == 2)
+                       return 8;
+               else
+                       return -1;
        }
 
        /* Some unknown board. Somebody forgot to update this function... */
@@ -274,6 +283,18 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
                        return result;
                }
                break;
+       case CVMX_BOARD_TYPE_CUST_DSR1000N:
+               if (ipd_port == 0 || ipd_port == 1) {
+                       /* Ports 0 and 1 connect to a switch (BCM53115). */
+                       result.s.link_up = 1;
+                       result.s.full_duplex = 1;
+                       result.s.speed = 1000;
+                       return result;
+               } else {
+                       /* Port 2 uses a Broadcom PHY (B5081). */
+                       is_broadcom_phy = 1;
+               }
+               break;
        }
 
        phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
@@ -738,6 +759,7 @@ enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(vo
        case CVMX_BOARD_TYPE_LANAI2_G:
        case CVMX_BOARD_TYPE_NIC10E_66:
        case CVMX_BOARD_TYPE_UBNT_E100:
+       case CVMX_BOARD_TYPE_CUST_DSR1000N:
                return USB_CLOCK_TYPE_CRYSTAL_12;
        case CVMX_BOARD_TYPE_NIC10E:
                return USB_CLOCK_TYPE_REF_12;
index 71b213d..2d68a39 100644 (file)
@@ -194,8 +194,7 @@ err_irq:
 static __exit void oct_ilm_module_exit(void)
 {
        disable_timer(TIMER_NUM);
-       if (dir)
-               debugfs_remove_recursive(dir);
+       debugfs_remove_recursive(dir);
        free_irq(OCTEON_IRQ_TIMER0 + TIMER_NUM, 0);
 }
 
index a7b3ae1..ecd903d 100644 (file)
@@ -84,9 +84,14 @@ static void octeon_smp_hotplug_setup(void)
 #ifdef CONFIG_HOTPLUG_CPU
        struct linux_app_boot_info *labi;
 
+       if (!setup_max_cpus)
+               return;
+
        labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-       if (labi->labi_signature != LABI_SIGNATURE)
-               panic("The bootloader version on this board is incorrect.");
+       if (labi->labi_signature != LABI_SIGNATURE) {
+               pr_info("The bootloader on this board does not support HOTPLUG_CPU.");
+               return;
+       }
 
        octeon_bootloader_entry_addr = labi->InitTLBStart_addr;
 #endif
@@ -129,7 +134,8 @@ static void octeon_smp_setup(void)
         * will assign CPU numbers for possible cores as well.  Cores
         * are always consecutively numberd from 0.
         */
-       for (id = 0; id < num_cores && id < NR_CPUS; id++) {
+       for (id = 0; setup_max_cpus && octeon_bootloader_entry_addr &&
+                    id < num_cores && id < NR_CPUS; id++) {
                if (!(core_mask & (1 << id))) {
                        set_cpu_possible(cpus, true);
                        __cpu_number_map[id] = cpus;
@@ -192,14 +198,6 @@ static void octeon_init_secondary(void)
  */
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
-#ifdef CONFIG_HOTPLUG_CPU
-       struct linux_app_boot_info *labi;
-
-       labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
-       if (labi->labi_signature != LABI_SIGNATURE)
-               panic("The bootloader version on this board is incorrect.");
-#endif
        /*
         * Only the low order mailbox bits are used for IPIs, leave
         * the other bits alone.
@@ -237,6 +235,9 @@ static int octeon_cpu_disable(void)
        if (cpu == 0)
                return -EBUSY;
 
+       if (!octeon_bootloader_entry_addr)
+               return -ENOTSUPP;
+
        set_cpu_online(cpu, false);
        cpu_clear(cpu, cpu_callin_map);
        local_irq_disable();
index fca91a8..4cb787f 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_MACH_LOONGSON=y
 CONFIG_SWIOTLB=y
-CONFIG_LEMOTE_MACH3A=y
+CONFIG_LOONGSON_MACH3X=y
 CONFIG_CPU_LOONGSON3=y
 CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_16KB=y
index 0543918..335e529 100644 (file)
@@ -15,4 +15,5 @@ generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
+generic-y += user.h
 generic-y += xor.h
index 3f74545..3b0e51d 100644 (file)
@@ -52,7 +52,7 @@
  */
 #define CPHYSADDR(a)           ((_ACAST32_(a)) & 0x1fffffff)
 #define XPHYSADDR(a)           ((_ACAST64_(a)) &                       \
-                                _CONST64_(0x000000ffffffffff))
+                                _CONST64_(0x0000ffffffffffff))
 
 #ifdef CONFIG_64BIT
 
index 935543f..cd9a98b 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <asm/hazards.h>
 #include <asm/asm-offsets.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
        st_d    29, THREAD_FPR29, \thread
        st_d    30, THREAD_FPR30, \thread
        st_d    31, THREAD_FPR31, \thread
+       .set    push
+       .set    noat
+       cfcmsa  $1, MSA_CSR
+       sw      $1, THREAD_MSA_CSR(\thread)
+       .set    pop
        .endm
 
        .macro  msa_restore_all thread
+       .set    push
+       .set    noat
+       lw      $1, THREAD_MSA_CSR(\thread)
+       ctcmsa  MSA_CSR, $1
+       .set    pop
        ld_d    0, THREAD_FPR0, \thread
        ld_d    1, THREAD_FPR1, \thread
        ld_d    2, THREAD_FPR2, \thread
        ld_d    31, THREAD_FPR31, \thread
        .endm
 
+       .macro  msa_init_upper wd
+#ifdef CONFIG_64BIT
+       insert_d \wd, 1
+#else
+       insert_w \wd, 2
+       insert_w \wd, 3
+#endif
+       .if     31-\wd
+       msa_init_upper  (\wd+1)
+       .endif
+       .endm
+
+       .macro  msa_init_all_upper
+       .set    push
+       .set    noat
+       not     $1, zero
+       msa_init_upper  0
+       .set    pop
+       .endm
+
 #endif /* _ASM_ASMMACRO_H */
index 7c8816f..bae6b0f 100644 (file)
@@ -559,7 +559,13 @@ static inline int fls(int x)
        int r;
 
        if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
-               __asm__("clz %0, %1" : "=r" (x) : "r" (x));
+               __asm__(
+               "       .set    push                                    \n"
+               "       .set    mips32                                  \n"
+               "       clz     %0, %1                                  \n"
+               "       .set    pop                                     \n"
+               : "=r" (x)
+               : "r" (x));
 
                return 32 - x;
        }
index c1516cc..d035298 100644 (file)
@@ -32,6 +32,14 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
 #define cop2_present           1
 #define cop2_lazy_restore      0
 
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+#define cop2_save(r)
+#define cop2_restore(r)
+
+#define cop2_present           1
+#define cop2_lazy_restore      1
+
 #else
 
 #define cop2_present           0
index c7d8c99..e079598 100644 (file)
 #ifndef cpu_has_eva
 #define cpu_has_eva            (cpu_data[0].options & MIPS_CPU_EVA)
 #endif
+#ifndef cpu_has_htw
+#define cpu_has_htw            (cpu_data[0].options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_has_rixiex
+#define cpu_has_rixiex         (cpu_data[0].options & MIPS_CPU_RIXIEX)
+#endif
+#ifndef cpu_has_maar
+#define cpu_has_maar           (cpu_data[0].options & MIPS_CPU_MAAR)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
index 47d5967..d5f42c1 100644 (file)
@@ -44,8 +44,8 @@ struct cpuinfo_mips {
        /*
         * Capability and feature descriptor structure for MIPS CPU
         */
-       unsigned long           options;
        unsigned long           ases;
+       unsigned long long      options;
        unsigned int            udelay_val;
        unsigned int            processor_id;
        unsigned int            fpu_id;
@@ -61,6 +61,7 @@ struct cpuinfo_mips {
        struct cache_desc       scache; /* Secondary cache */
        struct cache_desc       tcache; /* Tertiary/split secondary cache */
        int                     srsets; /* Shadow register sets */
+       int                     package;/* physical package number */
        int                     core;   /* physical core number */
 #ifdef CONFIG_64BIT
        int                     vmbits; /* Virtual memory size in bits */
@@ -115,7 +116,7 @@ struct proc_cpuinfo_notifier_args {
 #ifdef CONFIG_MIPS_MT_SMP
 # define cpu_vpe_id(cpuinfo)   ((cpuinfo)->vpe_id)
 #else
-# define cpu_vpe_id(cpuinfo)   0
+# define cpu_vpe_id(cpuinfo)   ({ (void)cpuinfo; 0; })
 #endif
 
 #endif /* __ASM_CPU_INFO_H */
index 129d087..dfdc77e 100644 (file)
 #define PRID_REV_LOONGSON2E    0x0002
 #define PRID_REV_LOONGSON2F    0x0003
 #define PRID_REV_LOONGSON3A    0x0005
+#define PRID_REV_LOONGSON3B_R1 0x0006
+#define PRID_REV_LOONGSON3B_R2 0x0007
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -335,34 +337,37 @@ enum cpu_type_enum {
 /*
  * CPU Option encodings
  */
-#define MIPS_CPU_TLB           0x00000001 /* CPU has TLB */
-#define MIPS_CPU_4KEX          0x00000002 /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE      0x00000004 /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE      0x00000008 /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE    0x00000010 /* TX3900-style caches */
-#define MIPS_CPU_FPU           0x00000020 /* CPU has FPU */
-#define MIPS_CPU_32FPR         0x00000040 /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER       0x00000080 /* Cycle count/compare */
-#define MIPS_CPU_WATCH         0x00000100 /* watchpoint registers */
-#define MIPS_CPU_DIVEC         0x00000200 /* dedicated interrupt vector */
-#define MIPS_CPU_VCE           0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P  0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S  0x00001000 /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK                0x00002000 /* Machine check exception */
-#define MIPS_CPU_EJTAG         0x00004000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX       0x00008000 /* no FPU exception */
-#define MIPS_CPU_LLSC          0x00010000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES      0x00020000 /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH      0x00040000 /* CPU has usable prefetch */
-#define MIPS_CPU_VINT          0x00080000 /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC          0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI          0x00200000 /* CPU has ULRI feature */
-#define MIPS_CPU_PCI           0x00400000 /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI          0x00800000 /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS     0x01000000 /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV                0x02000000 /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS      0x04000000 /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA           0x80000000 /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_TLB           0x00000001ull /* CPU has TLB */
+#define MIPS_CPU_4KEX          0x00000002ull /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE      0x00000004ull /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE      0x00000008ull /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE    0x00000010ull /* TX3900-style caches */
+#define MIPS_CPU_FPU           0x00000020ull /* CPU has FPU */
+#define MIPS_CPU_32FPR         0x00000040ull /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER       0x00000080ull /* Cycle count/compare */
+#define MIPS_CPU_WATCH         0x00000100ull /* watchpoint registers */
+#define MIPS_CPU_DIVEC         0x00000200ull /* dedicated interrupt vector */
+#define MIPS_CPU_VCE           0x00000400ull /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P  0x00000800ull /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S  0x00001000ull /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK                0x00002000ull /* Machine check exception */
+#define MIPS_CPU_EJTAG         0x00004000ull /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX       0x00008000ull /* no FPU exception */
+#define MIPS_CPU_LLSC          0x00010000ull /* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES      0x00020000ull /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH      0x00040000ull /* CPU has usable prefetch */
+#define MIPS_CPU_VINT          0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC          0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI          0x00200000ull /* CPU has ULRI feature */
+#define MIPS_CPU_PCI           0x00400000ull /* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI          0x00800000ull /* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS     0x01000000ull /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV                0x02000000ull /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS      0x04000000ull /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA           0x80000000ull /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW           0x100000000ull /* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX                0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR          0x400000000ull /* MAAR(I) registers are present */
 
 /*
  * CPU ASE encodings
index d414405..1d38fe0 100644 (file)
@@ -339,23 +339,6 @@ do {                                                                       \
 
 #endif /* CONFIG_64BIT */
 
-struct pt_regs;
-struct task_struct;
-
-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)
-
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE      PAGE_SIZE
 
index a939574..4d0aeda 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/hazards.h>
 #include <asm/processor.h>
 #include <asm/current.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #include <asm/mips_mt.h>
@@ -141,13 +142,21 @@ static inline int own_fpu(int restore)
 static inline void lose_fpu(int save)
 {
        preempt_disable();
-       if (is_fpu_owner()) {
+       if (is_msa_enabled()) {
+               if (save) {
+                       save_msa(current);
+                       asm volatile("cfc1 %0, $31"
+                               : "=r"(current->thread.fpu.fcr31));
+               }
+               disable_msa();
+               clear_thread_flag(TIF_USEDMSA);
+       } else if (is_fpu_owner()) {
                if (save)
                        _save_fp(current);
-               KSTK_STATUS(current) &= ~ST0_CU1;
-               clear_thread_flag(TIF_USEDFPU);
                __disable_fpu();
        }
+       KSTK_STATUS(current) &= ~ST0_CU1;
+       clear_thread_flag(TIF_USEDFPU);
        preempt_enable();
 }
 
@@ -155,8 +164,6 @@ static inline int init_fpu(void)
 {
        int ret = 0;
 
-       preempt_disable();
-
        if (cpu_has_fpu) {
                ret = __own_fpu();
                if (!ret)
@@ -164,8 +171,6 @@ static inline int init_fpu(void)
        } else
                fpu_emulator_init_fpu();
 
-       preempt_enable();
-
        return ret;
 }
 
index 10f6a99..3f20b21 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/bitmap.h>
 #include <linux/threads.h>
 
+#include <irq.h>
+
 #undef GICISBYTELITTLEENDIAN
 
 /* Constants */
@@ -22,8 +24,6 @@
 #define GIC_TRIG_EDGE                  1
 #define GIC_TRIG_LEVEL                 0
 
-#define GIC_NUM_INTRS                  (24 + NR_CPUS * 2)
-
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)            (*(volatile unsigned int *) (addr))
 #define REG(base, offs)                REG32((unsigned long)(base) + offs##_##OFS)
 #ifdef GICISBYTELITTLEENDIAN
 #define GICREAD(reg, data)     ((data) = (reg), (data) = le32_to_cpu(data))
 #define GICWRITE(reg, data)    ((reg) = cpu_to_le32(data))
-#define GICBIS(reg, bits)                      \
-       ({unsigned int data;                    \
-               GICREAD(reg, data);             \
-               data |= bits;                   \
-               GICWRITE(reg, data);            \
-       })
-
 #else
 #define GICREAD(reg, data)     ((data) = (reg))
 #define GICWRITE(reg, data)    ((reg) = (data))
-#define GICBIS(reg, bits)      ((reg) |= (bits))
 #endif
+#define GICBIS(reg, mask, bits)                        \
+       do { u32 data;                          \
+               GICREAD((reg), data);           \
+               data &= ~(mask);                \
+               data |= ((bits) & (mask));      \
+               GICWRITE((reg), data);          \
+       } while (0)
 
 
 /* GIC Address Space */
 #define GIC_SH_SET_POLARITY_OFS                0x0100
 #define GIC_SET_POLARITY(intr, pol) \
        GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
-               GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
+               GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+               (pol) << GIC_INTR_BIT(intr))
 
 /* Triggering : Reset Value is always 0 */
 #define GIC_SH_SET_TRIGGER_OFS         0x0180
 #define GIC_SET_TRIGGER(intr, trig) \
        GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
-               GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
+               GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+               (trig) << GIC_INTR_BIT(intr))
 
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS               0x0380
        GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
                 GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
 
-struct gic_pcpu_mask {
-       DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
-};
-
-struct gic_pending_regs {
-       DECLARE_BITMAP(pending, GIC_NUM_INTRS);
-};
-
-struct gic_intrmask_regs {
-       DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
-};
-
 /*
  * Interrupt Meta-data specification. The ipiflag helps
  * in building ipi_map.
@@ -329,8 +318,7 @@ struct gic_intr_map {
        unsigned int polarity;  /* Polarity : +/-       */
        unsigned int trigtype;  /* Trigger  : Edge/Levl */
        unsigned int flags;     /* Misc flags   */
-#define GIC_FLAG_IPI          0x01
-#define GIC_FLAG_TRANSPARENT   0x02
+#define GIC_FLAG_TRANSPARENT   0x01
 };
 
 /*
@@ -386,6 +374,7 @@ extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
+extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
 extern void gic_enable_interrupt(int irq_vec);
 extern void gic_disable_interrupt(int irq_vec);
diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h
new file mode 100644 (file)
index 0000000..6c62b0f
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * 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.
+ */
+
+#ifndef __MIPS_ASM_MIPS_MAAR_H__
+#define __MIPS_ASM_MIPS_MAAR_H__
+
+#include <asm/hazards.h>
+#include <asm/mipsregs.h>
+
+/**
+ * platform_maar_init() - perform platform-level MAAR configuration
+ * @num_pairs: The number of MAAR pairs present in the system.
+ *
+ * Platforms should implement this function such that it configures as many
+ * MAAR pairs as required, from 0 up to the maximum of num_pairs-1, and returns
+ * the number that were used. Any further MAARs will be configured to be
+ * invalid. The default implementation of this function will simply indicate
+ * that it has configured 0 MAAR pairs.
+ *
+ * Return:     The number of MAAR pairs configured.
+ */
+unsigned __weak platform_maar_init(unsigned num_pairs);
+
+/**
+ * write_maar_pair() - write to a pair of MAARs
+ * @idx:       The index of the pair (ie. use MAARs idx*2 & (idx*2)+1).
+ * @lower:     The lowest address that the MAAR pair will affect. Must be
+ *             aligned to a 2^16 byte boundary.
+ * @upper:     The highest address that the MAAR pair will affect. Must be
+ *             aligned to one byte before a 2^16 byte boundary.
+ * @attrs:     The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *             MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Program the pair of MAAR registers specified by idx to apply the attributes
+ * specified by attrs to the range of addresses from lower to higher.
+ */
+static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
+                                  phys_addr_t upper, unsigned attrs)
+{
+       /* Addresses begin at bit 16, but are shifted right 4 bits */
+       BUG_ON(lower & (0xffff | ~(MIPS_MAAR_ADDR << 4)));
+       BUG_ON(((upper & 0xffff) != 0xffff)
+               || ((upper & ~0xffffull) & ~(MIPS_MAAR_ADDR << 4)));
+
+       /* Automatically set MIPS_MAAR_V */
+       attrs |= MIPS_MAAR_V;
+
+       /* Write the upper address & attributes (only MIPS_MAAR_V matters) */
+       write_c0_maari(idx << 1);
+       back_to_back_c0_hazard();
+       write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
+       back_to_back_c0_hazard();
+
+       /* Write the lower address & attributes */
+       write_c0_maari((idx << 1) | 0x1);
+       back_to_back_c0_hazard();
+       write_c0_maar((lower >> 4) | attrs);
+       back_to_back_c0_hazard();
+}
+
+/**
+ * struct maar_config - MAAR configuration data
+ * @lower:     The lowest address that the MAAR pair will affect. Must be
+ *             aligned to a 2^16 byte boundary.
+ * @upper:     The highest address that the MAAR pair will affect. Must be
+ *             aligned to one byte before a 2^16 byte boundary.
+ * @attrs:     The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *             MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Describes the configuration of a pair of Memory Accessibility Attribute
+ * Registers - applying attributes from attrs to the range of physical
+ * addresses from lower to upper inclusive.
+ */
+struct maar_config {
+       phys_addr_t lower;
+       phys_addr_t upper;
+       unsigned attrs;
+};
+
+/**
+ * maar_config() - configure MAARs according to provided data
+ * @cfg:       Pointer to an array of struct maar_config.
+ * @num_cfg:   The number of structs in the cfg array.
+ * @num_pairs: The number of MAAR pairs present in the system.
+ *
+ * Configures as many MAARs as are present and specified in the cfg
+ * array with the values taken from the cfg array.
+ *
+ * Return:     The number of MAAR pairs configured.
+ */
+static inline unsigned maar_config(const struct maar_config *cfg,
+                                  unsigned num_cfg, unsigned num_pairs)
+{
+       unsigned i;
+
+       for (i = 0; i < min(num_cfg, num_pairs); i++)
+               write_maar_pair(i, cfg[i].lower, cfg[i].upper, cfg[i].attrs);
+
+       return i;
+}
+
+#endif /* __MIPS_ASM_MIPS_MAAR_H__ */
index b4c3ecb..a7eec33 100644 (file)
 #ifndef _AU1000_H_
 #define _AU1000_H_
 
+/* SOC Interrupt numbers */
+/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
+#define AU1000_INTC0_INT_BASE  (MIPS_CPU_IRQ_BASE + 8)
+#define AU1000_INTC0_INT_LAST  (AU1000_INTC0_INT_BASE + 31)
+#define AU1000_INTC1_INT_BASE  (AU1000_INTC0_INT_LAST + 1)
+#define AU1000_INTC1_INT_LAST  (AU1000_INTC1_INT_BASE + 31)
+#define AU1000_MAX_INTR                AU1000_INTC1_INT_LAST
 
-#ifndef _LANGUAGE_ASSEMBLY
+/* Au1300-style (GPIC): 1 controller with up to 128 sources */
+#define ALCHEMY_GPIC_INT_BASE  (MIPS_CPU_IRQ_BASE + 8)
+#define ALCHEMY_GPIC_INT_NUM   128
+#define ALCHEMY_GPIC_INT_LAST  (ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
 
-#include <linux/delay.h>
-#include <linux/types.h>
+/* common clock names, shared among all variants. AUXPLL2 is Au1300 */
+#define ALCHEMY_ROOT_CLK               "root_clk"
+#define ALCHEMY_CPU_CLK                        "cpu_clk"
+#define ALCHEMY_AUXPLL_CLK             "auxpll_clk"
+#define ALCHEMY_AUXPLL2_CLK            "auxpll2_clk"
+#define ALCHEMY_SYSBUS_CLK             "sysbus_clk"
+#define ALCHEMY_PERIPH_CLK             "periph_clk"
+#define ALCHEMY_MEM_CLK                        "mem_clk"
+#define ALCHEMY_LR_CLK                 "lr_clk"
+#define ALCHEMY_FG0_CLK                        "fg0_clk"
+#define ALCHEMY_FG1_CLK                        "fg1_clk"
+#define ALCHEMY_FG2_CLK                        "fg2_clk"
+#define ALCHEMY_FG3_CLK                        "fg3_clk"
+#define ALCHEMY_FG4_CLK                        "fg4_clk"
+#define ALCHEMY_FG5_CLK                        "fg5_clk"
 
-#include <linux/io.h>
-#include <linux/irq.h>
+/* Au1300 peripheral interrupt numbers */
+#define AU1300_FIRST_INT       (ALCHEMY_GPIC_INT_BASE)
+#define AU1300_UART1_INT       (AU1300_FIRST_INT + 17)
+#define AU1300_UART2_INT       (AU1300_FIRST_INT + 25)
+#define AU1300_UART3_INT       (AU1300_FIRST_INT + 27)
+#define AU1300_SD1_INT         (AU1300_FIRST_INT + 32)
+#define AU1300_SD2_INT         (AU1300_FIRST_INT + 38)
+#define AU1300_PSC0_INT                (AU1300_FIRST_INT + 48)
+#define AU1300_PSC1_INT                (AU1300_FIRST_INT + 52)
+#define AU1300_PSC2_INT                (AU1300_FIRST_INT + 56)
+#define AU1300_PSC3_INT                (AU1300_FIRST_INT + 60)
+#define AU1300_NAND_INT                (AU1300_FIRST_INT + 62)
+#define AU1300_DDMA_INT                (AU1300_FIRST_INT + 75)
+#define AU1300_MMU_INT         (AU1300_FIRST_INT + 76)
+#define AU1300_MPU_INT         (AU1300_FIRST_INT + 77)
+#define AU1300_GPU_INT         (AU1300_FIRST_INT + 78)
+#define AU1300_UDMA_INT                (AU1300_FIRST_INT + 79)
+#define AU1300_TOY_INT         (AU1300_FIRST_INT + 80)
+#define AU1300_TOY_MATCH0_INT  (AU1300_FIRST_INT + 81)
+#define AU1300_TOY_MATCH1_INT  (AU1300_FIRST_INT + 82)
+#define AU1300_TOY_MATCH2_INT  (AU1300_FIRST_INT + 83)
+#define AU1300_RTC_INT         (AU1300_FIRST_INT + 84)
+#define AU1300_RTC_MATCH0_INT  (AU1300_FIRST_INT + 85)
+#define AU1300_RTC_MATCH1_INT  (AU1300_FIRST_INT + 86)
+#define AU1300_RTC_MATCH2_INT  (AU1300_FIRST_INT + 87)
+#define AU1300_UART0_INT       (AU1300_FIRST_INT + 88)
+#define AU1300_SD0_INT         (AU1300_FIRST_INT + 89)
+#define AU1300_USB_INT         (AU1300_FIRST_INT + 90)
+#define AU1300_LCD_INT         (AU1300_FIRST_INT + 91)
+#define AU1300_BSA_INT         (AU1300_FIRST_INT + 92)
+#define AU1300_MPE_INT         (AU1300_FIRST_INT + 93)
+#define AU1300_ITE_INT         (AU1300_FIRST_INT + 94)
+#define AU1300_AES_INT         (AU1300_FIRST_INT + 95)
+#define AU1300_CIM_INT         (AU1300_FIRST_INT + 96)
 
-#include <asm/cpu.h>
+/**********************************************************************/
 
-/* cpu pipeline flush */
-void static inline au_sync(void)
-{
-       __asm__ volatile ("sync");
-}
+/*
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
+ */
 
-void static inline au_sync_udelay(int us)
-{
-       __asm__ volatile ("sync");
-       udelay(us);
-}
+#define AU1000_AC97_PHYS_ADDR          0x10000000 /* 012 */
+#define AU1300_ROM_PHYS_ADDR           0x10000000 /* 5 */
+#define AU1300_OTP_PHYS_ADDR           0x10002000 /* 5 */
+#define AU1300_VSS_PHYS_ADDR           0x10003000 /* 5 */
+#define AU1300_UART0_PHYS_ADDR         0x10100000 /* 5 */
+#define AU1300_UART1_PHYS_ADDR         0x10101000 /* 5 */
+#define AU1300_UART2_PHYS_ADDR         0x10102000 /* 5 */
+#define AU1300_UART3_PHYS_ADDR         0x10103000 /* 5 */
+#define AU1000_USB_OHCI_PHYS_ADDR      0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR       0x10200000 /* 0123 */
+#define AU1300_GPIC_PHYS_ADDR          0x10200000 /* 5 */
+#define AU1000_IRDA_PHYS_ADDR          0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR           0x10300000 /* 45 */
+#define AU1000_IC0_PHYS_ADDR           0x10400000 /* 01234 */
+#define AU1300_GPU_PHYS_ADDR           0x10500000 /* 5 */
+#define AU1000_MAC0_PHYS_ADDR          0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR          0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR         0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR           0x10600000 /* 245 */
+#define AU1300_SD1_PHYS_ADDR           0x10601000 /* 5 */
+#define AU1300_SD2_PHYS_ADDR           0x10602000 /* 5 */
+#define AU1100_SD1_PHYS_ADDR           0x10680000 /* 24 */
+#define AU1300_SYS_PHYS_ADDR           0x10900000 /* 5 */
+#define AU1550_PSC2_PHYS_ADDR          0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR          0x10B00000 /* 3 */
+#define AU1300_PSC0_PHYS_ADDR          0x10A00000 /* 5 */
+#define AU1300_PSC1_PHYS_ADDR          0x10A01000 /* 5 */
+#define AU1300_PSC2_PHYS_ADDR          0x10A02000 /* 5 */
+#define AU1300_PSC3_PHYS_ADDR          0x10A03000 /* 5 */
+#define AU1000_I2S_PHYS_ADDR           0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR          0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR          0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR         0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR         0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR         0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR         0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR         0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR         0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR          0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR          0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR         0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR           0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR           0x11900000 /* 012345 */
+#define AU1550_PSC0_PHYS_ADDR          0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR          0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR           0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR    0x14001000 /* 01234 */
+#define AU1300_UDMA_PHYS_ADDR          0x14001800 /* 5 */
+#define AU1000_DMA_PHYS_ADDR           0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR         0x14002000 /* 345 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR    0x14003000 /* 345 */
+#define AU1000_MACDMA0_PHYS_ADDR       0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR       0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR           0x14004000 /* 45 */
+#define AU1500_PCI_PHYS_ADDR           0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR            0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR         0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR         0x14012000 /* 4 */
+#define AU1300_MAEITE_PHYS_ADDR                0x14010000 /* 5 */
+#define AU1300_MAEMPE_PHYS_ADDR                0x14014000 /* 5 */
+#define AU1550_USB_OHCI_PHYS_ADDR      0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR       0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR       0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR      0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR      0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR       0x14022000 /* 4 */
+#define AU1300_USB_EHCI_PHYS_ADDR      0x14020000 /* 5 */
+#define AU1300_USB_OHCI0_PHYS_ADDR     0x14020400 /* 5 */
+#define AU1300_USB_OHCI1_PHYS_ADDR     0x14020800 /* 5 */
+#define AU1300_USB_CTL_PHYS_ADDR       0x14021000 /* 5 */
+#define AU1300_USB_OTG_PHYS_ADDR       0x14022000 /* 5 */
+#define AU1300_MAEBSA_PHYS_ADDR                0x14030000 /* 5 */
+#define AU1100_LCD_PHYS_ADDR           0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR           0x15000000 /* 45 */
+#define AU1500_PCI_MEM_PHYS_ADDR       0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR                0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR   0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR   0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR     0xF00000000ULL /* 012345 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR   0xF40000000ULL /* 012345 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR    0xF80000000ULL /* 012345 */
 
-void static inline au_sync_delay(int ms)
-{
-       __asm__ volatile ("sync");
-       mdelay(ms);
-}
+/**********************************************************************/
 
-void static inline au_writeb(u8 val, unsigned long reg)
-{
-       *(volatile u8 *)reg = val;
-}
 
-void static inline au_writew(u16 val, unsigned long reg)
-{
-       *(volatile u16 *)reg = val;
-}
+/*
+ * Au1300 GPIO+INT controller (GPIC) register offsets and bits
+ * Registers are 128bits (0x10 bytes), divided into 4 "banks".
+ */
+#define AU1300_GPIC_PINVAL     0x0000
+#define AU1300_GPIC_PINVALCLR  0x0010
+#define AU1300_GPIC_IPEND      0x0020
+#define AU1300_GPIC_PRIENC     0x0030
+#define AU1300_GPIC_IEN                0x0040  /* int_mask in manual */
+#define AU1300_GPIC_IDIS       0x0050  /* int_maskclr in manual */
+#define AU1300_GPIC_DMASEL     0x0060
+#define AU1300_GPIC_DEVSEL     0x0080
+#define AU1300_GPIC_DEVCLR     0x0090
+#define AU1300_GPIC_RSTVAL     0x00a0
+/* pin configuration space. one 32bit register for up to 128 IRQs */
+#define AU1300_GPIC_PINCFG     0x1000
 
-void static inline au_writel(u32 val, unsigned long reg)
-{
-       *(volatile u32 *)reg = val;
-}
+#define GPIC_GPIO_TO_BIT(gpio) \
+       (1 << ((gpio) & 0x1f))
 
-static inline u8 au_readb(unsigned long reg)
-{
-       return *(volatile u8 *)reg;
-}
+#define GPIC_GPIO_BANKOFF(gpio) \
+       (((gpio) >> 5) * 4)
 
-static inline u16 au_readw(unsigned long reg)
-{
-       return *(volatile u16 *)reg;
-}
+/* Pin Control bits: who owns the pin, what does it do */
+#define GPIC_CFG_PC_GPIN               0
+#define GPIC_CFG_PC_DEV                        1
+#define GPIC_CFG_PC_GPOLOW             2
+#define GPIC_CFG_PC_GPOHIGH            3
+#define GPIC_CFG_PC_MASK               3
 
-static inline u32 au_readl(unsigned long reg)
-{
-       return *(volatile u32 *)reg;
-}
+/* assign pin to MIPS IRQ line */
+#define GPIC_CFG_IL_SET(x)     (((x) & 3) << 2)
+#define GPIC_CFG_IL_MASK       (3 << 2)
 
-/* Early Au1000 have a write-only SYS_CPUPLL register. */
-static inline int au1xxx_cpu_has_pll_wo(void)
-{
-       switch (read_c0_prid()) {
-       case 0x00030100:        /* Au1000 DA */
-       case 0x00030201:        /* Au1000 HA */
-       case 0x00030202:        /* Au1000 HB */
-               return 1;
-       }
-       return 0;
-}
+/* pin interrupt type setup */
+#define GPIC_CFG_IC_OFF                (0 << 4)
+#define GPIC_CFG_IC_LEVEL_LOW  (1 << 4)
+#define GPIC_CFG_IC_LEVEL_HIGH (2 << 4)
+#define GPIC_CFG_IC_EDGE_FALL  (5 << 4)
+#define GPIC_CFG_IC_EDGE_RISE  (6 << 4)
+#define GPIC_CFG_IC_EDGE_BOTH  (7 << 4)
+#define GPIC_CFG_IC_MASK       (7 << 4)
 
-/* does CPU need CONFIG[OD] set to fix tons of errata? */
-static inline int au1xxx_cpu_needs_config_od(void)
-{
-       /*
-        * c0_config.od (bit 19) was write only (and read as 0) on the
-        * early revisions of Alchemy SOCs.  It disables the bus trans-
-        * action overlapping and needs to be set to fix various errata.
-        */
-       switch (read_c0_prid()) {
-       case 0x00030100: /* Au1000 DA */
-       case 0x00030201: /* Au1000 HA */
-       case 0x00030202: /* Au1000 HB */
-       case 0x01030200: /* Au1500 AB */
-       /*
-        * Au1100/Au1200 errata actually keep silence about this bit,
-        * so we set it just in case for those revisions that require
-        * it to be set according to the (now gone) cpu_table.
-        */
-       case 0x02030200: /* Au1100 AB */
-       case 0x02030201: /* Au1100 BA */
-       case 0x02030202: /* Au1100 BC */
-       case 0x04030201: /* Au1200 AC */
-               return 1;
-       }
-       return 0;
-}
+/* allow interrupt to wake cpu from 'wait' */
+#define GPIC_CFG_IDLEWAKE      (1 << 7)
 
-#define ALCHEMY_CPU_UNKNOWN    -1
-#define ALCHEMY_CPU_AU1000     0
-#define ALCHEMY_CPU_AU1500     1
-#define ALCHEMY_CPU_AU1100     2
-#define ALCHEMY_CPU_AU1550     3
-#define ALCHEMY_CPU_AU1200     4
-#define ALCHEMY_CPU_AU1300     5
+/***********************************************************************/
 
-static inline int alchemy_get_cputype(void)
-{
-       switch (read_c0_prid() & (PRID_OPT_MASK | PRID_COMP_MASK)) {
-       case 0x00030000:
-               return ALCHEMY_CPU_AU1000;
-               break;
-       case 0x01030000:
-               return ALCHEMY_CPU_AU1500;
-               break;
-       case 0x02030000:
-               return ALCHEMY_CPU_AU1100;
-               break;
-       case 0x03030000:
-               return ALCHEMY_CPU_AU1550;
-               break;
-       case 0x04030000:
-       case 0x05030000:
-               return ALCHEMY_CPU_AU1200;
-               break;
-       case 0x800c0000:
-               return ALCHEMY_CPU_AU1300;
-               break;
-       }
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0             0x0000
+#define AU1000_MEM_SDMODE1             0x0004
+#define AU1000_MEM_SDMODE2             0x0008
+#define AU1000_MEM_SDADDR0             0x000C
+#define AU1000_MEM_SDADDR1             0x0010
+#define AU1000_MEM_SDADDR2             0x0014
+#define AU1000_MEM_SDREFCFG            0x0018
+#define AU1000_MEM_SDPRECMD            0x001C
+#define AU1000_MEM_SDAUTOREF           0x0020
+#define AU1000_MEM_SDWRMD0             0x0024
+#define AU1000_MEM_SDWRMD1             0x0028
+#define AU1000_MEM_SDWRMD2             0x002C
+#define AU1000_MEM_SDSLEEP             0x0030
+#define AU1000_MEM_SDSMCKE             0x0034
 
-       return ALCHEMY_CPU_UNKNOWN;
-}
+/* MEM_SDMODE register content definitions */
+#define MEM_SDMODE_F           (1 << 22)
+#define MEM_SDMODE_SR          (1 << 21)
+#define MEM_SDMODE_BS          (1 << 20)
+#define MEM_SDMODE_RS          (3 << 18)
+#define MEM_SDMODE_CS          (7 << 15)
+#define MEM_SDMODE_TRAS                (15 << 11)
+#define MEM_SDMODE_TMRD                (3 << 9)
+#define MEM_SDMODE_TWR         (3 << 7)
+#define MEM_SDMODE_TRP         (3 << 5)
+#define MEM_SDMODE_TRCD                (3 << 3)
+#define MEM_SDMODE_TCL         (7 << 0)
 
-/* return number of uarts on a given cputype */
-static inline int alchemy_get_uarts(int type)
-{
-       switch (type) {
-       case ALCHEMY_CPU_AU1000:
-       case ALCHEMY_CPU_AU1300:
-               return 4;
-       case ALCHEMY_CPU_AU1500:
-       case ALCHEMY_CPU_AU1200:
-               return 2;
-       case ALCHEMY_CPU_AU1100:
-       case ALCHEMY_CPU_AU1550:
-               return 3;
-       }
-       return 0;
-}
+#define MEM_SDMODE_BS_2Bank    (0 << 20)
+#define MEM_SDMODE_BS_4Bank    (1 << 20)
+#define MEM_SDMODE_RS_11Row    (0 << 18)
+#define MEM_SDMODE_RS_12Row    (1 << 18)
+#define MEM_SDMODE_RS_13Row    (2 << 18)
+#define MEM_SDMODE_RS_N(N)     ((N) << 18)
+#define MEM_SDMODE_CS_7Col     (0 << 15)
+#define MEM_SDMODE_CS_8Col     (1 << 15)
+#define MEM_SDMODE_CS_9Col     (2 << 15)
+#define MEM_SDMODE_CS_10Col    (3 << 15)
+#define MEM_SDMODE_CS_11Col    (4 << 15)
+#define MEM_SDMODE_CS_N(N)     ((N) << 15)
+#define MEM_SDMODE_TRAS_N(N)   ((N) << 11)
+#define MEM_SDMODE_TMRD_N(N)   ((N) << 9)
+#define MEM_SDMODE_TWR_N(N)    ((N) << 7)
+#define MEM_SDMODE_TRP_N(N)    ((N) << 5)
+#define MEM_SDMODE_TRCD_N(N)   ((N) << 3)
+#define MEM_SDMODE_TCL_N(N)    ((N) << 0)
 
-/* enable an UART block if it isn't already */
-static inline void alchemy_uart_enable(u32 uart_phys)
-{
-       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+/* MEM_SDADDR register contents definitions */
+#define MEM_SDADDR_E           (1 << 20)
+#define MEM_SDADDR_CSBA                (0x03FF << 10)
+#define MEM_SDADDR_CSMASK      (0x03FF << 0)
+#define MEM_SDADDR_CSBA_N(N)   ((N) & (0x03FF << 22) >> 12)
+#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF << 22) >> 22)
 
-       /* reset, enable clock, deassert reset */
-       if ((__raw_readl(addr + 0x100) & 3) != 3) {
-               __raw_writel(0, addr + 0x100);
-               wmb();
-               __raw_writel(1, addr + 0x100);
-               wmb();
-       }
-       __raw_writel(3, addr + 0x100);
-       wmb();
-}
+/* MEM_SDREFCFG register content definitions */
+#define MEM_SDREFCFG_TRC       (15 << 28)
+#define MEM_SDREFCFG_TRPM      (3 << 26)
+#define MEM_SDREFCFG_E         (1 << 25)
+#define MEM_SDREFCFG_RE                (0x1ffffff << 0)
+#define MEM_SDREFCFG_TRC_N(N)  ((N) << MEM_SDREFCFG_TRC)
+#define MEM_SDREFCFG_TRPM_N(N) ((N) << MEM_SDREFCFG_TRPM)
+#define MEM_SDREFCFG_REF_N(N)  (N)
 
-static inline void alchemy_uart_disable(u32 uart_phys)
-{
-       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
-       __raw_writel(0, addr + 0x100);  /* UART_MOD_CNTRL */
-       wmb();
-}
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0             0x0800
+#define AU1550_MEM_SDMODE1             0x0808
+#define AU1550_MEM_SDMODE2             0x0810
+#define AU1550_MEM_SDADDR0             0x0820
+#define AU1550_MEM_SDADDR1             0x0828
+#define AU1550_MEM_SDADDR2             0x0830
+#define AU1550_MEM_SDCONFIGA           0x0840
+#define AU1550_MEM_SDCONFIGB           0x0848
+#define AU1550_MEM_SDSTAT              0x0850
+#define AU1550_MEM_SDERRADDR           0x0858
+#define AU1550_MEM_SDSTRIDE0           0x0860
+#define AU1550_MEM_SDSTRIDE1           0x0868
+#define AU1550_MEM_SDSTRIDE2           0x0870
+#define AU1550_MEM_SDWRMD0             0x0880
+#define AU1550_MEM_SDWRMD1             0x0888
+#define AU1550_MEM_SDWRMD2             0x0890
+#define AU1550_MEM_SDPRECMD            0x08C0
+#define AU1550_MEM_SDAUTOREF           0x08C8
+#define AU1550_MEM_SDSREF              0x08D0
+#define AU1550_MEM_SDSLEEP             MEM_SDSREF
 
-static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
-{
-       void __iomem *base = (void __iomem *)KSEG1ADDR(uart_phys);
-       int timeout, i;
+/* Static Bus Controller register offsets */
+#define AU1000_MEM_STCFG0      0x000
+#define AU1000_MEM_STTIME0     0x004
+#define AU1000_MEM_STADDR0     0x008
+#define AU1000_MEM_STCFG1      0x010
+#define AU1000_MEM_STTIME1     0x014
+#define AU1000_MEM_STADDR1     0x018
+#define AU1000_MEM_STCFG2      0x020
+#define AU1000_MEM_STTIME2     0x024
+#define AU1000_MEM_STADDR2     0x028
+#define AU1000_MEM_STCFG3      0x030
+#define AU1000_MEM_STTIME3     0x034
+#define AU1000_MEM_STADDR3     0x038
+#define AU1000_MEM_STNDCTL     0x100
+#define AU1000_MEM_STSTAT      0x104
 
-       /* check LSR TX_EMPTY bit */
-       timeout = 0xffffff;
-       do {
-               if (__raw_readl(base + 0x1c) & 0x20)
-                       break;
-               /* slow down */
-               for (i = 10000; i; i--)
-                       asm volatile ("nop");
-       } while (--timeout);
+#define MEM_STNAND_CMD         0x0
+#define MEM_STNAND_ADDR                0x4
+#define MEM_STNAND_DATA                0x20
 
-       __raw_writel(c, base + 0x04);   /* tx */
-       wmb();
-}
 
-/* return number of ethernet MACs on a given cputype */
-static inline int alchemy_get_macs(int type)
-{
-       switch (type) {
-       case ALCHEMY_CPU_AU1000:
-       case ALCHEMY_CPU_AU1500:
-       case ALCHEMY_CPU_AU1550:
-               return 2;
-       case ALCHEMY_CPU_AU1100:
-               return 1;
-       }
-       return 0;
-}
+/* Programmable Counters 0 and 1 */
+#define AU1000_SYS_CNTRCTRL    0x14
+#  define SYS_CNTRL_E1S                (1 << 23)
+#  define SYS_CNTRL_T1S                (1 << 20)
+#  define SYS_CNTRL_M21                (1 << 19)
+#  define SYS_CNTRL_M11                (1 << 18)
+#  define SYS_CNTRL_M01                (1 << 17)
+#  define SYS_CNTRL_C1S                (1 << 16)
+#  define SYS_CNTRL_BP         (1 << 14)
+#  define SYS_CNTRL_EN1                (1 << 13)
+#  define SYS_CNTRL_BT1                (1 << 12)
+#  define SYS_CNTRL_EN0                (1 << 11)
+#  define SYS_CNTRL_BT0                (1 << 10)
+#  define SYS_CNTRL_E0         (1 << 8)
+#  define SYS_CNTRL_E0S                (1 << 7)
+#  define SYS_CNTRL_32S                (1 << 5)
+#  define SYS_CNTRL_T0S                (1 << 4)
+#  define SYS_CNTRL_M20                (1 << 3)
+#  define SYS_CNTRL_M10                (1 << 2)
+#  define SYS_CNTRL_M00                (1 << 1)
+#  define SYS_CNTRL_C0S                (1 << 0)
 
-/* arch/mips/au1000/common/clocks.c */
-extern void set_au1x00_speed(unsigned int new_freq);
-extern unsigned int get_au1x00_speed(void);
-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
-extern unsigned long get_au1x00_uart_baud_base(void);
-extern unsigned long au1xxx_calc_clock(void);
+/* Programmable Counter 0 Registers */
+#define AU1000_SYS_TOYTRIM     0x00
+#define AU1000_SYS_TOYWRITE    0x04
+#define AU1000_SYS_TOYMATCH0   0x08
+#define AU1000_SYS_TOYMATCH1   0x0c
+#define AU1000_SYS_TOYMATCH2   0x10
+#define AU1000_SYS_TOYREAD     0x40
 
-/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
-void alchemy_sleep_au1000(void);
-void alchemy_sleep_au1550(void);
-void alchemy_sleep_au1300(void);
-void au_sleep(void);
+/* Programmable Counter 1 Registers */
+#define AU1000_SYS_RTCTRIM     0x44
+#define AU1000_SYS_RTCWRITE    0x48
+#define AU1000_SYS_RTCMATCH0   0x4c
+#define AU1000_SYS_RTCMATCH1   0x50
+#define AU1000_SYS_RTCMATCH2   0x54
+#define AU1000_SYS_RTCREAD     0x58
 
-/* USB: drivers/usb/host/alchemy-common.c */
-enum alchemy_usb_block {
-       ALCHEMY_USB_OHCI0,
-       ALCHEMY_USB_UDC0,
-       ALCHEMY_USB_EHCI0,
-       ALCHEMY_USB_OTG0,
-       ALCHEMY_USB_OHCI1,
-};
-int alchemy_usb_control(int block, int enable);
 
-/* PCI controller platform data */
-struct alchemy_pci_platdata {
-       int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
-       int (*board_pci_idsel)(unsigned int devsel, int assert);
-       /* bits to set/clear in PCI_CONFIG register */
-       unsigned long pci_cfg_set;
-       unsigned long pci_cfg_clr;
-};
+/* GPIO */
+#define AU1000_SYS_PINFUNC     0x2C
+#  define SYS_PF_USB           (1 << 15)       /* 2nd USB device/host */
+#  define SYS_PF_U3            (1 << 14)       /* GPIO23/U3TXD */
+#  define SYS_PF_U2            (1 << 13)       /* GPIO22/U2TXD */
+#  define SYS_PF_U1            (1 << 12)       /* GPIO21/U1TXD */
+#  define SYS_PF_SRC           (1 << 11)       /* GPIO6/SROMCKE */
+#  define SYS_PF_CK5           (1 << 10)       /* GPIO3/CLK5 */
+#  define SYS_PF_CK4           (1 << 9)        /* GPIO2/CLK4 */
+#  define SYS_PF_IRF           (1 << 8)        /* GPIO15/IRFIRSEL */
+#  define SYS_PF_UR3           (1 << 7)        /* GPIO[14:9]/UART3 */
+#  define SYS_PF_I2D           (1 << 6)        /* GPIO8/I2SDI */
+#  define SYS_PF_I2S           (1 << 5)        /* I2S/GPIO[29:31] */
+#  define SYS_PF_NI2           (1 << 4)        /* NI2/GPIO[24:28] */
+#  define SYS_PF_U0            (1 << 3)        /* U0TXD/GPIO20 */
+#  define SYS_PF_RD            (1 << 2)        /* IRTXD/GPIO19 */
+#  define SYS_PF_A97           (1 << 1)        /* AC97/SSL1 */
+#  define SYS_PF_S0            (1 << 0)        /* SSI_0/GPIO[16:18] */
 
-/* Multifunction pins: Each of these pins can either be assigned to the
- * GPIO controller or a on-chip peripheral.
- * Call "au1300_pinfunc_to_dev()" or "au1300_pinfunc_to_gpio()" to
- * assign one of these to either the GPIO controller or the device.
- */
-enum au1300_multifunc_pins {
-       /* wake-from-str pins 0-3 */
-       AU1300_PIN_WAKE0 = 0, AU1300_PIN_WAKE1, AU1300_PIN_WAKE2,
-       AU1300_PIN_WAKE3,
-       /* external clock sources for PSCs: 4-5 */
-       AU1300_PIN_EXTCLK0, AU1300_PIN_EXTCLK1,
-       /* 8bit MMC interface on SD0: 6-9 */
-       AU1300_PIN_SD0DAT4, AU1300_PIN_SD0DAT5, AU1300_PIN_SD0DAT6,
-       AU1300_PIN_SD0DAT7,
-       /* aux clk input for freqgen 3: 10 */
-       AU1300_PIN_FG3AUX,
-       /* UART1 pins: 11-18 */
-       AU1300_PIN_U1RI, AU1300_PIN_U1DCD, AU1300_PIN_U1DSR,
-       AU1300_PIN_U1CTS, AU1300_PIN_U1RTS, AU1300_PIN_U1DTR,
-       AU1300_PIN_U1RX, AU1300_PIN_U1TX,
-       /* UART0 pins: 19-24 */
-       AU1300_PIN_U0RI, AU1300_PIN_U0DCD, AU1300_PIN_U0DSR,
-       AU1300_PIN_U0CTS, AU1300_PIN_U0RTS, AU1300_PIN_U0DTR,
-       /* UART2: 25-26 */
-       AU1300_PIN_U2RX, AU1300_PIN_U2TX,
-       /* UART3: 27-28 */
-       AU1300_PIN_U3RX, AU1300_PIN_U3TX,
-       /* LCD controller PWMs, ext pixclock: 29-31 */
-       AU1300_PIN_LCDPWM0, AU1300_PIN_LCDPWM1, AU1300_PIN_LCDCLKIN,
-       /* SD1 interface: 32-37 */
-       AU1300_PIN_SD1DAT0, AU1300_PIN_SD1DAT1, AU1300_PIN_SD1DAT2,
-       AU1300_PIN_SD1DAT3, AU1300_PIN_SD1CMD, AU1300_PIN_SD1CLK,
-       /* SD2 interface: 38-43 */
-       AU1300_PIN_SD2DAT0, AU1300_PIN_SD2DAT1, AU1300_PIN_SD2DAT2,
-       AU1300_PIN_SD2DAT3, AU1300_PIN_SD2CMD, AU1300_PIN_SD2CLK,
-       /* PSC0/1 clocks: 44-45 */
-       AU1300_PIN_PSC0CLK, AU1300_PIN_PSC1CLK,
-       /* PSCs: 46-49/50-53/54-57/58-61 */
-       AU1300_PIN_PSC0SYNC0, AU1300_PIN_PSC0SYNC1, AU1300_PIN_PSC0D0,
-       AU1300_PIN_PSC0D1,
-       AU1300_PIN_PSC1SYNC0, AU1300_PIN_PSC1SYNC1, AU1300_PIN_PSC1D0,
-       AU1300_PIN_PSC1D1,
-       AU1300_PIN_PSC2SYNC0, AU1300_PIN_PSC2SYNC1, AU1300_PIN_PSC2D0,
-       AU1300_PIN_PSC2D1,
-       AU1300_PIN_PSC3SYNC0, AU1300_PIN_PSC3SYNC1, AU1300_PIN_PSC3D0,
-       AU1300_PIN_PSC3D1,
-       /* PCMCIA interface: 62-70 */
-       AU1300_PIN_PCE2, AU1300_PIN_PCE1, AU1300_PIN_PIOS16,
-       AU1300_PIN_PIOR, AU1300_PIN_PWE, AU1300_PIN_PWAIT,
-       AU1300_PIN_PREG, AU1300_PIN_POE, AU1300_PIN_PIOW,
-       /* camera interface H/V sync inputs: 71-72 */
-       AU1300_PIN_CIMLS, AU1300_PIN_CIMFS,
-       /* PSC2/3 clocks: 73-74 */
-       AU1300_PIN_PSC2CLK, AU1300_PIN_PSC3CLK,
-};
+/* Au1100 only */
+#  define SYS_PF_PC            (1 << 18)       /* PCMCIA/GPIO[207:204] */
+#  define SYS_PF_LCD           (1 << 17)       /* extern lcd/GPIO[203:200] */
+#  define SYS_PF_CS            (1 << 16)       /* EXTCLK0/32KHz to gpio2 */
+#  define SYS_PF_EX0           (1 << 9)        /* GPIO2/clock */
 
-/* GPIC (Au1300) pin management: arch/mips/alchemy/common/gpioint.c */
-extern void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio);
-extern void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio);
-extern void au1300_set_irq_priority(unsigned int irq, int p);
-extern void au1300_set_dbdma_gpio(int dchan, unsigned int gpio);
+/* Au1550 only.         Redefines lots of pins */
+#  define SYS_PF_PSC2_MASK     (7 << 17)
+#  define SYS_PF_PSC2_AC97     0
+#  define SYS_PF_PSC2_SPI      0
+#  define SYS_PF_PSC2_I2S      (1 << 17)
+#  define SYS_PF_PSC2_SMBUS    (3 << 17)
+#  define SYS_PF_PSC2_GPIO     (7 << 17)
+#  define SYS_PF_PSC3_MASK     (7 << 20)
+#  define SYS_PF_PSC3_AC97     0
+#  define SYS_PF_PSC3_SPI      0
+#  define SYS_PF_PSC3_I2S      (1 << 20)
+#  define SYS_PF_PSC3_SMBUS    (3 << 20)
+#  define SYS_PF_PSC3_GPIO     (7 << 20)
+#  define SYS_PF_PSC1_S1       (1 << 1)
+#  define SYS_PF_MUST_BE_SET   ((1 << 5) | (1 << 2))
 
-/* Au1300 allows to disconnect certain blocks from internal power supply */
-enum au1300_vss_block {
-       AU1300_VSS_MPE = 0,
-       AU1300_VSS_BSA,
-       AU1300_VSS_GPE,
-       AU1300_VSS_MGP,
-};
+/* Au1200 only */
+#define SYS_PINFUNC_DMA                (1 << 31)
+#define SYS_PINFUNC_S0A                (1 << 30)
+#define SYS_PINFUNC_S1A                (1 << 29)
+#define SYS_PINFUNC_LP0                (1 << 28)
+#define SYS_PINFUNC_LP1                (1 << 27)
+#define SYS_PINFUNC_LD16       (1 << 26)
+#define SYS_PINFUNC_LD8                (1 << 25)
+#define SYS_PINFUNC_LD1                (1 << 24)
+#define SYS_PINFUNC_LD0                (1 << 23)
+#define SYS_PINFUNC_P1A                (3 << 21)
+#define SYS_PINFUNC_P1B                (1 << 20)
+#define SYS_PINFUNC_FS3                (1 << 19)
+#define SYS_PINFUNC_P0A                (3 << 17)
+#define SYS_PINFUNC_CS         (1 << 16)
+#define SYS_PINFUNC_CIM                (1 << 15)
+#define SYS_PINFUNC_P1C                (1 << 14)
+#define SYS_PINFUNC_U1T                (1 << 12)
+#define SYS_PINFUNC_U1R                (1 << 11)
+#define SYS_PINFUNC_EX1                (1 << 10)
+#define SYS_PINFUNC_EX0                (1 << 9)
+#define SYS_PINFUNC_U0R                (1 << 8)
+#define SYS_PINFUNC_MC         (1 << 7)
+#define SYS_PINFUNC_S0B                (1 << 6)
+#define SYS_PINFUNC_S0C                (1 << 5)
+#define SYS_PINFUNC_P0B                (1 << 4)
+#define SYS_PINFUNC_U0T                (1 << 3)
+#define SYS_PINFUNC_S1B                (1 << 2)
 
-extern void au1300_vss_block_control(int block, int enable);
+/* Power Management */
+#define AU1000_SYS_SCRATCH0    0x18
+#define AU1000_SYS_SCRATCH1    0x1c
+#define AU1000_SYS_WAKEMSK     0x34
+#define AU1000_SYS_ENDIAN      0x38
+#define AU1000_SYS_POWERCTRL   0x3c
+#define AU1000_SYS_WAKESRC     0x5c
+#define AU1000_SYS_SLPPWR      0x78
+#define AU1000_SYS_SLEEP       0x7c
 
+#define SYS_WAKEMSK_D2         (1 << 9)
+#define SYS_WAKEMSK_M2         (1 << 8)
+#define SYS_WAKEMSK_GPIO(x)    (1 << (x))
 
-/* SOC Interrupt numbers */
-/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
-#define AU1000_INTC0_INT_BASE  (MIPS_CPU_IRQ_BASE + 8)
-#define AU1000_INTC0_INT_LAST  (AU1000_INTC0_INT_BASE + 31)
-#define AU1000_INTC1_INT_BASE  (AU1000_INTC0_INT_LAST + 1)
-#define AU1000_INTC1_INT_LAST  (AU1000_INTC1_INT_BASE + 31)
-#define AU1000_MAX_INTR                AU1000_INTC1_INT_LAST
+/* Clock Controller */
+#define AU1000_SYS_FREQCTRL0   0x20
+#define AU1000_SYS_FREQCTRL1   0x24
+#define AU1000_SYS_CLKSRC      0x28
+#define AU1000_SYS_CPUPLL      0x60
+#define AU1000_SYS_AUXPLL      0x64
+#define AU1300_SYS_AUXPLL2     0x68
 
-/* Au1300-style (GPIC): 1 controller with up to 128 sources */
-#define ALCHEMY_GPIC_INT_BASE  (MIPS_CPU_IRQ_BASE + 8)
-#define ALCHEMY_GPIC_INT_NUM   128
-#define ALCHEMY_GPIC_INT_LAST  (ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
 
-enum soc_au1000_ints {
-       AU1000_FIRST_INT        = AU1000_INTC0_INT_BASE,
-       AU1000_UART0_INT        = AU1000_FIRST_INT,
-       AU1000_UART1_INT,
-       AU1000_UART2_INT,
-       AU1000_UART3_INT,
-       AU1000_SSI0_INT,
-       AU1000_SSI1_INT,
-       AU1000_DMA_INT_BASE,
+/**********************************************************************/
 
-       AU1000_TOY_INT          = AU1000_FIRST_INT + 14,
-       AU1000_TOY_MATCH0_INT,
-       AU1000_TOY_MATCH1_INT,
-       AU1000_TOY_MATCH2_INT,
-       AU1000_RTC_INT,
-       AU1000_RTC_MATCH0_INT,
-       AU1000_RTC_MATCH1_INT,
-       AU1000_RTC_MATCH2_INT,
-       AU1000_IRDA_TX_INT,
-       AU1000_IRDA_RX_INT,
-       AU1000_USB_DEV_REQ_INT,
-       AU1000_USB_DEV_SUS_INT,
-       AU1000_USB_HOST_INT,
-       AU1000_ACSYNC_INT,
-       AU1000_MAC0_DMA_INT,
-       AU1000_MAC1_DMA_INT,
-       AU1000_I2S_UO_INT,
-       AU1000_AC97C_INT,
-       AU1000_GPIO0_INT,
-       AU1000_GPIO1_INT,
-       AU1000_GPIO2_INT,
-       AU1000_GPIO3_INT,
-       AU1000_GPIO4_INT,
-       AU1000_GPIO5_INT,
-       AU1000_GPIO6_INT,
-       AU1000_GPIO7_INT,
-       AU1000_GPIO8_INT,
-       AU1000_GPIO9_INT,
-       AU1000_GPIO10_INT,
-       AU1000_GPIO11_INT,
-       AU1000_GPIO12_INT,
-       AU1000_GPIO13_INT,
-       AU1000_GPIO14_INT,
-       AU1000_GPIO15_INT,
-       AU1000_GPIO16_INT,
-       AU1000_GPIO17_INT,
-       AU1000_GPIO18_INT,
-       AU1000_GPIO19_INT,
-       AU1000_GPIO20_INT,
-       AU1000_GPIO21_INT,
-       AU1000_GPIO22_INT,
-       AU1000_GPIO23_INT,
-       AU1000_GPIO24_INT,
-       AU1000_GPIO25_INT,
-       AU1000_GPIO26_INT,
-       AU1000_GPIO27_INT,
-       AU1000_GPIO28_INT,
-       AU1000_GPIO29_INT,
-       AU1000_GPIO30_INT,
-       AU1000_GPIO31_INT,
-};
 
-enum soc_au1100_ints {
-       AU1100_FIRST_INT        = AU1000_INTC0_INT_BASE,
-       AU1100_UART0_INT        = AU1100_FIRST_INT,
-       AU1100_UART1_INT,
-       AU1100_SD_INT,
-       AU1100_UART3_INT,
-       AU1100_SSI0_INT,
-       AU1100_SSI1_INT,
-       AU1100_DMA_INT_BASE,
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI.  When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
+ */
+#define ALCHEMY_PCI_MEMWIN_START       (AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END         (ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
 
-       AU1100_TOY_INT          = AU1100_FIRST_INT + 14,
-       AU1100_TOY_MATCH0_INT,
-       AU1100_TOY_MATCH1_INT,
-       AU1100_TOY_MATCH2_INT,
-       AU1100_RTC_INT,
-       AU1100_RTC_MATCH0_INT,
-       AU1100_RTC_MATCH1_INT,
-       AU1100_RTC_MATCH2_INT,
-       AU1100_IRDA_TX_INT,
-       AU1100_IRDA_RX_INT,
-       AU1100_USB_DEV_REQ_INT,
-       AU1100_USB_DEV_SUS_INT,
-       AU1100_USB_HOST_INT,
-       AU1100_ACSYNC_INT,
-       AU1100_MAC0_DMA_INT,
-       AU1100_GPIO208_215_INT,
-       AU1100_LCD_INT,
-       AU1100_AC97C_INT,
-       AU1100_GPIO0_INT,
-       AU1100_GPIO1_INT,
-       AU1100_GPIO2_INT,
-       AU1100_GPIO3_INT,
-       AU1100_GPIO4_INT,
-       AU1100_GPIO5_INT,
-       AU1100_GPIO6_INT,
-       AU1100_GPIO7_INT,
-       AU1100_GPIO8_INT,
-       AU1100_GPIO9_INT,
-       AU1100_GPIO10_INT,
-       AU1100_GPIO11_INT,
-       AU1100_GPIO12_INT,
-       AU1100_GPIO13_INT,
-       AU1100_GPIO14_INT,
-       AU1100_GPIO15_INT,
-       AU1100_GPIO16_INT,
-       AU1100_GPIO17_INT,
-       AU1100_GPIO18_INT,
-       AU1100_GPIO19_INT,
-       AU1100_GPIO20_INT,
-       AU1100_GPIO21_INT,
-       AU1100_GPIO22_INT,
-       AU1100_GPIO23_INT,
-       AU1100_GPIO24_INT,
-       AU1100_GPIO25_INT,
-       AU1100_GPIO26_INT,
-       AU1100_GPIO27_INT,
-       AU1100_GPIO28_INT,
-       AU1100_GPIO29_INT,
-       AU1100_GPIO30_INT,
-       AU1100_GPIO31_INT,
-};
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START                0x00001000
+#define ALCHEMY_PCI_IOWIN_END          0x0000FFFF
 
-enum soc_au1500_ints {
-       AU1500_FIRST_INT        = AU1000_INTC0_INT_BASE,
-       AU1500_UART0_INT        = AU1500_FIRST_INT,
-       AU1500_PCI_INTA,
-       AU1500_PCI_INTB,
-       AU1500_UART3_INT,
-       AU1500_PCI_INTC,
-       AU1500_PCI_INTD,
-       AU1500_DMA_INT_BASE,
+#ifdef CONFIG_PCI
 
-       AU1500_TOY_INT          = AU1500_FIRST_INT + 14,
-       AU1500_TOY_MATCH0_INT,
-       AU1500_TOY_MATCH1_INT,
-       AU1500_TOY_MATCH2_INT,
-       AU1500_RTC_INT,
-       AU1500_RTC_MATCH0_INT,
-       AU1500_RTC_MATCH1_INT,
-       AU1500_RTC_MATCH2_INT,
-       AU1500_PCI_ERR_INT,
-       AU1500_RESERVED_INT,
-       AU1500_USB_DEV_REQ_INT,
-       AU1500_USB_DEV_SUS_INT,
-       AU1500_USB_HOST_INT,
-       AU1500_ACSYNC_INT,
-       AU1500_MAC0_DMA_INT,
-       AU1500_MAC1_DMA_INT,
-       AU1500_AC97C_INT        = AU1500_FIRST_INT + 31,
-       AU1500_GPIO0_INT,
-       AU1500_GPIO1_INT,
-       AU1500_GPIO2_INT,
-       AU1500_GPIO3_INT,
-       AU1500_GPIO4_INT,
-       AU1500_GPIO5_INT,
-       AU1500_GPIO6_INT,
-       AU1500_GPIO7_INT,
-       AU1500_GPIO8_INT,
-       AU1500_GPIO9_INT,
-       AU1500_GPIO10_INT,
-       AU1500_GPIO11_INT,
-       AU1500_GPIO12_INT,
-       AU1500_GPIO13_INT,
-       AU1500_GPIO14_INT,
-       AU1500_GPIO15_INT,
-       AU1500_GPIO200_INT,
-       AU1500_GPIO201_INT,
-       AU1500_GPIO202_INT,
-       AU1500_GPIO203_INT,
-       AU1500_GPIO20_INT,
-       AU1500_GPIO204_INT,
-       AU1500_GPIO205_INT,
-       AU1500_GPIO23_INT,
-       AU1500_GPIO24_INT,
-       AU1500_GPIO25_INT,
-       AU1500_GPIO26_INT,
-       AU1500_GPIO27_INT,
-       AU1500_GPIO28_INT,
-       AU1500_GPIO206_INT,
-       AU1500_GPIO207_INT,
-       AU1500_GPIO208_215_INT,
-};
-
-enum soc_au1550_ints {
-       AU1550_FIRST_INT        = AU1000_INTC0_INT_BASE,
-       AU1550_UART0_INT        = AU1550_FIRST_INT,
-       AU1550_PCI_INTA,
-       AU1550_PCI_INTB,
-       AU1550_DDMA_INT,
-       AU1550_CRYPTO_INT,
-       AU1550_PCI_INTC,
-       AU1550_PCI_INTD,
-       AU1550_PCI_RST_INT,
-       AU1550_UART1_INT,
-       AU1550_UART3_INT,
-       AU1550_PSC0_INT,
-       AU1550_PSC1_INT,
-       AU1550_PSC2_INT,
-       AU1550_PSC3_INT,
-       AU1550_TOY_INT,
-       AU1550_TOY_MATCH0_INT,
-       AU1550_TOY_MATCH1_INT,
-       AU1550_TOY_MATCH2_INT,
-       AU1550_RTC_INT,
-       AU1550_RTC_MATCH0_INT,
-       AU1550_RTC_MATCH1_INT,
-       AU1550_RTC_MATCH2_INT,
-
-       AU1550_NAND_INT         = AU1550_FIRST_INT + 23,
-       AU1550_USB_DEV_REQ_INT,
-       AU1550_USB_DEV_SUS_INT,
-       AU1550_USB_HOST_INT,
-       AU1550_MAC0_DMA_INT,
-       AU1550_MAC1_DMA_INT,
-       AU1550_GPIO0_INT        = AU1550_FIRST_INT + 32,
-       AU1550_GPIO1_INT,
-       AU1550_GPIO2_INT,
-       AU1550_GPIO3_INT,
-       AU1550_GPIO4_INT,
-       AU1550_GPIO5_INT,
-       AU1550_GPIO6_INT,
-       AU1550_GPIO7_INT,
-       AU1550_GPIO8_INT,
-       AU1550_GPIO9_INT,
-       AU1550_GPIO10_INT,
-       AU1550_GPIO11_INT,
-       AU1550_GPIO12_INT,
-       AU1550_GPIO13_INT,
-       AU1550_GPIO14_INT,
-       AU1550_GPIO15_INT,
-       AU1550_GPIO200_INT,
-       AU1550_GPIO201_205_INT, /* Logical or of GPIO201:205 */
-       AU1550_GPIO16_INT,
-       AU1550_GPIO17_INT,
-       AU1550_GPIO20_INT,
-       AU1550_GPIO21_INT,
-       AU1550_GPIO22_INT,
-       AU1550_GPIO23_INT,
-       AU1550_GPIO24_INT,
-       AU1550_GPIO25_INT,
-       AU1550_GPIO26_INT,
-       AU1550_GPIO27_INT,
-       AU1550_GPIO28_INT,
-       AU1550_GPIO206_INT,
-       AU1550_GPIO207_INT,
-       AU1550_GPIO208_215_INT, /* Logical or of GPIO208:215 */
-};
-
-enum soc_au1200_ints {
-       AU1200_FIRST_INT        = AU1000_INTC0_INT_BASE,
-       AU1200_UART0_INT        = AU1200_FIRST_INT,
-       AU1200_SWT_INT,
-       AU1200_SD_INT,
-       AU1200_DDMA_INT,
-       AU1200_MAE_BE_INT,
-       AU1200_GPIO200_INT,
-       AU1200_GPIO201_INT,
-       AU1200_GPIO202_INT,
-       AU1200_UART1_INT,
-       AU1200_MAE_FE_INT,
-       AU1200_PSC0_INT,
-       AU1200_PSC1_INT,
-       AU1200_AES_INT,
-       AU1200_CAMERA_INT,
-       AU1200_TOY_INT,
-       AU1200_TOY_MATCH0_INT,
-       AU1200_TOY_MATCH1_INT,
-       AU1200_TOY_MATCH2_INT,
-       AU1200_RTC_INT,
-       AU1200_RTC_MATCH0_INT,
-       AU1200_RTC_MATCH1_INT,
-       AU1200_RTC_MATCH2_INT,
-       AU1200_GPIO203_INT,
-       AU1200_NAND_INT,
-       AU1200_GPIO204_INT,
-       AU1200_GPIO205_INT,
-       AU1200_GPIO206_INT,
-       AU1200_GPIO207_INT,
-       AU1200_GPIO208_215_INT, /* Logical OR of 208:215 */
-       AU1200_USB_INT,
-       AU1200_LCD_INT,
-       AU1200_MAE_BOTH_INT,
-       AU1200_GPIO0_INT,
-       AU1200_GPIO1_INT,
-       AU1200_GPIO2_INT,
-       AU1200_GPIO3_INT,
-       AU1200_GPIO4_INT,
-       AU1200_GPIO5_INT,
-       AU1200_GPIO6_INT,
-       AU1200_GPIO7_INT,
-       AU1200_GPIO8_INT,
-       AU1200_GPIO9_INT,
-       AU1200_GPIO10_INT,
-       AU1200_GPIO11_INT,
-       AU1200_GPIO12_INT,
-       AU1200_GPIO13_INT,
-       AU1200_GPIO14_INT,
-       AU1200_GPIO15_INT,
-       AU1200_GPIO16_INT,
-       AU1200_GPIO17_INT,
-       AU1200_GPIO18_INT,
-       AU1200_GPIO19_INT,
-       AU1200_GPIO20_INT,
-       AU1200_GPIO21_INT,
-       AU1200_GPIO22_INT,
-       AU1200_GPIO23_INT,
-       AU1200_GPIO24_INT,
-       AU1200_GPIO25_INT,
-       AU1200_GPIO26_INT,
-       AU1200_GPIO27_INT,
-       AU1200_GPIO28_INT,
-       AU1200_GPIO29_INT,
-       AU1200_GPIO30_INT,
-       AU1200_GPIO31_INT,
-};
+#define IOPORT_RESOURCE_START  0x00001000      /* skip legacy probing */
+#define IOPORT_RESOURCE_END    0xffffffff
+#define IOMEM_RESOURCE_START   0x10000000
+#define IOMEM_RESOURCE_END     0xfffffffffULL
 
-#endif /* !defined (_LANGUAGE_ASSEMBLY) */
+#else
 
-/* Au1300 peripheral interrupt numbers */
-#define AU1300_FIRST_INT       (ALCHEMY_GPIC_INT_BASE)
-#define AU1300_UART1_INT       (AU1300_FIRST_INT + 17)
-#define AU1300_UART2_INT       (AU1300_FIRST_INT + 25)
-#define AU1300_UART3_INT       (AU1300_FIRST_INT + 27)
-#define AU1300_SD1_INT         (AU1300_FIRST_INT + 32)
-#define AU1300_SD2_INT         (AU1300_FIRST_INT + 38)
-#define AU1300_PSC0_INT                (AU1300_FIRST_INT + 48)
-#define AU1300_PSC1_INT                (AU1300_FIRST_INT + 52)
-#define AU1300_PSC2_INT                (AU1300_FIRST_INT + 56)
-#define AU1300_PSC3_INT                (AU1300_FIRST_INT + 60)
-#define AU1300_NAND_INT                (AU1300_FIRST_INT + 62)
-#define AU1300_DDMA_INT                (AU1300_FIRST_INT + 75)
-#define AU1300_MMU_INT         (AU1300_FIRST_INT + 76)
-#define AU1300_MPU_INT         (AU1300_FIRST_INT + 77)
-#define AU1300_GPU_INT         (AU1300_FIRST_INT + 78)
-#define AU1300_UDMA_INT                (AU1300_FIRST_INT + 79)
-#define AU1300_TOY_INT         (AU1300_FIRST_INT + 80)
-#define AU1300_TOY_MATCH0_INT  (AU1300_FIRST_INT + 81)
-#define AU1300_TOY_MATCH1_INT  (AU1300_FIRST_INT + 82)
-#define AU1300_TOY_MATCH2_INT  (AU1300_FIRST_INT + 83)
-#define AU1300_RTC_INT         (AU1300_FIRST_INT + 84)
-#define AU1300_RTC_MATCH0_INT  (AU1300_FIRST_INT + 85)
-#define AU1300_RTC_MATCH1_INT  (AU1300_FIRST_INT + 86)
-#define AU1300_RTC_MATCH2_INT  (AU1300_FIRST_INT + 87)
-#define AU1300_UART0_INT       (AU1300_FIRST_INT + 88)
-#define AU1300_SD0_INT         (AU1300_FIRST_INT + 89)
-#define AU1300_USB_INT         (AU1300_FIRST_INT + 90)
-#define AU1300_LCD_INT         (AU1300_FIRST_INT + 91)
-#define AU1300_BSA_INT         (AU1300_FIRST_INT + 92)
-#define AU1300_MPE_INT         (AU1300_FIRST_INT + 93)
-#define AU1300_ITE_INT         (AU1300_FIRST_INT + 94)
-#define AU1300_AES_INT         (AU1300_FIRST_INT + 95)
-#define AU1300_CIM_INT         (AU1300_FIRST_INT + 96)
+/* Don't allow any legacy ports probing */
+#define IOPORT_RESOURCE_START  0x10000000
+#define IOPORT_RESOURCE_END    0xffffffff
+#define IOMEM_RESOURCE_START   0x10000000
+#define IOMEM_RESOURCE_END     0xfffffffffULL
 
-/**********************************************************************/
+#endif
 
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
- */
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM           0x0000
+#define PCI_REG_CONFIG         0x0004
+#define PCI_REG_B2BMASK_CCH    0x0008
+#define PCI_REG_B2BBASE0_VID   0x000C
+#define PCI_REG_B2BBASE1_SID   0x0010
+#define PCI_REG_MWMASK_DEV     0x0014
+#define PCI_REG_MWBASE_REV_CCL 0x0018
+#define PCI_REG_ERR_ADDR       0x001C
+#define PCI_REG_SPEC_INTACK    0x0020
+#define PCI_REG_ID             0x0100
+#define PCI_REG_STATCMD                0x0104
+#define PCI_REG_CLASSREV       0x0108
+#define PCI_REG_PARAM          0x010C
+#define PCI_REG_MBAR           0x0110
+#define PCI_REG_TIMEOUT                0x0140
 
-#define AU1000_AC97_PHYS_ADDR          0x10000000 /* 012 */
-#define AU1300_ROM_PHYS_ADDR           0x10000000 /* 5 */
-#define AU1300_OTP_PHYS_ADDR           0x10002000 /* 5 */
-#define AU1300_VSS_PHYS_ADDR           0x10003000 /* 5 */
-#define AU1300_UART0_PHYS_ADDR         0x10100000 /* 5 */
-#define AU1300_UART1_PHYS_ADDR         0x10101000 /* 5 */
-#define AU1300_UART2_PHYS_ADDR         0x10102000 /* 5 */
-#define AU1300_UART3_PHYS_ADDR         0x10103000 /* 5 */
-#define AU1000_USB_OHCI_PHYS_ADDR      0x10100000 /* 012 */
-#define AU1000_USB_UDC_PHYS_ADDR       0x10200000 /* 0123 */
-#define AU1300_GPIC_PHYS_ADDR          0x10200000 /* 5 */
-#define AU1000_IRDA_PHYS_ADDR          0x10300000 /* 02 */
-#define AU1200_AES_PHYS_ADDR           0x10300000 /* 45 */
-#define AU1000_IC0_PHYS_ADDR           0x10400000 /* 01234 */
-#define AU1300_GPU_PHYS_ADDR           0x10500000 /* 5 */
-#define AU1000_MAC0_PHYS_ADDR          0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR          0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR         0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR           0x10600000 /* 245 */
-#define AU1300_SD1_PHYS_ADDR           0x10601000 /* 5 */
-#define AU1300_SD2_PHYS_ADDR           0x10602000 /* 5 */
-#define AU1100_SD1_PHYS_ADDR           0x10680000 /* 24 */
-#define AU1300_SYS_PHYS_ADDR           0x10900000 /* 5 */
-#define AU1550_PSC2_PHYS_ADDR          0x10A00000 /* 3 */
-#define AU1550_PSC3_PHYS_ADDR          0x10B00000 /* 3 */
-#define AU1300_PSC0_PHYS_ADDR          0x10A00000 /* 5 */
-#define AU1300_PSC1_PHYS_ADDR          0x10A01000 /* 5 */
-#define AU1300_PSC2_PHYS_ADDR          0x10A02000 /* 5 */
-#define AU1300_PSC3_PHYS_ADDR          0x10A03000 /* 5 */
-#define AU1000_I2S_PHYS_ADDR           0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR          0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR          0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR         0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR         0x11100000 /* 01234 */
-#define AU1200_SWCNT_PHYS_ADDR         0x1110010C /* 4 */
-#define AU1000_UART1_PHYS_ADDR         0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR         0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR         0x11400000 /* 0123 */
-#define AU1000_SSI0_PHYS_ADDR          0x11600000 /* 02 */
-#define AU1000_SSI1_PHYS_ADDR          0x11680000 /* 02 */
-#define AU1500_GPIO2_PHYS_ADDR         0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR           0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR           0x11900000 /* 012345 */
-#define AU1550_PSC0_PHYS_ADDR          0x11A00000 /* 34 */
-#define AU1550_PSC1_PHYS_ADDR          0x11B00000 /* 34 */
-#define AU1000_MEM_PHYS_ADDR           0x14000000 /* 01234 */
-#define AU1000_STATIC_MEM_PHYS_ADDR    0x14001000 /* 01234 */
-#define AU1300_UDMA_PHYS_ADDR          0x14001800 /* 5 */
-#define AU1000_DMA_PHYS_ADDR           0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR         0x14002000 /* 345 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR    0x14003000 /* 345 */
-#define AU1000_MACDMA0_PHYS_ADDR       0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR       0x14004200 /* 0123 */
-#define AU1200_CIM_PHYS_ADDR           0x14004000 /* 45 */
-#define AU1500_PCI_PHYS_ADDR           0x14005000 /* 13 */
-#define AU1550_PE_PHYS_ADDR            0x14008000 /* 3 */
-#define AU1200_MAEBE_PHYS_ADDR         0x14010000 /* 4 */
-#define AU1200_MAEFE_PHYS_ADDR         0x14012000 /* 4 */
-#define AU1300_MAEITE_PHYS_ADDR                0x14010000 /* 5 */
-#define AU1300_MAEMPE_PHYS_ADDR                0x14014000 /* 5 */
-#define AU1550_USB_OHCI_PHYS_ADDR      0x14020000 /* 3 */
-#define AU1200_USB_CTL_PHYS_ADDR       0x14020000 /* 4 */
-#define AU1200_USB_OTG_PHYS_ADDR       0x14020020 /* 4 */
-#define AU1200_USB_OHCI_PHYS_ADDR      0x14020100 /* 4 */
-#define AU1200_USB_EHCI_PHYS_ADDR      0x14020200 /* 4 */
-#define AU1200_USB_UDC_PHYS_ADDR       0x14022000 /* 4 */
-#define AU1300_USB_EHCI_PHYS_ADDR      0x14020000 /* 5 */
-#define AU1300_USB_OHCI0_PHYS_ADDR     0x14020400 /* 5 */
-#define AU1300_USB_OHCI1_PHYS_ADDR     0x14020800 /* 5 */
-#define AU1300_USB_CTL_PHYS_ADDR       0x14021000 /* 5 */
-#define AU1300_USB_OTG_PHYS_ADDR       0x14022000 /* 5 */
-#define AU1300_MAEBSA_PHYS_ADDR                0x14030000 /* 5 */
-#define AU1100_LCD_PHYS_ADDR           0x15000000 /* 2 */
-#define AU1200_LCD_PHYS_ADDR           0x15000000 /* 45 */
-#define AU1500_PCI_MEM_PHYS_ADDR       0x400000000ULL /* 13 */
-#define AU1500_PCI_IO_PHYS_ADDR                0x500000000ULL /* 13 */
-#define AU1500_PCI_CONFIG0_PHYS_ADDR   0x600000000ULL /* 13 */
-#define AU1500_PCI_CONFIG1_PHYS_ADDR   0x680000000ULL /* 13 */
-#define AU1000_PCMCIA_IO_PHYS_ADDR     0xF00000000ULL /* 012345 */
-#define AU1000_PCMCIA_ATTR_PHYS_ADDR   0xF40000000ULL /* 012345 */
-#define AU1000_PCMCIA_MEM_PHYS_ADDR    0xF80000000ULL /* 012345 */
-
-/**********************************************************************/
-
-
-/*
- * Au1300 GPIO+INT controller (GPIC) register offsets and bits
- * Registers are 128bits (0x10 bytes), divided into 4 "banks".
- */
-#define AU1300_GPIC_PINVAL     0x0000
-#define AU1300_GPIC_PINVALCLR  0x0010
-#define AU1300_GPIC_IPEND      0x0020
-#define AU1300_GPIC_PRIENC     0x0030
-#define AU1300_GPIC_IEN                0x0040  /* int_mask in manual */
-#define AU1300_GPIC_IDIS       0x0050  /* int_maskclr in manual */
-#define AU1300_GPIC_DMASEL     0x0060
-#define AU1300_GPIC_DEVSEL     0x0080
-#define AU1300_GPIC_DEVCLR     0x0090
-#define AU1300_GPIC_RSTVAL     0x00a0
-/* pin configuration space. one 32bit register for up to 128 IRQs */
-#define AU1300_GPIC_PINCFG     0x1000
-
-#define GPIC_GPIO_TO_BIT(gpio) \
-       (1 << ((gpio) & 0x1f))
-
-#define GPIC_GPIO_BANKOFF(gpio) \
-       (((gpio) >> 5) * 4)
+/* PCI controller block register bits */
+#define PCI_CMEM_E             (1 << 28)       /* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x)     (((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x)     ((x) & 0x3fff)
+#define PCI_CONFIG_ERD         (1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET          (1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF          (1 << 25) /* fatal error */
+#define PCI_CONFIG_EP          (1 << 24) /* parity error */
+#define PCI_CONFIG_EM          (1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM          (1 << 22) /* bad master error */
+#define PCI_CONFIG_PD          (1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME         (1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC          (1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA          (1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP          (1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS          (1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM         (1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM         (1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT         (1 << 9)  /* int on target abort (as target) */
+#define PCI_CONFIG_IPB         (1 << 8)  /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO      (0 << 6)  /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR  (1 << 6)  /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT (2 << 6)  /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL     (3 << 6)  /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST          (1 << 5)  /* swap data by target transactions */
+#define PCI_CONFIG_SM          (1 << 4)  /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN         (1 << 3)  /* enable internal arbiter */
+#define PCI_CONFIG_R2H         (1 << 2)  /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H         (1 << 1)  /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH          (1 << 0)  /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x) (((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x)     ((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x) (((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x) ((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x) (((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x) ((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x) ((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x)         (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x)         ((x) & 0xff)
+#define PCI_ID_DID(x)          (((x) & 0xffff) << 16)
+#define PCI_ID_VID(x)          ((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x)  (((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x)     ((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x)  (((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x)    ((x) & 0xff)
+#define PCI_PARAM_BIST(x)      (((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x)                (((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x)                (((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x)       ((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x) (((x) & 0xff) << 8)     /* max retries */
+#define PCI_TIMEOUT_TO(x)      ((x) & 0xff)    /* target ready timeout */
 
-/* Pin Control bits: who owns the pin, what does it do */
-#define GPIC_CFG_PC_GPIN               0
-#define GPIC_CFG_PC_DEV                        1
-#define GPIC_CFG_PC_GPOLOW             2
-#define GPIC_CFG_PC_GPOHIGH            3
-#define GPIC_CFG_PC_MASK               3
 
-/* assign pin to MIPS IRQ line */
-#define GPIC_CFG_IL_SET(x)     (((x) & 3) << 2)
-#define GPIC_CFG_IL_MASK       (3 << 2)
+/**********************************************************************/
 
-/* pin interrupt type setup */
-#define GPIC_CFG_IC_OFF                (0 << 4)
-#define GPIC_CFG_IC_LEVEL_LOW  (1 << 4)
-#define GPIC_CFG_IC_LEVEL_HIGH (2 << 4)
-#define GPIC_CFG_IC_EDGE_FALL  (5 << 4)
-#define GPIC_CFG_IC_EDGE_RISE  (6 << 4)
-#define GPIC_CFG_IC_EDGE_BOTH  (7 << 4)
-#define GPIC_CFG_IC_MASK       (7 << 4)
 
-/* allow interrupt to wake cpu from 'wait' */
-#define GPIC_CFG_IDLEWAKE      (1 << 7)
+#ifndef _LANGUAGE_ASSEMBLY
 
-/***********************************************************************/
+#include <linux/delay.h>
+#include <linux/types.h>
 
-/* Au1000 SDRAM memory controller register offsets */
-#define AU1000_MEM_SDMODE0             0x0000
-#define AU1000_MEM_SDMODE1             0x0004
-#define AU1000_MEM_SDMODE2             0x0008
-#define AU1000_MEM_SDADDR0             0x000C
-#define AU1000_MEM_SDADDR1             0x0010
-#define AU1000_MEM_SDADDR2             0x0014
-#define AU1000_MEM_SDREFCFG            0x0018
-#define AU1000_MEM_SDPRECMD            0x001C
-#define AU1000_MEM_SDAUTOREF           0x0020
-#define AU1000_MEM_SDWRMD0             0x0024
-#define AU1000_MEM_SDWRMD1             0x0028
-#define AU1000_MEM_SDWRMD2             0x002C
-#define AU1000_MEM_SDSLEEP             0x0030
-#define AU1000_MEM_SDSMCKE             0x0034
+#include <linux/io.h>
+#include <linux/irq.h>
 
-/* MEM_SDMODE register content definitions */
-#define MEM_SDMODE_F           (1 << 22)
-#define MEM_SDMODE_SR          (1 << 21)
-#define MEM_SDMODE_BS          (1 << 20)
-#define MEM_SDMODE_RS          (3 << 18)
-#define MEM_SDMODE_CS          (7 << 15)
-#define MEM_SDMODE_TRAS                (15 << 11)
-#define MEM_SDMODE_TMRD                (3 << 9)
-#define MEM_SDMODE_TWR         (3 << 7)
-#define MEM_SDMODE_TRP         (3 << 5)
-#define MEM_SDMODE_TRCD                (3 << 3)
-#define MEM_SDMODE_TCL         (7 << 0)
+#include <asm/cpu.h>
 
-#define MEM_SDMODE_BS_2Bank    (0 << 20)
-#define MEM_SDMODE_BS_4Bank    (1 << 20)
-#define MEM_SDMODE_RS_11Row    (0 << 18)
-#define MEM_SDMODE_RS_12Row    (1 << 18)
-#define MEM_SDMODE_RS_13Row    (2 << 18)
-#define MEM_SDMODE_RS_N(N)     ((N) << 18)
-#define MEM_SDMODE_CS_7Col     (0 << 15)
-#define MEM_SDMODE_CS_8Col     (1 << 15)
-#define MEM_SDMODE_CS_9Col     (2 << 15)
-#define MEM_SDMODE_CS_10Col    (3 << 15)
-#define MEM_SDMODE_CS_11Col    (4 << 15)
-#define MEM_SDMODE_CS_N(N)     ((N) << 15)
-#define MEM_SDMODE_TRAS_N(N)   ((N) << 11)
-#define MEM_SDMODE_TMRD_N(N)   ((N) << 9)
-#define MEM_SDMODE_TWR_N(N)    ((N) << 7)
-#define MEM_SDMODE_TRP_N(N)    ((N) << 5)
-#define MEM_SDMODE_TRCD_N(N)   ((N) << 3)
-#define MEM_SDMODE_TCL_N(N)    ((N) << 0)
+/* helpers to access the SYS_* registers */
+static inline unsigned long alchemy_rdsys(int regofs)
+{
+       void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 
-/* MEM_SDADDR register contents definitions */
-#define MEM_SDADDR_E           (1 << 20)
-#define MEM_SDADDR_CSBA                (0x03FF << 10)
-#define MEM_SDADDR_CSMASK      (0x03FF << 0)
-#define MEM_SDADDR_CSBA_N(N)   ((N) & (0x03FF << 22) >> 12)
-#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF << 22) >> 22)
+       return __raw_readl(b + regofs);
+}
 
-/* MEM_SDREFCFG register content definitions */
-#define MEM_SDREFCFG_TRC       (15 << 28)
-#define MEM_SDREFCFG_TRPM      (3 << 26)
-#define MEM_SDREFCFG_E         (1 << 25)
-#define MEM_SDREFCFG_RE                (0x1ffffff << 0)
-#define MEM_SDREFCFG_TRC_N(N)  ((N) << MEM_SDREFCFG_TRC)
-#define MEM_SDREFCFG_TRPM_N(N) ((N) << MEM_SDREFCFG_TRPM)
-#define MEM_SDREFCFG_REF_N(N)  (N)
+static inline void alchemy_wrsys(unsigned long v, int regofs)
+{
+       void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 
-/* Au1550 SDRAM Register Offsets */
-#define AU1550_MEM_SDMODE0             0x0800
-#define AU1550_MEM_SDMODE1             0x0808
-#define AU1550_MEM_SDMODE2             0x0810
-#define AU1550_MEM_SDADDR0             0x0820
-#define AU1550_MEM_SDADDR1             0x0828
-#define AU1550_MEM_SDADDR2             0x0830
-#define AU1550_MEM_SDCONFIGA           0x0840
-#define AU1550_MEM_SDCONFIGB           0x0848
-#define AU1550_MEM_SDSTAT              0x0850
-#define AU1550_MEM_SDERRADDR           0x0858
-#define AU1550_MEM_SDSTRIDE0           0x0860
-#define AU1550_MEM_SDSTRIDE1           0x0868
-#define AU1550_MEM_SDSTRIDE2           0x0870
-#define AU1550_MEM_SDWRMD0             0x0880
-#define AU1550_MEM_SDWRMD1             0x0888
-#define AU1550_MEM_SDWRMD2             0x0890
-#define AU1550_MEM_SDPRECMD            0x08C0
-#define AU1550_MEM_SDAUTOREF           0x08C8
-#define AU1550_MEM_SDSREF              0x08D0
-#define AU1550_MEM_SDSLEEP             MEM_SDSREF
+       __raw_writel(v, b + regofs);
+       wmb(); /* drain writebuffer */
+}
 
-/* Static Bus Controller */
-#define MEM_STCFG0             0xB4001000
-#define MEM_STTIME0            0xB4001004
-#define MEM_STADDR0            0xB4001008
+/* helpers to access static memctrl registers */
+static inline unsigned long alchemy_rdsmem(int regofs)
+{
+       void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 
-#define MEM_STCFG1             0xB4001010
-#define MEM_STTIME1            0xB4001014
-#define MEM_STADDR1            0xB4001018
+       return __raw_readl(b + regofs);
+}
 
-#define MEM_STCFG2             0xB4001020
-#define MEM_STTIME2            0xB4001024
-#define MEM_STADDR2            0xB4001028
+static inline void alchemy_wrsmem(unsigned long v, int regofs)
+{
+       void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 
-#define MEM_STCFG3             0xB4001030
-#define MEM_STTIME3            0xB4001034
-#define MEM_STADDR3            0xB4001038
+       __raw_writel(v, b + regofs);
+       wmb(); /* drain writebuffer */
+}
 
-#define MEM_STNDCTL            0xB4001100
-#define MEM_STSTAT             0xB4001104
+/* Early Au1000 have a write-only SYS_CPUPLL register. */
+static inline int au1xxx_cpu_has_pll_wo(void)
+{
+       switch (read_c0_prid()) {
+       case 0x00030100:        /* Au1000 DA */
+       case 0x00030201:        /* Au1000 HA */
+       case 0x00030202:        /* Au1000 HB */
+               return 1;
+       }
+       return 0;
+}
 
-#define MEM_STNAND_CMD         0x0
-#define MEM_STNAND_ADDR                0x4
-#define MEM_STNAND_DATA                0x20
-
-
-/* Programmable Counters 0 and 1 */
-#define SYS_BASE               0xB1900000
-#define SYS_COUNTER_CNTRL      (SYS_BASE + 0x14)
-#  define SYS_CNTRL_E1S                (1 << 23)
-#  define SYS_CNTRL_T1S                (1 << 20)
-#  define SYS_CNTRL_M21                (1 << 19)
-#  define SYS_CNTRL_M11                (1 << 18)
-#  define SYS_CNTRL_M01                (1 << 17)
-#  define SYS_CNTRL_C1S                (1 << 16)
-#  define SYS_CNTRL_BP         (1 << 14)
-#  define SYS_CNTRL_EN1                (1 << 13)
-#  define SYS_CNTRL_BT1                (1 << 12)
-#  define SYS_CNTRL_EN0                (1 << 11)
-#  define SYS_CNTRL_BT0                (1 << 10)
-#  define SYS_CNTRL_E0         (1 << 8)
-#  define SYS_CNTRL_E0S                (1 << 7)
-#  define SYS_CNTRL_32S                (1 << 5)
-#  define SYS_CNTRL_T0S                (1 << 4)
-#  define SYS_CNTRL_M20                (1 << 3)
-#  define SYS_CNTRL_M10                (1 << 2)
-#  define SYS_CNTRL_M00                (1 << 1)
-#  define SYS_CNTRL_C0S                (1 << 0)
+/* does CPU need CONFIG[OD] set to fix tons of errata? */
+static inline int au1xxx_cpu_needs_config_od(void)
+{
+       /*
+        * c0_config.od (bit 19) was write only (and read as 0) on the
+        * early revisions of Alchemy SOCs.  It disables the bus trans-
+        * action overlapping and needs to be set to fix various errata.
+        */
+       switch (read_c0_prid()) {
+       case 0x00030100: /* Au1000 DA */
+       case 0x00030201: /* Au1000 HA */
+       case 0x00030202: /* Au1000 HB */
+       case 0x01030200: /* Au1500 AB */
+       /*
+        * Au1100/Au1200 errata actually keep silence about this bit,
+        * so we set it just in case for those revisions that require
+        * it to be set according to the (now gone) cpu_table.
+        */
+       case 0x02030200: /* Au1100 AB */
+       case 0x02030201: /* Au1100 BA */
+       case 0x02030202: /* Au1100 BC */
+       case 0x04030201: /* Au1200 AC */
+               return 1;
+       }
+       return 0;
+}
 
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM            (SYS_BASE + 0)
-#define SYS_TOYWRITE           (SYS_BASE + 4)
-#define SYS_TOYMATCH0          (SYS_BASE + 8)
-#define SYS_TOYMATCH1          (SYS_BASE + 0xC)
-#define SYS_TOYMATCH2          (SYS_BASE + 0x10)
-#define SYS_TOYREAD            (SYS_BASE + 0x40)
+#define ALCHEMY_CPU_UNKNOWN    -1
+#define ALCHEMY_CPU_AU1000     0
+#define ALCHEMY_CPU_AU1500     1
+#define ALCHEMY_CPU_AU1100     2
+#define ALCHEMY_CPU_AU1550     3
+#define ALCHEMY_CPU_AU1200     4
+#define ALCHEMY_CPU_AU1300     5
 
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM            (SYS_BASE + 0x44)
-#define SYS_RTCWRITE           (SYS_BASE + 0x48)
-#define SYS_RTCMATCH0          (SYS_BASE + 0x4C)
-#define SYS_RTCMATCH1          (SYS_BASE + 0x50)
-#define SYS_RTCMATCH2          (SYS_BASE + 0x54)
-#define SYS_RTCREAD            (SYS_BASE + 0x58)
-
-/* I2S Controller */
-#define I2S_DATA               0xB1000000
-#  define I2S_DATA_MASK                0xffffff
-#define I2S_CONFIG             0xB1000004
-#  define I2S_CONFIG_XU                (1 << 25)
-#  define I2S_CONFIG_XO                (1 << 24)
-#  define I2S_CONFIG_RU                (1 << 23)
-#  define I2S_CONFIG_RO                (1 << 22)
-#  define I2S_CONFIG_TR                (1 << 21)
-#  define I2S_CONFIG_TE                (1 << 20)
-#  define I2S_CONFIG_TF                (1 << 19)
-#  define I2S_CONFIG_RR                (1 << 18)
-#  define I2S_CONFIG_RE                (1 << 17)
-#  define I2S_CONFIG_RF                (1 << 16)
-#  define I2S_CONFIG_PD                (1 << 11)
-#  define I2S_CONFIG_LB                (1 << 10)
-#  define I2S_CONFIG_IC                (1 << 9)
-#  define I2S_CONFIG_FM_BIT    7
-#  define I2S_CONFIG_FM_MASK   (0x3 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_I2S  (0x0 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_LJ   (0x1 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_RJ   (0x2 << I2S_CONFIG_FM_BIT)
-#  define I2S_CONFIG_TN                (1 << 6)
-#  define I2S_CONFIG_RN                (1 << 5)
-#  define I2S_CONFIG_SZ_BIT    0
-#  define I2S_CONFIG_SZ_MASK   (0x1F << I2S_CONFIG_SZ_BIT)
-
-#define I2S_CONTROL            0xB1000008
-#  define I2S_CONTROL_D                (1 << 1)
-#  define I2S_CONTROL_CE       (1 << 0)
-
-
-/* Ethernet Controllers  */
-
-/* 4 byte offsets from AU1000_ETH_BASE */
-#define MAC_CONTROL            0x0
-#  define MAC_RX_ENABLE                (1 << 2)
-#  define MAC_TX_ENABLE                (1 << 3)
-#  define MAC_DEF_CHECK                (1 << 5)
-#  define MAC_SET_BL(X)                (((X) & 0x3) << 6)
-#  define MAC_AUTO_PAD         (1 << 8)
-#  define MAC_DISABLE_RETRY    (1 << 10)
-#  define MAC_DISABLE_BCAST    (1 << 11)
-#  define MAC_LATE_COL         (1 << 12)
-#  define MAC_HASH_MODE                (1 << 13)
-#  define MAC_HASH_ONLY                (1 << 15)
-#  define MAC_PASS_ALL         (1 << 16)
-#  define MAC_INVERSE_FILTER   (1 << 17)
-#  define MAC_PROMISCUOUS      (1 << 18)
-#  define MAC_PASS_ALL_MULTI   (1 << 19)
-#  define MAC_FULL_DUPLEX      (1 << 20)
-#  define MAC_NORMAL_MODE      0
-#  define MAC_INT_LOOPBACK     (1 << 21)
-#  define MAC_EXT_LOOPBACK     (1 << 22)
-#  define MAC_DISABLE_RX_OWN   (1 << 23)
-#  define MAC_BIG_ENDIAN       (1 << 30)
-#  define MAC_RX_ALL           (1 << 31)
-#define MAC_ADDRESS_HIGH       0x4
-#define MAC_ADDRESS_LOW                0x8
-#define MAC_MCAST_HIGH         0xC
-#define MAC_MCAST_LOW          0x10
-#define MAC_MII_CNTRL          0x14
-#  define MAC_MII_BUSY         (1 << 0)
-#  define MAC_MII_READ         0
-#  define MAC_MII_WRITE                (1 << 1)
-#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
-#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
-#define MAC_MII_DATA           0x18
-#define MAC_FLOW_CNTRL         0x1C
-#  define MAC_FLOW_CNTRL_BUSY  (1 << 0)
-#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
-#  define MAC_PASS_CONTROL     (1 << 2)
-#  define MAC_SET_PAUSE(X)     (((X) & 0xffff) << 16)
-#define MAC_VLAN1_TAG          0x20
-#define MAC_VLAN2_TAG          0x24
-
-/* Ethernet Controller Enable */
-
-#  define MAC_EN_CLOCK_ENABLE  (1 << 0)
-#  define MAC_EN_RESET0                (1 << 1)
-#  define MAC_EN_TOSS          (0 << 2)
-#  define MAC_EN_CACHEABLE     (1 << 3)
-#  define MAC_EN_RESET1                (1 << 4)
-#  define MAC_EN_RESET2                (1 << 5)
-#  define MAC_DMA_RESET                (1 << 6)
-
-/* Ethernet Controller DMA Channels */
-
-#define MAC0_TX_DMA_ADDR       0xB4004000
-#define MAC1_TX_DMA_ADDR       0xB4004200
-/* offsets from MAC_TX_RING_ADDR address */
-#define MAC_TX_BUFF0_STATUS    0x0
-#  define TX_FRAME_ABORTED     (1 << 0)
-#  define TX_JAB_TIMEOUT       (1 << 1)
-#  define TX_NO_CARRIER                (1 << 2)
-#  define TX_LOSS_CARRIER      (1 << 3)
-#  define TX_EXC_DEF           (1 << 4)
-#  define TX_LATE_COLL_ABORT   (1 << 5)
-#  define TX_EXC_COLL          (1 << 6)
-#  define TX_UNDERRUN          (1 << 7)
-#  define TX_DEFERRED          (1 << 8)
-#  define TX_LATE_COLL         (1 << 9)
-#  define TX_COLL_CNT_MASK     (0xF << 10)
-#  define TX_PKT_RETRY         (1 << 31)
-#define MAC_TX_BUFF0_ADDR      0x4
-#  define TX_DMA_ENABLE                (1 << 0)
-#  define TX_T_DONE            (1 << 1)
-#  define TX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
-#define MAC_TX_BUFF0_LEN       0x8
-#define MAC_TX_BUFF1_STATUS    0x10
-#define MAC_TX_BUFF1_ADDR      0x14
-#define MAC_TX_BUFF1_LEN       0x18
-#define MAC_TX_BUFF2_STATUS    0x20
-#define MAC_TX_BUFF2_ADDR      0x24
-#define MAC_TX_BUFF2_LEN       0x28
-#define MAC_TX_BUFF3_STATUS    0x30
-#define MAC_TX_BUFF3_ADDR      0x34
-#define MAC_TX_BUFF3_LEN       0x38
-
-#define MAC0_RX_DMA_ADDR       0xB4004100
-#define MAC1_RX_DMA_ADDR       0xB4004300
-/* offsets from MAC_RX_RING_ADDR */
-#define MAC_RX_BUFF0_STATUS    0x0
-#  define RX_FRAME_LEN_MASK    0x3fff
-#  define RX_WDOG_TIMER                (1 << 14)
-#  define RX_RUNT              (1 << 15)
-#  define RX_OVERLEN           (1 << 16)
-#  define RX_COLL              (1 << 17)
-#  define RX_ETHER             (1 << 18)
-#  define RX_MII_ERROR         (1 << 19)
-#  define RX_DRIBBLING         (1 << 20)
-#  define RX_CRC_ERROR         (1 << 21)
-#  define RX_VLAN1             (1 << 22)
-#  define RX_VLAN2             (1 << 23)
-#  define RX_LEN_ERROR         (1 << 24)
-#  define RX_CNTRL_FRAME       (1 << 25)
-#  define RX_U_CNTRL_FRAME     (1 << 26)
-#  define RX_MCAST_FRAME       (1 << 27)
-#  define RX_BCAST_FRAME       (1 << 28)
-#  define RX_FILTER_FAIL       (1 << 29)
-#  define RX_PACKET_FILTER     (1 << 30)
-#  define RX_MISSED_FRAME      (1 << 31)
-
-#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
-                   RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
-                   RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
-#define MAC_RX_BUFF0_ADDR      0x4
-#  define RX_DMA_ENABLE                (1 << 0)
-#  define RX_T_DONE            (1 << 1)
-#  define RX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
-#  define RX_SET_BUFF_ADDR(X)  ((X) & 0xffffffc0)
-#define MAC_RX_BUFF1_STATUS    0x10
-#define MAC_RX_BUFF1_ADDR      0x14
-#define MAC_RX_BUFF2_STATUS    0x20
-#define MAC_RX_BUFF2_ADDR      0x24
-#define MAC_RX_BUFF3_STATUS    0x30
-#define MAC_RX_BUFF3_ADDR      0x34
-
-/* SSIO */
-#define SSI0_STATUS            0xB1600000
-#  define SSI_STATUS_BF                (1 << 4)
-#  define SSI_STATUS_OF                (1 << 3)
-#  define SSI_STATUS_UF                (1 << 2)
-#  define SSI_STATUS_D         (1 << 1)
-#  define SSI_STATUS_B         (1 << 0)
-#define SSI0_INT               0xB1600004
-#  define SSI_INT_OI           (1 << 3)
-#  define SSI_INT_UI           (1 << 2)
-#  define SSI_INT_DI           (1 << 1)
-#define SSI0_INT_ENABLE                0xB1600008
-#  define SSI_INTE_OIE         (1 << 3)
-#  define SSI_INTE_UIE         (1 << 2)
-#  define SSI_INTE_DIE         (1 << 1)
-#define SSI0_CONFIG            0xB1600020
-#  define SSI_CONFIG_AO                (1 << 24)
-#  define SSI_CONFIG_DO                (1 << 23)
-#  define SSI_CONFIG_ALEN_BIT  20
-#  define SSI_CONFIG_ALEN_MASK (0x7 << 20)
-#  define SSI_CONFIG_DLEN_BIT  16
-#  define SSI_CONFIG_DLEN_MASK (0x7 << 16)
-#  define SSI_CONFIG_DD                (1 << 11)
-#  define SSI_CONFIG_AD                (1 << 10)
-#  define SSI_CONFIG_BM_BIT    8
-#  define SSI_CONFIG_BM_MASK   (0x3 << 8)
-#  define SSI_CONFIG_CE                (1 << 7)
-#  define SSI_CONFIG_DP                (1 << 6)
-#  define SSI_CONFIG_DL                (1 << 5)
-#  define SSI_CONFIG_EP                (1 << 4)
-#define SSI0_ADATA             0xB1600024
-#  define SSI_AD_D             (1 << 24)
-#  define SSI_AD_ADDR_BIT      16
-#  define SSI_AD_ADDR_MASK     (0xff << 16)
-#  define SSI_AD_DATA_BIT      0
-#  define SSI_AD_DATA_MASK     (0xfff << 0)
-#define SSI0_CLKDIV            0xB1600028
-#define SSI0_CONTROL           0xB1600100
-#  define SSI_CONTROL_CD       (1 << 1)
-#  define SSI_CONTROL_E                (1 << 0)
-
-/* SSI1 */
-#define SSI1_STATUS            0xB1680000
-#define SSI1_INT               0xB1680004
-#define SSI1_INT_ENABLE                0xB1680008
-#define SSI1_CONFIG            0xB1680020
-#define SSI1_ADATA             0xB1680024
-#define SSI1_CLKDIV            0xB1680028
-#define SSI1_ENABLE            0xB1680100
+static inline int alchemy_get_cputype(void)
+{
+       switch (read_c0_prid() & (PRID_OPT_MASK | PRID_COMP_MASK)) {
+       case 0x00030000:
+               return ALCHEMY_CPU_AU1000;
+               break;
+       case 0x01030000:
+               return ALCHEMY_CPU_AU1500;
+               break;
+       case 0x02030000:
+               return ALCHEMY_CPU_AU1100;
+               break;
+       case 0x03030000:
+               return ALCHEMY_CPU_AU1550;
+               break;
+       case 0x04030000:
+       case 0x05030000:
+               return ALCHEMY_CPU_AU1200;
+               break;
+       case 0x800c0000:
+               return ALCHEMY_CPU_AU1300;
+               break;
+       }
 
-/*
- * Register content definitions
- */
-#define SSI_STATUS_BF          (1 << 4)
-#define SSI_STATUS_OF          (1 << 3)
-#define SSI_STATUS_UF          (1 << 2)
-#define SSI_STATUS_D           (1 << 1)
-#define SSI_STATUS_B           (1 << 0)
-
-/* SSI_INT */
-#define SSI_INT_OI             (1 << 3)
-#define SSI_INT_UI             (1 << 2)
-#define SSI_INT_DI             (1 << 1)
-
-/* SSI_INTEN */
-#define SSI_INTEN_OIE          (1 << 3)
-#define SSI_INTEN_UIE          (1 << 2)
-#define SSI_INTEN_DIE          (1 << 1)
-
-#define SSI_CONFIG_AO          (1 << 24)
-#define SSI_CONFIG_DO          (1 << 23)
-#define SSI_CONFIG_ALEN                (7 << 20)
-#define SSI_CONFIG_DLEN                (15 << 16)
-#define SSI_CONFIG_DD          (1 << 11)
-#define SSI_CONFIG_AD          (1 << 10)
-#define SSI_CONFIG_BM          (3 << 8)
-#define SSI_CONFIG_CE          (1 << 7)
-#define SSI_CONFIG_DP          (1 << 6)
-#define SSI_CONFIG_DL          (1 << 5)
-#define SSI_CONFIG_EP          (1 << 4)
-#define SSI_CONFIG_ALEN_N(N)   ((N-1) << 20)
-#define SSI_CONFIG_DLEN_N(N)   ((N-1) << 16)
-#define SSI_CONFIG_BM_HI       (0 << 8)
-#define SSI_CONFIG_BM_LO       (1 << 8)
-#define SSI_CONFIG_BM_CY       (2 << 8)
-
-#define SSI_ADATA_D            (1 << 24)
-#define SSI_ADATA_ADDR         (0xFF << 16)
-#define SSI_ADATA_DATA         0x0FFF
-#define SSI_ADATA_ADDR_N(N)    (N << 16)
-
-#define SSI_ENABLE_CD          (1 << 1)
-#define SSI_ENABLE_E           (1 << 0)
+       return ALCHEMY_CPU_UNKNOWN;
+}
 
+/* return number of uarts on a given cputype */
+static inline int alchemy_get_uarts(int type)
+{
+       switch (type) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1300:
+               return 4;
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1200:
+               return 2;
+       case ALCHEMY_CPU_AU1100:
+       case ALCHEMY_CPU_AU1550:
+               return 3;
+       }
+       return 0;
+}
 
-/*
- * The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's not
- * used to select FIR/SIR mode on the transceiver but as a GPIO.  Instead a
- * CPLD has to be told about the mode.
- */
-#define AU1000_IRDA_PHY_MODE_OFF       0
-#define AU1000_IRDA_PHY_MODE_SIR       1
-#define AU1000_IRDA_PHY_MODE_FIR       2
+/* enable an UART block if it isn't already */
+static inline void alchemy_uart_enable(u32 uart_phys)
+{
+       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
 
-struct au1k_irda_platform_data {
-       void(*set_phy_mode)(int mode);
-};
+       /* reset, enable clock, deassert reset */
+       if ((__raw_readl(addr + 0x100) & 3) != 3) {
+               __raw_writel(0, addr + 0x100);
+               wmb(); /* drain writebuffer */
+               __raw_writel(1, addr + 0x100);
+               wmb(); /* drain writebuffer */
+       }
+       __raw_writel(3, addr + 0x100);
+       wmb(); /* drain writebuffer */
+}
 
+static inline void alchemy_uart_disable(u32 uart_phys)
+{
+       void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
 
-/* GPIO */
-#define SYS_PINFUNC            0xB190002C
-#  define SYS_PF_USB           (1 << 15)       /* 2nd USB device/host */
-#  define SYS_PF_U3            (1 << 14)       /* GPIO23/U3TXD */
-#  define SYS_PF_U2            (1 << 13)       /* GPIO22/U2TXD */
-#  define SYS_PF_U1            (1 << 12)       /* GPIO21/U1TXD */
-#  define SYS_PF_SRC           (1 << 11)       /* GPIO6/SROMCKE */
-#  define SYS_PF_CK5           (1 << 10)       /* GPIO3/CLK5 */
-#  define SYS_PF_CK4           (1 << 9)        /* GPIO2/CLK4 */
-#  define SYS_PF_IRF           (1 << 8)        /* GPIO15/IRFIRSEL */
-#  define SYS_PF_UR3           (1 << 7)        /* GPIO[14:9]/UART3 */
-#  define SYS_PF_I2D           (1 << 6)        /* GPIO8/I2SDI */
-#  define SYS_PF_I2S           (1 << 5)        /* I2S/GPIO[29:31] */
-#  define SYS_PF_NI2           (1 << 4)        /* NI2/GPIO[24:28] */
-#  define SYS_PF_U0            (1 << 3)        /* U0TXD/GPIO20 */
-#  define SYS_PF_RD            (1 << 2)        /* IRTXD/GPIO19 */
-#  define SYS_PF_A97           (1 << 1)        /* AC97/SSL1 */
-#  define SYS_PF_S0            (1 << 0)        /* SSI_0/GPIO[16:18] */
+       __raw_writel(0, addr + 0x100);  /* UART_MOD_CNTRL */
+       wmb(); /* drain writebuffer */
+}
 
-/* Au1100 only */
-#  define SYS_PF_PC            (1 << 18)       /* PCMCIA/GPIO[207:204] */
-#  define SYS_PF_LCD           (1 << 17)       /* extern lcd/GPIO[203:200] */
-#  define SYS_PF_CS            (1 << 16)       /* EXTCLK0/32KHz to gpio2 */
-#  define SYS_PF_EX0           (1 << 9)        /* GPIO2/clock */
+static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(uart_phys);
+       int timeout, i;
 
-/* Au1550 only.         Redefines lots of pins */
-#  define SYS_PF_PSC2_MASK     (7 << 17)
-#  define SYS_PF_PSC2_AC97     0
-#  define SYS_PF_PSC2_SPI      0
-#  define SYS_PF_PSC2_I2S      (1 << 17)
-#  define SYS_PF_PSC2_SMBUS    (3 << 17)
-#  define SYS_PF_PSC2_GPIO     (7 << 17)
-#  define SYS_PF_PSC3_MASK     (7 << 20)
-#  define SYS_PF_PSC3_AC97     0
-#  define SYS_PF_PSC3_SPI      0
-#  define SYS_PF_PSC3_I2S      (1 << 20)
-#  define SYS_PF_PSC3_SMBUS    (3 << 20)
-#  define SYS_PF_PSC3_GPIO     (7 << 20)
-#  define SYS_PF_PSC1_S1       (1 << 1)
-#  define SYS_PF_MUST_BE_SET   ((1 << 5) | (1 << 2))
+       /* check LSR TX_EMPTY bit */
+       timeout = 0xffffff;
+       do {
+               if (__raw_readl(base + 0x1c) & 0x20)
+                       break;
+               /* slow down */
+               for (i = 10000; i; i--)
+                       asm volatile ("nop");
+       } while (--timeout);
 
-/* Au1200 only */
-#define SYS_PINFUNC_DMA                (1 << 31)
-#define SYS_PINFUNC_S0A                (1 << 30)
-#define SYS_PINFUNC_S1A                (1 << 29)
-#define SYS_PINFUNC_LP0                (1 << 28)
-#define SYS_PINFUNC_LP1                (1 << 27)
-#define SYS_PINFUNC_LD16       (1 << 26)
-#define SYS_PINFUNC_LD8                (1 << 25)
-#define SYS_PINFUNC_LD1                (1 << 24)
-#define SYS_PINFUNC_LD0                (1 << 23)
-#define SYS_PINFUNC_P1A                (3 << 21)
-#define SYS_PINFUNC_P1B                (1 << 20)
-#define SYS_PINFUNC_FS3                (1 << 19)
-#define SYS_PINFUNC_P0A                (3 << 17)
-#define SYS_PINFUNC_CS         (1 << 16)
-#define SYS_PINFUNC_CIM                (1 << 15)
-#define SYS_PINFUNC_P1C                (1 << 14)
-#define SYS_PINFUNC_U1T                (1 << 12)
-#define SYS_PINFUNC_U1R                (1 << 11)
-#define SYS_PINFUNC_EX1                (1 << 10)
-#define SYS_PINFUNC_EX0                (1 << 9)
-#define SYS_PINFUNC_U0R                (1 << 8)
-#define SYS_PINFUNC_MC         (1 << 7)
-#define SYS_PINFUNC_S0B                (1 << 6)
-#define SYS_PINFUNC_S0C                (1 << 5)
-#define SYS_PINFUNC_P0B                (1 << 4)
-#define SYS_PINFUNC_U0T                (1 << 3)
-#define SYS_PINFUNC_S1B                (1 << 2)
+       __raw_writel(c, base + 0x04);   /* tx */
+       wmb(); /* drain writebuffer */
+}
 
-/* Power Management */
-#define SYS_SCRATCH0           0xB1900018
-#define SYS_SCRATCH1           0xB190001C
-#define SYS_WAKEMSK            0xB1900034
-#define SYS_ENDIAN             0xB1900038
-#define SYS_POWERCTRL          0xB190003C
-#define SYS_WAKESRC            0xB190005C
-#define SYS_SLPPWR             0xB1900078
-#define SYS_SLEEP              0xB190007C
+/* return number of ethernet MACs on a given cputype */
+static inline int alchemy_get_macs(int type)
+{
+       switch (type) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1550:
+               return 2;
+       case ALCHEMY_CPU_AU1100:
+               return 1;
+       }
+       return 0;
+}
 
-#define SYS_WAKEMSK_D2         (1 << 9)
-#define SYS_WAKEMSK_M2         (1 << 8)
-#define SYS_WAKEMSK_GPIO(x)    (1 << (x))
+/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
+void alchemy_sleep_au1000(void);
+void alchemy_sleep_au1550(void);
+void alchemy_sleep_au1300(void);
+void au_sleep(void);
 
-/* Clock Controller */
-#define SYS_FREQCTRL0          0xB1900020
-#  define SYS_FC_FRDIV2_BIT    22
-#  define SYS_FC_FRDIV2_MASK   (0xff << SYS_FC_FRDIV2_BIT)
-#  define SYS_FC_FE2           (1 << 21)
-#  define SYS_FC_FS2           (1 << 20)
-#  define SYS_FC_FRDIV1_BIT    12
-#  define SYS_FC_FRDIV1_MASK   (0xff << SYS_FC_FRDIV1_BIT)
-#  define SYS_FC_FE1           (1 << 11)
-#  define SYS_FC_FS1           (1 << 10)
-#  define SYS_FC_FRDIV0_BIT    2
-#  define SYS_FC_FRDIV0_MASK   (0xff << SYS_FC_FRDIV0_BIT)
-#  define SYS_FC_FE0           (1 << 1)
-#  define SYS_FC_FS0           (1 << 0)
-#define SYS_FREQCTRL1          0xB1900024
-#  define SYS_FC_FRDIV5_BIT    22
-#  define SYS_FC_FRDIV5_MASK   (0xff << SYS_FC_FRDIV5_BIT)
-#  define SYS_FC_FE5           (1 << 21)
-#  define SYS_FC_FS5           (1 << 20)
-#  define SYS_FC_FRDIV4_BIT    12
-#  define SYS_FC_FRDIV4_MASK   (0xff << SYS_FC_FRDIV4_BIT)
-#  define SYS_FC_FE4           (1 << 11)
-#  define SYS_FC_FS4           (1 << 10)
-#  define SYS_FC_FRDIV3_BIT    2
-#  define SYS_FC_FRDIV3_MASK   (0xff << SYS_FC_FRDIV3_BIT)
-#  define SYS_FC_FE3           (1 << 1)
-#  define SYS_FC_FS3           (1 << 0)
-#define SYS_CLKSRC             0xB1900028
-#  define SYS_CS_ME1_BIT       27
-#  define SYS_CS_ME1_MASK      (0x7 << SYS_CS_ME1_BIT)
-#  define SYS_CS_DE1           (1 << 26)
-#  define SYS_CS_CE1           (1 << 25)
-#  define SYS_CS_ME0_BIT       22
-#  define SYS_CS_ME0_MASK      (0x7 << SYS_CS_ME0_BIT)
-#  define SYS_CS_DE0           (1 << 21)
-#  define SYS_CS_CE0           (1 << 20)
-#  define SYS_CS_MI2_BIT       17
-#  define SYS_CS_MI2_MASK      (0x7 << SYS_CS_MI2_BIT)
-#  define SYS_CS_DI2           (1 << 16)
-#  define SYS_CS_CI2           (1 << 15)
-
-#  define SYS_CS_ML_BIT                7
-#  define SYS_CS_ML_MASK       (0x7 << SYS_CS_ML_BIT)
-#  define SYS_CS_DL            (1 << 6)
-#  define SYS_CS_CL            (1 << 5)
-
-#  define SYS_CS_MUH_BIT       12
-#  define SYS_CS_MUH_MASK      (0x7 << SYS_CS_MUH_BIT)
-#  define SYS_CS_DUH           (1 << 11)
-#  define SYS_CS_CUH           (1 << 10)
-#  define SYS_CS_MUD_BIT       7
-#  define SYS_CS_MUD_MASK      (0x7 << SYS_CS_MUD_BIT)
-#  define SYS_CS_DUD           (1 << 6)
-#  define SYS_CS_CUD           (1 << 5)
-
-#  define SYS_CS_MIR_BIT       2
-#  define SYS_CS_MIR_MASK      (0x7 << SYS_CS_MIR_BIT)
-#  define SYS_CS_DIR           (1 << 1)
-#  define SYS_CS_CIR           (1 << 0)
-
-#  define SYS_CS_MUX_AUX       0x1
-#  define SYS_CS_MUX_FQ0       0x2
-#  define SYS_CS_MUX_FQ1       0x3
-#  define SYS_CS_MUX_FQ2       0x4
-#  define SYS_CS_MUX_FQ3       0x5
-#  define SYS_CS_MUX_FQ4       0x6
-#  define SYS_CS_MUX_FQ5       0x7
-#define SYS_CPUPLL             0xB1900060
-#define SYS_AUXPLL             0xB1900064
-
-/* AC97 Controller */
-#define AC97C_CONFIG           0xB0000000
-#  define AC97C_RECV_SLOTS_BIT 13
-#  define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
-#  define AC97C_XMIT_SLOTS_BIT 3
-#  define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
-#  define AC97C_SG             (1 << 2)
-#  define AC97C_SYNC           (1 << 1)
-#  define AC97C_RESET          (1 << 0)
-#define AC97C_STATUS           0xB0000004
-#  define AC97C_XU             (1 << 11)
-#  define AC97C_XO             (1 << 10)
-#  define AC97C_RU             (1 << 9)
-#  define AC97C_RO             (1 << 8)
-#  define AC97C_READY          (1 << 7)
-#  define AC97C_CP             (1 << 6)
-#  define AC97C_TR             (1 << 5)
-#  define AC97C_TE             (1 << 4)
-#  define AC97C_TF             (1 << 3)
-#  define AC97C_RR             (1 << 2)
-#  define AC97C_RE             (1 << 1)
-#  define AC97C_RF             (1 << 0)
-#define AC97C_DATA             0xB0000008
-#define AC97C_CMD              0xB000000C
-#  define AC97C_WD_BIT         16
-#  define AC97C_READ           (1 << 7)
-#  define AC97C_INDEX_MASK     0x7f
-#define AC97C_CNTRL            0xB0000010
-#  define AC97C_RS             (1 << 1)
-#  define AC97C_CE             (1 << 0)
+/* USB: arch/mips/alchemy/common/usb.c */
+enum alchemy_usb_block {
+       ALCHEMY_USB_OHCI0,
+       ALCHEMY_USB_UDC0,
+       ALCHEMY_USB_EHCI0,
+       ALCHEMY_USB_OTG0,
+       ALCHEMY_USB_OHCI1,
+};
+int alchemy_usb_control(int block, int enable);
 
+/* PCI controller platform data */
+struct alchemy_pci_platdata {
+       int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
+       int (*board_pci_idsel)(unsigned int devsel, int assert);
+       /* bits to set/clear in PCI_CONFIG register */
+       unsigned long pci_cfg_set;
+       unsigned long pci_cfg_clr;
+};
 
-/* The PCI chip selects are outside the 32bit space, and since we can't
- * just program the 36bit addresses into BARs, we have to take a chunk
- * out of the 32bit space and reserve it for PCI.  When these addresses
- * are ioremap()ed, they'll be fixed up to the real 36bit address before
- * being passed to the real ioremap function.
+/* The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's
+ * not used to select FIR/SIR mode on the transceiver but as a GPIO.
+ * Instead a CPLD has to be told about the mode.  The driver calls the
+ * set_phy_mode() function in addition to driving the IRFIRSEL pin.
  */
-#define ALCHEMY_PCI_MEMWIN_START       (AU1500_PCI_MEM_PHYS_ADDR >> 4)
-#define ALCHEMY_PCI_MEMWIN_END         (ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
+#define AU1000_IRDA_PHY_MODE_OFF       0
+#define AU1000_IRDA_PHY_MODE_SIR       1
+#define AU1000_IRDA_PHY_MODE_FIR       2
 
-/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
- * adjust the device's resources.
+struct au1k_irda_platform_data {
+       void (*set_phy_mode)(int mode);
+};
+
+
+/* Multifunction pins: Each of these pins can either be assigned to the
+ * GPIO controller or a on-chip peripheral.
+ * Call "au1300_pinfunc_to_dev()" or "au1300_pinfunc_to_gpio()" to
+ * assign one of these to either the GPIO controller or the device.
  */
-#define ALCHEMY_PCI_IOWIN_START                0x00001000
-#define ALCHEMY_PCI_IOWIN_END          0x0000FFFF
+enum au1300_multifunc_pins {
+       /* wake-from-str pins 0-3 */
+       AU1300_PIN_WAKE0 = 0, AU1300_PIN_WAKE1, AU1300_PIN_WAKE2,
+       AU1300_PIN_WAKE3,
+       /* external clock sources for PSCs: 4-5 */
+       AU1300_PIN_EXTCLK0, AU1300_PIN_EXTCLK1,
+       /* 8bit MMC interface on SD0: 6-9 */
+       AU1300_PIN_SD0DAT4, AU1300_PIN_SD0DAT5, AU1300_PIN_SD0DAT6,
+       AU1300_PIN_SD0DAT7,
+       /* aux clk input for freqgen 3: 10 */
+       AU1300_PIN_FG3AUX,
+       /* UART1 pins: 11-18 */
+       AU1300_PIN_U1RI, AU1300_PIN_U1DCD, AU1300_PIN_U1DSR,
+       AU1300_PIN_U1CTS, AU1300_PIN_U1RTS, AU1300_PIN_U1DTR,
+       AU1300_PIN_U1RX, AU1300_PIN_U1TX,
+       /* UART0 pins: 19-24 */
+       AU1300_PIN_U0RI, AU1300_PIN_U0DCD, AU1300_PIN_U0DSR,
+       AU1300_PIN_U0CTS, AU1300_PIN_U0RTS, AU1300_PIN_U0DTR,
+       /* UART2: 25-26 */
+       AU1300_PIN_U2RX, AU1300_PIN_U2TX,
+       /* UART3: 27-28 */
+       AU1300_PIN_U3RX, AU1300_PIN_U3TX,
+       /* LCD controller PWMs, ext pixclock: 29-31 */
+       AU1300_PIN_LCDPWM0, AU1300_PIN_LCDPWM1, AU1300_PIN_LCDCLKIN,
+       /* SD1 interface: 32-37 */
+       AU1300_PIN_SD1DAT0, AU1300_PIN_SD1DAT1, AU1300_PIN_SD1DAT2,
+       AU1300_PIN_SD1DAT3, AU1300_PIN_SD1CMD, AU1300_PIN_SD1CLK,
+       /* SD2 interface: 38-43 */
+       AU1300_PIN_SD2DAT0, AU1300_PIN_SD2DAT1, AU1300_PIN_SD2DAT2,
+       AU1300_PIN_SD2DAT3, AU1300_PIN_SD2CMD, AU1300_PIN_SD2CLK,
+       /* PSC0/1 clocks: 44-45 */
+       AU1300_PIN_PSC0CLK, AU1300_PIN_PSC1CLK,
+       /* PSCs: 46-49/50-53/54-57/58-61 */
+       AU1300_PIN_PSC0SYNC0, AU1300_PIN_PSC0SYNC1, AU1300_PIN_PSC0D0,
+       AU1300_PIN_PSC0D1,
+       AU1300_PIN_PSC1SYNC0, AU1300_PIN_PSC1SYNC1, AU1300_PIN_PSC1D0,
+       AU1300_PIN_PSC1D1,
+       AU1300_PIN_PSC2SYNC0, AU1300_PIN_PSC2SYNC1, AU1300_PIN_PSC2D0,
+       AU1300_PIN_PSC2D1,
+       AU1300_PIN_PSC3SYNC0, AU1300_PIN_PSC3SYNC1, AU1300_PIN_PSC3D0,
+       AU1300_PIN_PSC3D1,
+       /* PCMCIA interface: 62-70 */
+       AU1300_PIN_PCE2, AU1300_PIN_PCE1, AU1300_PIN_PIOS16,
+       AU1300_PIN_PIOR, AU1300_PIN_PWE, AU1300_PIN_PWAIT,
+       AU1300_PIN_PREG, AU1300_PIN_POE, AU1300_PIN_PIOW,
+       /* camera interface H/V sync inputs: 71-72 */
+       AU1300_PIN_CIMLS, AU1300_PIN_CIMFS,
+       /* PSC2/3 clocks: 73-74 */
+       AU1300_PIN_PSC2CLK, AU1300_PIN_PSC3CLK,
+};
 
-#ifdef CONFIG_PCI
+/* GPIC (Au1300) pin management: arch/mips/alchemy/common/gpioint.c */
+extern void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio);
+extern void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio);
+extern void au1300_set_irq_priority(unsigned int irq, int p);
+extern void au1300_set_dbdma_gpio(int dchan, unsigned int gpio);
 
-#define IOPORT_RESOURCE_START  0x00001000      /* skip legacy probing */
-#define IOPORT_RESOURCE_END    0xffffffff
-#define IOMEM_RESOURCE_START   0x10000000
-#define IOMEM_RESOURCE_END     0xfffffffffULL
+/* Au1300 allows to disconnect certain blocks from internal power supply */
+enum au1300_vss_block {
+       AU1300_VSS_MPE = 0,
+       AU1300_VSS_BSA,
+       AU1300_VSS_GPE,
+       AU1300_VSS_MGP,
+};
 
-#else
+extern void au1300_vss_block_control(int block, int enable);
 
-/* Don't allow any legacy ports probing */
-#define IOPORT_RESOURCE_START  0x10000000
-#define IOPORT_RESOURCE_END    0xffffffff
-#define IOMEM_RESOURCE_START   0x10000000
-#define IOMEM_RESOURCE_END     0xfffffffffULL
+enum soc_au1000_ints {
+       AU1000_FIRST_INT        = AU1000_INTC0_INT_BASE,
+       AU1000_UART0_INT        = AU1000_FIRST_INT,
+       AU1000_UART1_INT,
+       AU1000_UART2_INT,
+       AU1000_UART3_INT,
+       AU1000_SSI0_INT,
+       AU1000_SSI1_INT,
+       AU1000_DMA_INT_BASE,
 
-#endif
+       AU1000_TOY_INT          = AU1000_FIRST_INT + 14,
+       AU1000_TOY_MATCH0_INT,
+       AU1000_TOY_MATCH1_INT,
+       AU1000_TOY_MATCH2_INT,
+       AU1000_RTC_INT,
+       AU1000_RTC_MATCH0_INT,
+       AU1000_RTC_MATCH1_INT,
+       AU1000_RTC_MATCH2_INT,
+       AU1000_IRDA_TX_INT,
+       AU1000_IRDA_RX_INT,
+       AU1000_USB_DEV_REQ_INT,
+       AU1000_USB_DEV_SUS_INT,
+       AU1000_USB_HOST_INT,
+       AU1000_ACSYNC_INT,
+       AU1000_MAC0_DMA_INT,
+       AU1000_MAC1_DMA_INT,
+       AU1000_I2S_UO_INT,
+       AU1000_AC97C_INT,
+       AU1000_GPIO0_INT,
+       AU1000_GPIO1_INT,
+       AU1000_GPIO2_INT,
+       AU1000_GPIO3_INT,
+       AU1000_GPIO4_INT,
+       AU1000_GPIO5_INT,
+       AU1000_GPIO6_INT,
+       AU1000_GPIO7_INT,
+       AU1000_GPIO8_INT,
+       AU1000_GPIO9_INT,
+       AU1000_GPIO10_INT,
+       AU1000_GPIO11_INT,
+       AU1000_GPIO12_INT,
+       AU1000_GPIO13_INT,
+       AU1000_GPIO14_INT,
+       AU1000_GPIO15_INT,
+       AU1000_GPIO16_INT,
+       AU1000_GPIO17_INT,
+       AU1000_GPIO18_INT,
+       AU1000_GPIO19_INT,
+       AU1000_GPIO20_INT,
+       AU1000_GPIO21_INT,
+       AU1000_GPIO22_INT,
+       AU1000_GPIO23_INT,
+       AU1000_GPIO24_INT,
+       AU1000_GPIO25_INT,
+       AU1000_GPIO26_INT,
+       AU1000_GPIO27_INT,
+       AU1000_GPIO28_INT,
+       AU1000_GPIO29_INT,
+       AU1000_GPIO30_INT,
+       AU1000_GPIO31_INT,
+};
 
-/* PCI controller block register offsets */
-#define PCI_REG_CMEM           0x0000
-#define PCI_REG_CONFIG         0x0004
-#define PCI_REG_B2BMASK_CCH    0x0008
-#define PCI_REG_B2BBASE0_VID   0x000C
-#define PCI_REG_B2BBASE1_SID   0x0010
-#define PCI_REG_MWMASK_DEV     0x0014
-#define PCI_REG_MWBASE_REV_CCL 0x0018
-#define PCI_REG_ERR_ADDR       0x001C
-#define PCI_REG_SPEC_INTACK    0x0020
-#define PCI_REG_ID             0x0100
-#define PCI_REG_STATCMD                0x0104
-#define PCI_REG_CLASSREV       0x0108
-#define PCI_REG_PARAM          0x010C
-#define PCI_REG_MBAR           0x0110
-#define PCI_REG_TIMEOUT                0x0140
+enum soc_au1100_ints {
+       AU1100_FIRST_INT        = AU1000_INTC0_INT_BASE,
+       AU1100_UART0_INT        = AU1100_FIRST_INT,
+       AU1100_UART1_INT,
+       AU1100_SD_INT,
+       AU1100_UART3_INT,
+       AU1100_SSI0_INT,
+       AU1100_SSI1_INT,
+       AU1100_DMA_INT_BASE,
 
-/* PCI controller block register bits */
-#define PCI_CMEM_E             (1 << 28)       /* enable cacheable memory */
-#define PCI_CMEM_CMBASE(x)     (((x) & 0x3fff) << 14)
-#define PCI_CMEM_CMMASK(x)     ((x) & 0x3fff)
-#define PCI_CONFIG_ERD         (1 << 27) /* pci error during R/W */
-#define PCI_CONFIG_ET          (1 << 26) /* error in target mode */
-#define PCI_CONFIG_EF          (1 << 25) /* fatal error */
-#define PCI_CONFIG_EP          (1 << 24) /* parity error */
-#define PCI_CONFIG_EM          (1 << 23) /* multiple errors */
-#define PCI_CONFIG_BM          (1 << 22) /* bad master error */
-#define PCI_CONFIG_PD          (1 << 20) /* PCI Disable */
-#define PCI_CONFIG_BME         (1 << 19) /* Byte Mask Enable for reads */
-#define PCI_CONFIG_NC          (1 << 16) /* mark mem access non-coherent */
-#define PCI_CONFIG_IA          (1 << 15) /* INTA# enabled (target mode) */
-#define PCI_CONFIG_IP          (1 << 13) /* int on PCI_PERR# */
-#define PCI_CONFIG_IS          (1 << 12) /* int on PCI_SERR# */
-#define PCI_CONFIG_IMM         (1 << 11) /* int on master abort */
-#define PCI_CONFIG_ITM         (1 << 10) /* int on target abort (as master) */
-#define PCI_CONFIG_ITT         (1 << 9)  /* int on target abort (as target) */
-#define PCI_CONFIG_IPB         (1 << 8)  /* int on PERR# in bus master acc */
-#define PCI_CONFIG_SIC_NO      (0 << 6)  /* no byte mask changes */
-#define PCI_CONFIG_SIC_BA_ADR  (1 << 6)  /* on byte/hw acc, invert adr bits */
-#define PCI_CONFIG_SIC_HWA_DAT (2 << 6)  /* on halfword acc, swap data */
-#define PCI_CONFIG_SIC_ALL     (3 << 6)  /* swap data bytes on all accesses */
-#define PCI_CONFIG_ST          (1 << 5)  /* swap data by target transactions */
-#define PCI_CONFIG_SM          (1 << 4)  /* swap data from PCI ctl */
-#define PCI_CONFIG_AEN         (1 << 3)  /* enable internal arbiter */
-#define PCI_CONFIG_R2H         (1 << 2)  /* REQ2# to hi-prio arbiter */
-#define PCI_CONFIG_R1H         (1 << 1)  /* REQ1# to hi-prio arbiter */
-#define PCI_CONFIG_CH          (1 << 0)  /* PCI ctl to hi-prio arbiter */
-#define PCI_B2BMASK_B2BMASK(x) (((x) & 0xffff) << 16)
-#define PCI_B2BMASK_CCH(x)     ((x) & 0xffff) /* 16 upper bits of class code */
-#define PCI_B2BBASE0_VID_B0(x) (((x) & 0xffff) << 16)
-#define PCI_B2BBASE0_VID_SV(x) ((x) & 0xffff)
-#define PCI_B2BBASE1_SID_B1(x) (((x) & 0xffff) << 16)
-#define PCI_B2BBASE1_SID_SI(x) ((x) & 0xffff)
-#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
-#define PCI_MWMASKDEV_DEVID(x) ((x) & 0xffff)
-#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
-#define PCI_MWBASEREVCCL_REV(x)         (((x) & 0xff) << 8)
-#define PCI_MWBASEREVCCL_CCL(x)         ((x) & 0xff)
-#define PCI_ID_DID(x)          (((x) & 0xffff) << 16)
-#define PCI_ID_VID(x)          ((x) & 0xffff)
-#define PCI_STATCMD_STATUS(x)  (((x) & 0xffff) << 16)
-#define PCI_STATCMD_CMD(x)     ((x) & 0xffff)
-#define PCI_CLASSREV_CLASS(x)  (((x) & 0x00ffffff) << 8)
-#define PCI_CLASSREV_REV(x)    ((x) & 0xff)
-#define PCI_PARAM_BIST(x)      (((x) & 0xff) << 24)
-#define PCI_PARAM_HT(x)                (((x) & 0xff) << 16)
-#define PCI_PARAM_LT(x)                (((x) & 0xff) << 8)
-#define PCI_PARAM_CLS(x)       ((x) & 0xff)
-#define PCI_TIMEOUT_RETRIES(x) (((x) & 0xff) << 8)     /* max retries */
-#define PCI_TIMEOUT_TO(x)      ((x) & 0xff)    /* target ready timeout */
+       AU1100_TOY_INT          = AU1100_FIRST_INT + 14,
+       AU1100_TOY_MATCH0_INT,
+       AU1100_TOY_MATCH1_INT,
+       AU1100_TOY_MATCH2_INT,
+       AU1100_RTC_INT,
+       AU1100_RTC_MATCH0_INT,
+       AU1100_RTC_MATCH1_INT,
+       AU1100_RTC_MATCH2_INT,
+       AU1100_IRDA_TX_INT,
+       AU1100_IRDA_RX_INT,
+       AU1100_USB_DEV_REQ_INT,
+       AU1100_USB_DEV_SUS_INT,
+       AU1100_USB_HOST_INT,
+       AU1100_ACSYNC_INT,
+       AU1100_MAC0_DMA_INT,
+       AU1100_GPIO208_215_INT,
+       AU1100_LCD_INT,
+       AU1100_AC97C_INT,
+       AU1100_GPIO0_INT,
+       AU1100_GPIO1_INT,
+       AU1100_GPIO2_INT,
+       AU1100_GPIO3_INT,
+       AU1100_GPIO4_INT,
+       AU1100_GPIO5_INT,
+       AU1100_GPIO6_INT,
+       AU1100_GPIO7_INT,
+       AU1100_GPIO8_INT,
+       AU1100_GPIO9_INT,
+       AU1100_GPIO10_INT,
+       AU1100_GPIO11_INT,
+       AU1100_GPIO12_INT,
+       AU1100_GPIO13_INT,
+       AU1100_GPIO14_INT,
+       AU1100_GPIO15_INT,
+       AU1100_GPIO16_INT,
+       AU1100_GPIO17_INT,
+       AU1100_GPIO18_INT,
+       AU1100_GPIO19_INT,
+       AU1100_GPIO20_INT,
+       AU1100_GPIO21_INT,
+       AU1100_GPIO22_INT,
+       AU1100_GPIO23_INT,
+       AU1100_GPIO24_INT,
+       AU1100_GPIO25_INT,
+       AU1100_GPIO26_INT,
+       AU1100_GPIO27_INT,
+       AU1100_GPIO28_INT,
+       AU1100_GPIO29_INT,
+       AU1100_GPIO30_INT,
+       AU1100_GPIO31_INT,
+};
+
+enum soc_au1500_ints {
+       AU1500_FIRST_INT        = AU1000_INTC0_INT_BASE,
+       AU1500_UART0_INT        = AU1500_FIRST_INT,
+       AU1500_PCI_INTA,
+       AU1500_PCI_INTB,
+       AU1500_UART3_INT,
+       AU1500_PCI_INTC,
+       AU1500_PCI_INTD,
+       AU1500_DMA_INT_BASE,
+
+       AU1500_TOY_INT          = AU1500_FIRST_INT + 14,
+       AU1500_TOY_MATCH0_INT,
+       AU1500_TOY_MATCH1_INT,
+       AU1500_TOY_MATCH2_INT,
+       AU1500_RTC_INT,
+       AU1500_RTC_MATCH0_INT,
+       AU1500_RTC_MATCH1_INT,
+       AU1500_RTC_MATCH2_INT,
+       AU1500_PCI_ERR_INT,
+       AU1500_RESERVED_INT,
+       AU1500_USB_DEV_REQ_INT,
+       AU1500_USB_DEV_SUS_INT,
+       AU1500_USB_HOST_INT,
+       AU1500_ACSYNC_INT,
+       AU1500_MAC0_DMA_INT,
+       AU1500_MAC1_DMA_INT,
+       AU1500_AC97C_INT        = AU1500_FIRST_INT + 31,
+       AU1500_GPIO0_INT,
+       AU1500_GPIO1_INT,
+       AU1500_GPIO2_INT,
+       AU1500_GPIO3_INT,
+       AU1500_GPIO4_INT,
+       AU1500_GPIO5_INT,
+       AU1500_GPIO6_INT,
+       AU1500_GPIO7_INT,
+       AU1500_GPIO8_INT,
+       AU1500_GPIO9_INT,
+       AU1500_GPIO10_INT,
+       AU1500_GPIO11_INT,
+       AU1500_GPIO12_INT,
+       AU1500_GPIO13_INT,
+       AU1500_GPIO14_INT,
+       AU1500_GPIO15_INT,
+       AU1500_GPIO200_INT,
+       AU1500_GPIO201_INT,
+       AU1500_GPIO202_INT,
+       AU1500_GPIO203_INT,
+       AU1500_GPIO20_INT,
+       AU1500_GPIO204_INT,
+       AU1500_GPIO205_INT,
+       AU1500_GPIO23_INT,
+       AU1500_GPIO24_INT,
+       AU1500_GPIO25_INT,
+       AU1500_GPIO26_INT,
+       AU1500_GPIO27_INT,
+       AU1500_GPIO28_INT,
+       AU1500_GPIO206_INT,
+       AU1500_GPIO207_INT,
+       AU1500_GPIO208_215_INT,
+};
+
+enum soc_au1550_ints {
+       AU1550_FIRST_INT        = AU1000_INTC0_INT_BASE,
+       AU1550_UART0_INT        = AU1550_FIRST_INT,
+       AU1550_PCI_INTA,
+       AU1550_PCI_INTB,
+       AU1550_DDMA_INT,
+       AU1550_CRYPTO_INT,
+       AU1550_PCI_INTC,
+       AU1550_PCI_INTD,
+       AU1550_PCI_RST_INT,
+       AU1550_UART1_INT,
+       AU1550_UART3_INT,
+       AU1550_PSC0_INT,
+       AU1550_PSC1_INT,
+       AU1550_PSC2_INT,
+       AU1550_PSC3_INT,
+       AU1550_TOY_INT,
+       AU1550_TOY_MATCH0_INT,
+       AU1550_TOY_MATCH1_INT,
+       AU1550_TOY_MATCH2_INT,
+       AU1550_RTC_INT,
+       AU1550_RTC_MATCH0_INT,
+       AU1550_RTC_MATCH1_INT,
+       AU1550_RTC_MATCH2_INT,
+
+       AU1550_NAND_INT         = AU1550_FIRST_INT + 23,
+       AU1550_USB_DEV_REQ_INT,
+       AU1550_USB_DEV_SUS_INT,
+       AU1550_USB_HOST_INT,
+       AU1550_MAC0_DMA_INT,
+       AU1550_MAC1_DMA_INT,
+       AU1550_GPIO0_INT        = AU1550_FIRST_INT + 32,
+       AU1550_GPIO1_INT,
+       AU1550_GPIO2_INT,
+       AU1550_GPIO3_INT,
+       AU1550_GPIO4_INT,
+       AU1550_GPIO5_INT,
+       AU1550_GPIO6_INT,
+       AU1550_GPIO7_INT,
+       AU1550_GPIO8_INT,
+       AU1550_GPIO9_INT,
+       AU1550_GPIO10_INT,
+       AU1550_GPIO11_INT,
+       AU1550_GPIO12_INT,
+       AU1550_GPIO13_INT,
+       AU1550_GPIO14_INT,
+       AU1550_GPIO15_INT,
+       AU1550_GPIO200_INT,
+       AU1550_GPIO201_205_INT, /* Logical or of GPIO201:205 */
+       AU1550_GPIO16_INT,
+       AU1550_GPIO17_INT,
+       AU1550_GPIO20_INT,
+       AU1550_GPIO21_INT,
+       AU1550_GPIO22_INT,
+       AU1550_GPIO23_INT,
+       AU1550_GPIO24_INT,
+       AU1550_GPIO25_INT,
+       AU1550_GPIO26_INT,
+       AU1550_GPIO27_INT,
+       AU1550_GPIO28_INT,
+       AU1550_GPIO206_INT,
+       AU1550_GPIO207_INT,
+       AU1550_GPIO208_215_INT, /* Logical or of GPIO208:215 */
+};
+
+enum soc_au1200_ints {
+       AU1200_FIRST_INT        = AU1000_INTC0_INT_BASE,
+       AU1200_UART0_INT        = AU1200_FIRST_INT,
+       AU1200_SWT_INT,
+       AU1200_SD_INT,
+       AU1200_DDMA_INT,
+       AU1200_MAE_BE_INT,
+       AU1200_GPIO200_INT,
+       AU1200_GPIO201_INT,
+       AU1200_GPIO202_INT,
+       AU1200_UART1_INT,
+       AU1200_MAE_FE_INT,
+       AU1200_PSC0_INT,
+       AU1200_PSC1_INT,
+       AU1200_AES_INT,
+       AU1200_CAMERA_INT,
+       AU1200_TOY_INT,
+       AU1200_TOY_MATCH0_INT,
+       AU1200_TOY_MATCH1_INT,
+       AU1200_TOY_MATCH2_INT,
+       AU1200_RTC_INT,
+       AU1200_RTC_MATCH0_INT,
+       AU1200_RTC_MATCH1_INT,
+       AU1200_RTC_MATCH2_INT,
+       AU1200_GPIO203_INT,
+       AU1200_NAND_INT,
+       AU1200_GPIO204_INT,
+       AU1200_GPIO205_INT,
+       AU1200_GPIO206_INT,
+       AU1200_GPIO207_INT,
+       AU1200_GPIO208_215_INT, /* Logical OR of 208:215 */
+       AU1200_USB_INT,
+       AU1200_LCD_INT,
+       AU1200_MAE_BOTH_INT,
+       AU1200_GPIO0_INT,
+       AU1200_GPIO1_INT,
+       AU1200_GPIO2_INT,
+       AU1200_GPIO3_INT,
+       AU1200_GPIO4_INT,
+       AU1200_GPIO5_INT,
+       AU1200_GPIO6_INT,
+       AU1200_GPIO7_INT,
+       AU1200_GPIO8_INT,
+       AU1200_GPIO9_INT,
+       AU1200_GPIO10_INT,
+       AU1200_GPIO11_INT,
+       AU1200_GPIO12_INT,
+       AU1200_GPIO13_INT,
+       AU1200_GPIO14_INT,
+       AU1200_GPIO15_INT,
+       AU1200_GPIO16_INT,
+       AU1200_GPIO17_INT,
+       AU1200_GPIO18_INT,
+       AU1200_GPIO19_INT,
+       AU1200_GPIO20_INT,
+       AU1200_GPIO21_INT,
+       AU1200_GPIO22_INT,
+       AU1200_GPIO23_INT,
+       AU1200_GPIO24_INT,
+       AU1200_GPIO25_INT,
+       AU1200_GPIO26_INT,
+       AU1200_GPIO27_INT,
+       AU1200_GPIO28_INT,
+       AU1200_GPIO29_INT,
+       AU1200_GPIO30_INT,
+       AU1200_GPIO31_INT,
+};
+
+#endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
 #endif
index 7cedca5..0a0cd42 100644 (file)
@@ -106,7 +106,7 @@ enum {
 struct dma_chan {
        int dev_id;             /* this channel is allocated if >= 0, */
                                /* free otherwise */
-       unsigned int io;
+       void __iomem *io;
        const char *dev_str;
        int irq;
        void *irq_dev;
@@ -157,7 +157,7 @@ static inline void enable_dma_buffer0(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
+       __raw_writel(DMA_BE0, chan->io + DMA_MODE_SET);
 }
 
 static inline void enable_dma_buffer1(unsigned int dmanr)
@@ -166,7 +166,7 @@ static inline void enable_dma_buffer1(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
+       __raw_writel(DMA_BE1, chan->io + DMA_MODE_SET);
 }
 static inline void enable_dma_buffers(unsigned int dmanr)
 {
@@ -174,7 +174,7 @@ static inline void enable_dma_buffers(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
+       __raw_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
 }
 
 static inline void start_dma(unsigned int dmanr)
@@ -183,7 +183,7 @@ static inline void start_dma(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_GO, chan->io + DMA_MODE_SET);
+       __raw_writel(DMA_GO, chan->io + DMA_MODE_SET);
 }
 
 #define DMA_HALT_POLL 0x5000
@@ -195,11 +195,11 @@ static inline void halt_dma(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
+       __raw_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
 
        /* Poll the halt bit */
        for (i = 0; i < DMA_HALT_POLL; i++)
-               if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
+               if (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
                        break;
        if (i == DMA_HALT_POLL)
                printk(KERN_INFO "halt_dma: HALT poll expired!\n");
@@ -215,7 +215,7 @@ static inline void disable_dma(unsigned int dmanr)
        halt_dma(dmanr);
 
        /* Now we can disable the buffers */
-       au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
+       __raw_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline int dma_halted(unsigned int dmanr)
@@ -224,7 +224,7 @@ static inline int dma_halted(unsigned int dmanr)
 
        if (!chan)
                return 1;
-       return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
+       return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
 }
 
 /* Initialize a DMA channel. */
@@ -239,14 +239,14 @@ static inline void init_dma(unsigned int dmanr)
        disable_dma(dmanr);
 
        /* Set device FIFO address */
-       au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
+       __raw_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
 
        mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
        if (chan->irq)
                mode |= DMA_IE;
 
-       au_writel(~mode, chan->io + DMA_MODE_CLEAR);
-       au_writel(mode,  chan->io + DMA_MODE_SET);
+       __raw_writel(~mode, chan->io + DMA_MODE_CLEAR);
+       __raw_writel(mode,       chan->io + DMA_MODE_SET);
 }
 
 /*
@@ -283,7 +283,7 @@ static inline int get_dma_active_buffer(unsigned int dmanr)
 
        if (!chan)
                return -1;
-       return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
+       return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
 }
 
 /*
@@ -304,7 +304,7 @@ static inline void set_dma_fifo_addr(unsigned int dmanr, unsigned int a)
        if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
                return;
 
-       au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
+       __raw_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
 }
 
 /*
@@ -316,7 +316,7 @@ static inline void clear_dma_done0(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
+       __raw_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline void clear_dma_done1(unsigned int dmanr)
@@ -325,7 +325,7 @@ static inline void clear_dma_done1(unsigned int dmanr)
 
        if (!chan)
                return;
-       au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
+       __raw_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
 }
 
 /*
@@ -344,7 +344,7 @@ static inline void set_dma_addr0(unsigned int dmanr, unsigned int a)
 
        if (!chan)
                return;
-       au_writel(a, chan->io + DMA_BUFFER0_START);
+       __raw_writel(a, chan->io + DMA_BUFFER0_START);
 }
 
 /*
@@ -356,7 +356,7 @@ static inline void set_dma_addr1(unsigned int dmanr, unsigned int a)
 
        if (!chan)
                return;
-       au_writel(a, chan->io + DMA_BUFFER1_START);
+       __raw_writel(a, chan->io + DMA_BUFFER1_START);
 }
 
 
@@ -370,7 +370,7 @@ static inline void set_dma_count0(unsigned int dmanr, unsigned int count)
        if (!chan)
                return;
        count &= DMA_COUNT_MASK;
-       au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+       __raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
 }
 
 /*
@@ -383,7 +383,7 @@ static inline void set_dma_count1(unsigned int dmanr, unsigned int count)
        if (!chan)
                return;
        count &= DMA_COUNT_MASK;
-       au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+       __raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -396,8 +396,8 @@ static inline void set_dma_count(unsigned int dmanr, unsigned int count)
        if (!chan)
                return;
        count &= DMA_COUNT_MASK;
-       au_writel(count, chan->io + DMA_BUFFER0_COUNT);
-       au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+       __raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
+       __raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -410,7 +410,7 @@ static inline unsigned int get_dma_buffer_done(unsigned int dmanr)
 
        if (!chan)
                return 0;
-       return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
+       return __raw_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
 }
 
 
@@ -437,10 +437,10 @@ static inline int get_dma_residue(unsigned int dmanr)
        if (!chan)
                return 0;
 
-       curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
+       curBufCntReg = (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
            DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
 
-       count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
+       count = __raw_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
 
        if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
                count <<= 1;
index 796afd0..9785e4e 100644 (file)
 #define MAKE_IRQ(intc, off)    (AU1000_INTC##intc##_INT_BASE + (off))
 
 /* GPIO1 registers within SYS_ area */
-#define SYS_TRIOUTRD           0x100
-#define SYS_TRIOUTCLR          0x100
-#define SYS_OUTPUTRD           0x108
-#define SYS_OUTPUTSET          0x108
-#define SYS_OUTPUTCLR          0x10C
-#define SYS_PINSTATERD         0x110
-#define SYS_PININPUTEN         0x110
+#define AU1000_SYS_TRIOUTRD    0x100
+#define AU1000_SYS_TRIOUTCLR   0x100
+#define AU1000_SYS_OUTPUTRD    0x108
+#define AU1000_SYS_OUTPUTSET   0x108
+#define AU1000_SYS_OUTPUTCLR   0x10C
+#define AU1000_SYS_PINSTATERD  0x110
+#define AU1000_SYS_PININPUTEN  0x110
 
 /* register offsets within GPIO2 block */
-#define GPIO2_DIR              0x00
-#define GPIO2_OUTPUT           0x08
-#define GPIO2_PINSTATE         0x0C
-#define GPIO2_INTENABLE                0x10
-#define GPIO2_ENABLE           0x14
+#define AU1000_GPIO2_DIR       0x00
+#define AU1000_GPIO2_OUTPUT    0x08
+#define AU1000_GPIO2_PINSTATE  0x0C
+#define AU1000_GPIO2_INTENABLE 0x10
+#define AU1000_GPIO2_ENABLE    0x14
 
 struct gpio;
 
@@ -217,26 +217,21 @@ static inline int au1200_irq_to_gpio(int irq)
  */
 static inline void alchemy_gpio1_set_value(int gpio, int v)
 {
-       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-       unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
-       __raw_writel(mask, base + r);
-       wmb();
+       unsigned long r = v ? AU1000_SYS_OUTPUTSET : AU1000_SYS_OUTPUTCLR;
+       alchemy_wrsys(mask, r);
 }
 
 static inline int alchemy_gpio1_get_value(int gpio)
 {
-       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-       return __raw_readl(base + SYS_PINSTATERD) & mask;
+       return alchemy_rdsys(AU1000_SYS_PINSTATERD) & mask;
 }
 
 static inline int alchemy_gpio1_direction_input(int gpio)
 {
-       void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-       __raw_writel(mask, base + SYS_TRIOUTCLR);
-       wmb();
+       alchemy_wrsys(mask, AU1000_SYS_TRIOUTCLR);
        return 0;
 }
 
@@ -279,13 +274,13 @@ static inline void __alchemy_gpio2_mod_dir(int gpio, int to_out)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
        unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
-       unsigned long d = __raw_readl(base + GPIO2_DIR);
+       unsigned long d = __raw_readl(base + AU1000_GPIO2_DIR);
 
        if (to_out)
                d |= mask;
        else
                d &= ~mask;
-       __raw_writel(d, base + GPIO2_DIR);
+       __raw_writel(d, base + AU1000_GPIO2_DIR);
        wmb();
 }
 
@@ -294,14 +289,15 @@ static inline void alchemy_gpio2_set_value(int gpio, int v)
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
        unsigned long mask;
        mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
-       __raw_writel(mask, base + GPIO2_OUTPUT);
+       __raw_writel(mask, base + AU1000_GPIO2_OUTPUT);
        wmb();
 }
 
 static inline int alchemy_gpio2_get_value(int gpio)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-       return __raw_readl(base + GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+       return __raw_readl(base + AU1000_GPIO2_PINSTATE) &
+                               (1 << (gpio - ALCHEMY_GPIO2_BASE));
 }
 
 static inline int alchemy_gpio2_direction_input(int gpio)
@@ -352,12 +348,12 @@ static inline int alchemy_gpio2_to_irq(int gpio)
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-       unsigned long r = __raw_readl(base + GPIO2_INTENABLE);
+       unsigned long r = __raw_readl(base + AU1000_GPIO2_INTENABLE);
        if (en)
                r |= 1 << gpio2;
        else
                r &= ~(1 << gpio2);
-       __raw_writel(r, base + GPIO2_INTENABLE);
+       __raw_writel(r, base + AU1000_GPIO2_INTENABLE);
        wmb();
 }
 
@@ -434,9 +430,9 @@ static inline void alchemy_gpio2_disable_int(int gpio2)
 static inline void alchemy_gpio2_enable(void)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-       __raw_writel(3, base + GPIO2_ENABLE);   /* reset, clock enabled */
+       __raw_writel(3, base + AU1000_GPIO2_ENABLE);    /* reset, clock enabled */
        wmb();
-       __raw_writel(1, base + GPIO2_ENABLE);   /* clock enabled */
+       __raw_writel(1, base + AU1000_GPIO2_ENABLE);    /* clock enabled */
        wmb();
 }
 
@@ -448,7 +444,7 @@ static inline void alchemy_gpio2_enable(void)
 static inline void alchemy_gpio2_disable(void)
 {
        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-       __raw_writel(2, base + GPIO2_ENABLE);   /* reset, clock disabled */
+       __raw_writel(2, base + AU1000_GPIO2_ENABLE);    /* reset, clock disabled */
        wmb();
 }
 
index bba7399..1f5643b 100644 (file)
@@ -18,6 +18,7 @@ enum bcm47xx_board {
        BCM47XX_BOARD_ASUS_WL300G,
        BCM47XX_BOARD_ASUS_WL320GE,
        BCM47XX_BOARD_ASUS_WL330GE,
+       BCM47XX_BOARD_ASUS_WL500G,
        BCM47XX_BOARD_ASUS_WL500GD,
        BCM47XX_BOARD_ASUS_WL500GPV1,
        BCM47XX_BOARD_ASUS_WL500GPV2,
@@ -70,11 +71,15 @@ enum bcm47xx_board {
        BCM47XX_BOARD_LINKSYS_WRT310NV1,
        BCM47XX_BOARD_LINKSYS_WRT310NV2,
        BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
-       BCM47XX_BOARD_LINKSYS_WRT54G,
+       BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
+       BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
+       BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
        BCM47XX_BOARD_LINKSYS_WRT610NV1,
        BCM47XX_BOARD_LINKSYS_WRT610NV2,
        BCM47XX_BOARD_LINKSYS_WRTSL54GS,
 
+       BCM47XX_BOARD_MICROSOFT_MN700,
+
        BCM47XX_BOARD_MOTOROLA_WE800G,
        BCM47XX_BOARD_MOTOROLA_WR850GP,
        BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
index 3112f08..56bb192 100644 (file)
 #define BCM6368_CPU_ID         0x6368
 
 void __init bcm63xx_cpu_init(void);
-u16 __bcm63xx_get_cpu_id(void);
 u8 bcm63xx_get_cpu_rev(void);
 unsigned int bcm63xx_get_cpu_freq(void);
 
+static inline u16 __pure __bcm63xx_get_cpu_id(const u16 cpu_id)
+{
+       switch (cpu_id) {
 #ifdef CONFIG_BCM63XX_CPU_3368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM3368_CPU_ID
-# endif
-# define BCMCPU_IS_3368()      (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
-#else
-# define BCMCPU_IS_3368()      (0)
+               case BCM3368_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6328
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6328_CPU_ID
-# endif
-# define BCMCPU_IS_6328()      (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
-#else
-# define BCMCPU_IS_6328()      (0)
+               case BCM6328_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6338
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6338_CPU_ID
-# endif
-# define BCMCPU_IS_6338()      (bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
-#else
-# define BCMCPU_IS_6338()      (0)
+               case BCM6338_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6345
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6345_CPU_ID
-# endif
-# define BCMCPU_IS_6345()      (bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
-#else
-# define BCMCPU_IS_6345()      (0)
+               case BCM6345_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6348
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6348_CPU_ID
-# endif
-# define BCMCPU_IS_6348()      (bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
-#else
-# define BCMCPU_IS_6348()      (0)
+               case BCM6348_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6358
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6358_CPU_ID
-# endif
-# define BCMCPU_IS_6358()      (bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
-#else
-# define BCMCPU_IS_6358()      (0)
+               case BCM6358_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6362
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6362_CPU_ID
-# endif
-# define BCMCPU_IS_6362()      (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
-#else
-# define BCMCPU_IS_6362()      (0)
+               case BCM6362_CPU_ID:
 #endif
 
-
 #ifdef CONFIG_BCM63XX_CPU_6368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id() BCM6368_CPU_ID
-# endif
-# define BCMCPU_IS_6368()      (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
-#else
-# define BCMCPU_IS_6368()      (0)
+               case BCM6368_CPU_ID:
 #endif
+               break;
+       default:
+               unreachable();
+       }
 
-#ifndef bcm63xx_get_cpu_id
-#error "No CPU support configured"
-#endif
+       return cpu_id;
+}
+
+extern u16 bcm63xx_cpu_id;
+
+static inline u16 __pure bcm63xx_get_cpu_id(void)
+{
+       const u16 cpu_id = bcm63xx_cpu_id;
+
+       return __bcm63xx_get_cpu_id(cpu_id);
+}
+
+#define BCMCPU_IS_3368()       (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#define BCMCPU_IS_6328()       (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
+#define BCMCPU_IS_6338()       (bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
+#define BCMCPU_IS_6345()       (bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
+#define BCMCPU_IS_6348()       (bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
+#define BCMCPU_IS_6358()       (bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
+#define BCMCPU_IS_6362()       (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
+#define BCMCPU_IS_6368()       (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
 
 /*
  * While registers sets are (mostly) the same across 63xx CPU, base
@@ -598,55 +548,6 @@ enum bcm63xx_regs_set {
 
 extern const unsigned long *bcm63xx_regs_base;
 
-#define __GEN_RSET_BASE(__cpu, __rset)                                 \
-       case RSET_## __rset :                                           \
-               return BCM_## __cpu ##_## __rset ##_BASE;
-
-#define __GEN_RSET(__cpu)                                              \
-       switch (set) {                                                  \
-       __GEN_RSET_BASE(__cpu, DSL_LMEM)                                \
-       __GEN_RSET_BASE(__cpu, PERF)                                    \
-       __GEN_RSET_BASE(__cpu, TIMER)                                   \
-       __GEN_RSET_BASE(__cpu, WDT)                                     \
-       __GEN_RSET_BASE(__cpu, UART0)                                   \
-       __GEN_RSET_BASE(__cpu, UART1)                                   \
-       __GEN_RSET_BASE(__cpu, GPIO)                                    \
-       __GEN_RSET_BASE(__cpu, SPI)                                     \
-       __GEN_RSET_BASE(__cpu, HSSPI)                                   \
-       __GEN_RSET_BASE(__cpu, UDC0)                                    \
-       __GEN_RSET_BASE(__cpu, OHCI0)                                   \
-       __GEN_RSET_BASE(__cpu, OHCI_PRIV)                               \
-       __GEN_RSET_BASE(__cpu, USBH_PRIV)                               \
-       __GEN_RSET_BASE(__cpu, USBD)                                    \
-       __GEN_RSET_BASE(__cpu, USBDMA)                                  \
-       __GEN_RSET_BASE(__cpu, MPI)                                     \
-       __GEN_RSET_BASE(__cpu, PCMCIA)                                  \
-       __GEN_RSET_BASE(__cpu, PCIE)                                    \
-       __GEN_RSET_BASE(__cpu, DSL)                                     \
-       __GEN_RSET_BASE(__cpu, ENET0)                                   \
-       __GEN_RSET_BASE(__cpu, ENET1)                                   \
-       __GEN_RSET_BASE(__cpu, ENETDMA)                                 \
-       __GEN_RSET_BASE(__cpu, ENETDMAC)                                \
-       __GEN_RSET_BASE(__cpu, ENETDMAS)                                \
-       __GEN_RSET_BASE(__cpu, ENETSW)                                  \
-       __GEN_RSET_BASE(__cpu, EHCI0)                                   \
-       __GEN_RSET_BASE(__cpu, SDRAM)                                   \
-       __GEN_RSET_BASE(__cpu, MEMC)                                    \
-       __GEN_RSET_BASE(__cpu, DDR)                                     \
-       __GEN_RSET_BASE(__cpu, M2M)                                     \
-       __GEN_RSET_BASE(__cpu, ATM)                                     \
-       __GEN_RSET_BASE(__cpu, XTM)                                     \
-       __GEN_RSET_BASE(__cpu, XTMDMA)                                  \
-       __GEN_RSET_BASE(__cpu, XTMDMAC)                                 \
-       __GEN_RSET_BASE(__cpu, XTMDMAS)                                 \
-       __GEN_RSET_BASE(__cpu, PCM)                                     \
-       __GEN_RSET_BASE(__cpu, PCMDMA)                                  \
-       __GEN_RSET_BASE(__cpu, PCMDMAC)                                 \
-       __GEN_RSET_BASE(__cpu, PCMDMAS)                                 \
-       __GEN_RSET_BASE(__cpu, RNG)                                     \
-       __GEN_RSET_BASE(__cpu, MISC)                                    \
-       }
-
 #define __GEN_CPU_REGS_TABLE(__cpu)                                    \
        [RSET_DSL_LMEM]         = BCM_## __cpu ##_DSL_LMEM_BASE,        \
        [RSET_PERF]             = BCM_## __cpu ##_PERF_BASE,            \
@@ -693,36 +594,7 @@ extern const unsigned long *bcm63xx_regs_base;
 
 static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
        return bcm63xx_regs_base[set];
-#else
-#ifdef CONFIG_BCM63XX_CPU_3368
-       __GEN_RSET(3368)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-       __GEN_RSET(6328)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-       __GEN_RSET(6338)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-       __GEN_RSET(6345)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-       __GEN_RSET(6348)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-       __GEN_RSET(6358)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-       __GEN_RSET(6362)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-       __GEN_RSET(6368)
-#endif
-#endif
-       /* unreached */
-       return 0;
 }
 
 /*
index 753953e..466fc85 100644 (file)
@@ -112,55 +112,9 @@ enum bcm63xx_regs_enetdmac {
 
 static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
        extern const unsigned long *bcm63xx_regs_enetdmac;
 
        return bcm63xx_regs_enetdmac[reg];
-#else
-#ifdef CONFIG_BCM63XX_CPU_6345
-       switch (reg) {
-       case ENETDMAC_CHANCFG:
-               return ENETDMA_6345_CHANCFG_REG;
-       case ENETDMAC_IR:
-               return ENETDMA_6345_IR_REG;
-       case ENETDMAC_IRMASK:
-               return ENETDMA_6345_IRMASK_REG;
-       case ENETDMAC_MAXBURST:
-               return ENETDMA_6345_MAXBURST_REG;
-       case ENETDMAC_BUFALLOC:
-               return ENETDMA_6345_BUFALLOC_REG;
-       case ENETDMAC_RSTART:
-               return ENETDMA_6345_RSTART_REG;
-       case ENETDMAC_FC:
-               return ENETDMA_6345_FC_REG;
-       case ENETDMAC_LEN:
-               return ENETDMA_6345_LEN_REG;
-       }
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6328) || \
-       defined(CONFIG_BCM63XX_CPU_6338) || \
-       defined(CONFIG_BCM63XX_CPU_6348) || \
-       defined(CONFIG_BCM63XX_CPU_6358) || \
-       defined(CONFIG_BCM63XX_CPU_6362) || \
-       defined(CONFIG_BCM63XX_CPU_6368)
-       switch (reg) {
-       case ENETDMAC_CHANCFG:
-               return ENETDMAC_CHANCFG_REG;
-       case ENETDMAC_IR:
-               return ENETDMAC_IR_REG;
-       case ENETDMAC_IRMASK:
-               return ENETDMAC_IRMASK_REG;
-       case ENETDMAC_MAXBURST:
-               return ENETDMAC_MAXBURST_REG;
-       case ENETDMAC_BUFALLOC:
-       case ENETDMAC_RSTART:
-       case ENETDMAC_FC:
-       case ENETDMAC_LEN:
-               return 0;
-       }
-#endif
-#endif
-       return 0;
 }
 
 
index c426cab..2573765 100644 (file)
@@ -30,26 +30,6 @@ enum bcm63xx_regs_spi {
        SPI_RX_DATA,
 };
 
-#define __GEN_SPI_RSET_BASE(__cpu, __rset)                             \
-       case SPI_## __rset:                                             \
-               return SPI_## __cpu ##_## __rset;
-
-#define __GEN_SPI_RSET(__cpu)                                          \
-       switch (reg) {                                                  \
-       __GEN_SPI_RSET_BASE(__cpu, CMD)                                 \
-       __GEN_SPI_RSET_BASE(__cpu, INT_STATUS)                          \
-       __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST)                         \
-       __GEN_SPI_RSET_BASE(__cpu, INT_MASK)                            \
-       __GEN_SPI_RSET_BASE(__cpu, ST)                                  \
-       __GEN_SPI_RSET_BASE(__cpu, CLK_CFG)                             \
-       __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE)                           \
-       __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL)                            \
-       __GEN_SPI_RSET_BASE(__cpu, RX_TAIL)                             \
-       __GEN_SPI_RSET_BASE(__cpu, MSG_CTL)                             \
-       __GEN_SPI_RSET_BASE(__cpu, MSG_DATA)                            \
-       __GEN_SPI_RSET_BASE(__cpu, RX_DATA)                             \
-       }
-
 #define __GEN_SPI_REGS_TABLE(__cpu)                                    \
        [SPI_CMD]               = SPI_## __cpu ##_CMD,                  \
        [SPI_INT_STATUS]        = SPI_## __cpu ##_INT_STATUS,           \
@@ -66,20 +46,9 @@ enum bcm63xx_regs_spi {
 
 static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
        extern const unsigned long *bcm63xx_regs_spi;
 
        return bcm63xx_regs_spi[reg];
-#else
-#if defined(CONFIG_BCM63XX_CPU_6338) || defined(CONFIG_BCM63XX_CPU_6348)
-       __GEN_SPI_RSET(6348)
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6358) || defined(CONFIG_BCM63XX_CPU_6362) || \
-       defined(CONFIG_BCM63XX_CPU_6368)
-       __GEN_SPI_RSET(6358)
-#endif
-#endif
-       return 0;
 }
 
 #endif /* BCM63XX_DEV_SPI_H */
index ab427f8..4794067 100644 (file)
 
 /* Interrupt Mask register */
 #define PERF_IRQMASK_3368_REG          0xc
-#define PERF_IRQMASK_6328_REG          0x20
+#define PERF_IRQMASK_6328_REG(x)       (0x20 + (x) * 0x10)
 #define PERF_IRQMASK_6338_REG          0xc
 #define PERF_IRQMASK_6345_REG          0xc
 #define PERF_IRQMASK_6348_REG          0xc
-#define PERF_IRQMASK_6358_REG          0xc
-#define PERF_IRQMASK_6362_REG          0x20
-#define PERF_IRQMASK_6368_REG          0x20
+#define PERF_IRQMASK_6358_REG(x)       (0xc + (x) * 0x2c)
+#define PERF_IRQMASK_6362_REG(x)       (0x20 + (x) * 0x10)
+#define PERF_IRQMASK_6368_REG(x)       (0x20 + (x) * 0x10)
 
 /* Interrupt Status register */
 #define PERF_IRQSTAT_3368_REG          0x10
-#define PERF_IRQSTAT_6328_REG          0x28
+#define PERF_IRQSTAT_6328_REG(x)       (0x28 + (x) * 0x10)
 #define PERF_IRQSTAT_6338_REG          0x10
 #define PERF_IRQSTAT_6345_REG          0x10
 #define PERF_IRQSTAT_6348_REG          0x10
-#define PERF_IRQSTAT_6358_REG          0x10
-#define PERF_IRQSTAT_6362_REG          0x28
-#define PERF_IRQSTAT_6368_REG          0x28
+#define PERF_IRQSTAT_6358_REG(x)       (0x10 + (x) * 0x2c)
+#define PERF_IRQSTAT_6362_REG(x)       (0x28 + (x) * 0x10)
+#define PERF_IRQSTAT_6368_REG(x)       (0x28 + (x) * 0x10)
 
 /* External Interrupt Configuration register */
 #define PERF_EXTIRQ_CFG_REG_3368       0x14
index e9c408e..bc1167d 100644 (file)
@@ -24,7 +24,7 @@
 #define cpu_has_smartmips              0
 #define cpu_has_vtag_icache            0
 
-#if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCM63XX_CPU_6348) || defined(CONFIG_BCM63XX_CPU_6345) || defined(CONFIG_BCM63XX_CPU_6338))
+#if !defined(CONFIG_SYS_HAS_CPU_BMIPS4350)
 #define cpu_has_dc_aliases             0
 #endif
 
index 829a7ec..3388fc5 100644 (file)
@@ -146,6 +146,9 @@ struct boot_params {
 
 struct loongson_system_configuration {
        u32 nr_cpus;
+       u32 nr_nodes;
+       int cores_per_node;
+       int cores_per_package;
        enum loongson_cpu_type cputype;
        u64 ht_control_base;
        u64 pci_mem_start_addr;
@@ -160,4 +163,5 @@ struct loongson_system_configuration {
 
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
+extern int cpuhotplug_workaround;
 #endif
diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
new file mode 100644 (file)
index 0000000..df5fca8
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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 Embedded Alley Solutions, Inc
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
+ */
+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+
+/*
+ * Override macros used in arch/mips/kernel/head.S.
+ */
+       .macro  kernel_entry_setup
+#ifdef CONFIG_CPU_LOONGSON3
+       .set    push
+       .set    mips64
+       /* Set LPA on LOONGSON3 config3 */
+       mfc0    t0, $16, 3
+       or      t0, (0x1 << 7)
+       mtc0    t0, $16, 3
+       /* Set ELPA on LOONGSON3 pagegrain */
+       li      t0, (0x1 << 29)
+       mtc0    t0, $5, 1
+       _ehb
+       .set    pop
+#endif
+       .endm
+
+/*
+ * Do SMP slave processor setup.
+ */
+       .macro  smp_slave_setup
+#ifdef CONFIG_CPU_LOONGSON3
+       .set    push
+       .set    mips64
+       /* Set LPA on LOONGSON3 config3 */
+       mfc0    t0, $16, 3
+       or      t0, (0x1 << 7)
+       mtc0    t0, $16, 3
+       /* Set ELPA on LOONGSON3 pagegrain */
+       li      t0, (0x1 << 29)
+       mtc0    t0, $5, 1
+       _ehb
+       .set    pop
+#endif
+       .endm
+
+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
index f3fd1eb..92bf76c 100644 (file)
@@ -249,8 +249,15 @@ static inline void do_perfcnt_IRQ(void)
 #define LOONGSON_PXARB_CFG             LOONGSON_REG(LOONGSON_REGBASE + 0x68)
 #define LOONGSON_PXARB_STATUS          LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
 
-/* Chip Config */
-#define LOONGSON_CHIPCFG0              LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#define MAX_PACKAGES 4
+
+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
+extern u64 loongson_chipcfg[MAX_PACKAGES];
+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
+
+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
+extern u64 loongson_freqctrl[MAX_PACKAGES];
+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
 
 /* pcimap */
 
index 1b1f592..228e378 100644 (file)
 
 #endif
 
-#ifdef CONFIG_LEMOTE_MACH3A
+#ifdef CONFIG_LOONGSON_MACH3X
 
 #define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
 
-#endif /* CONFIG_LEMOTE_MACH3A */
+#endif /* CONFIG_LOONGSON_MACH3X */
 
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h
new file mode 100644 (file)
index 0000000..37c08a2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * 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.
+ */
+#ifndef _ASM_MACH_MMZONE_H
+#define _ASM_MACH_MMZONE_H
+
+#include <boot_param.h>
+#define NODE_ADDRSPACE_SHIFT 44
+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
+
+#define pa_to_nid(addr)  (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
+
+#define LEVELS_PER_SLICE 128
+
+struct slice_data {
+       unsigned long irq_enable_mask[2];
+       int level_to_irq[LEVELS_PER_SLICE];
+};
+
+struct hub_data {
+       cpumask_t       h_cpus;
+       unsigned long slice_map;
+       unsigned long irq_alloc_mask[2];
+       struct slice_data slice[2];
+};
+
+struct node_data {
+       struct pglist_data pglist;
+       struct hub_data hub;
+       cpumask_t cpumask;
+};
+
+extern struct node_data *__node_data[];
+
+#define NODE_DATA(n)           (&__node_data[(n)]->pglist)
+#define hub_data(n)            (&__node_data[(n)]->hub)
+
+extern void setup_zero_pages(void);
+extern void __init prom_init_numa_memory(void);
+
+#endif /* _ASM_MACH_MMZONE_H */
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
new file mode 100644 (file)
index 0000000..5598ba7
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _ASM_MACH_TOPOLOGY_H
+#define _ASM_MACH_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#define cpu_to_node(cpu)       ((cpu) >> 2)
+#define parent_node(node)      (node)
+#define cpumask_of_node(node)  (&__node_data[(node)]->cpumask)
+
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *);
+
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
+
+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+
+#define node_distance(from, to)        (__node_distances[(from)][(to)])
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_MACH_TOPOLOGY_H */
index 47cfe64..f2c13d2 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_MACH_MIPS_IRQ_H
 
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 #include_next <irq.h>
index 5d154cf..d8106f7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 
index b2048d1..5368891 100644 (file)
@@ -413,7 +413,6 @@ extern unsigned long _pcictrl_bonito_pcicfg;
 #define BONITO_PCIMEMBASECFG_SIZE(WIN, CFG)  (((((~(CFG)) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK)) << (BONITO_PCIMEMBASECFG_ASHIFT - BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT)) | BONITO_PCIMEMBASECFG_AMASK)
 
 
-#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)         ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 #define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)         ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 #define BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 
index 98e9754..cf3b580 100644 (file)
 #define PG_XIE         (_ULCAST_(1) <<  30)
 #define PG_ELPA                (_ULCAST_(1) <<  29)
 #define PG_ESP         (_ULCAST_(1) <<  28)
+#define PG_IEC         (_ULCAST_(1) <<  27)
 
 /*
  * R4x00 interrupt enable / cause bits
 #define MIPS_CONF4_MMUSIZEEXT_SHIFT    (0)
 #define MIPS_CONF4_MMUSIZEEXT  (_ULCAST_(255) << 0)
 #define MIPS_CONF4_FTLBSETS_SHIFT      (0)
-#define MIPS_CONF4_FTLBSETS_SHIFT      (0)
 #define MIPS_CONF4_FTLBSETS    (_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT)
 #define MIPS_CONF4_FTLBWAYS_SHIFT      (4)
 #define MIPS_CONF4_FTLBWAYS    (_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT)
 
 #define MIPS_CONF5_NF          (_ULCAST_(1) << 0)
 #define MIPS_CONF5_UFR         (_ULCAST_(1) << 2)
+#define MIPS_CONF5_MRP         (_ULCAST_(1) << 3)
 #define MIPS_CONF5_MSAEN       (_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA         (_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV          (_ULCAST_(1) << 29)
 #define MIPS_CONF7_IAR         (_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR          (_ULCAST_(1) << 16)
 
+/* MAAR bit definitions */
+#define MIPS_MAAR_ADDR         ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
+#define MIPS_MAAR_ADDR_SHIFT   12
+#define MIPS_MAAR_S            (_ULCAST_(1) << 1)
+#define MIPS_MAAR_V            (_ULCAST_(1) << 0)
+
 /*  EntryHI bit definition */
 #define MIPS_ENTRYHI_EHINV     (_ULCAST_(1) << 10)
 
 #define MIPS_SEGCFG_MK         _ULCAST_(1)
 #define MIPS_SEGCFG_UK         _ULCAST_(0)
 
+#define MIPS_PWFIELD_GDI_SHIFT 24
+#define MIPS_PWFIELD_GDI_MASK  0x3f000000
+#define MIPS_PWFIELD_UDI_SHIFT 18
+#define MIPS_PWFIELD_UDI_MASK  0x00fc0000
+#define MIPS_PWFIELD_MDI_SHIFT 12
+#define MIPS_PWFIELD_MDI_MASK  0x0003f000
+#define MIPS_PWFIELD_PTI_SHIFT 6
+#define MIPS_PWFIELD_PTI_MASK  0x00000fc0
+#define MIPS_PWFIELD_PTEI_SHIFT        0
+#define MIPS_PWFIELD_PTEI_MASK 0x0000003f
+
+#define MIPS_PWSIZE_GDW_SHIFT  24
+#define MIPS_PWSIZE_GDW_MASK   0x3f000000
+#define MIPS_PWSIZE_UDW_SHIFT  18
+#define MIPS_PWSIZE_UDW_MASK   0x00fc0000
+#define MIPS_PWSIZE_MDW_SHIFT  12
+#define MIPS_PWSIZE_MDW_MASK   0x0003f000
+#define MIPS_PWSIZE_PTW_SHIFT  6
+#define MIPS_PWSIZE_PTW_MASK   0x00000fc0
+#define MIPS_PWSIZE_PTEW_SHIFT 0
+#define MIPS_PWSIZE_PTEW_MASK  0x0000003f
+
+#define MIPS_PWCTL_PWEN_SHIFT  31
+#define MIPS_PWCTL_PWEN_MASK   0x80000000
+#define MIPS_PWCTL_DPH_SHIFT   7
+#define MIPS_PWCTL_DPH_MASK    0x00000080
+#define MIPS_PWCTL_HUGEPG_SHIFT        6
+#define MIPS_PWCTL_HUGEPG_MASK 0x00000060
+#define MIPS_PWCTL_PSN_SHIFT   0
+#define MIPS_PWCTL_PSN_MASK    0x0000003f
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -1044,6 +1082,11 @@ do {                                                                     \
 #define write_c0_config6(val)  __write_32bit_c0_register($16, 6, val)
 #define write_c0_config7(val)  __write_32bit_c0_register($16, 7, val)
 
+#define read_c0_maar()         __read_ulong_c0_register($17, 1)
+#define write_c0_maar(val)     __write_ulong_c0_register($17, 1, val)
+#define read_c0_maari()                __read_32bit_c0_register($17, 2)
+#define write_c0_maari(val)    __write_32bit_c0_register($17, 2, val)
+
 /*
  * The WatchLo register.  There may be up to 8 of them.
  */
@@ -1201,6 +1244,19 @@ do {                                                                     \
 #define read_c0_segctl2()      __read_32bit_c0_register($5, 4)
 #define write_c0_segctl2(val)  __write_32bit_c0_register($5, 4, val)
 
+/* Hardware Page Table Walker */
+#define read_c0_pwbase()       __read_ulong_c0_register($5, 5)
+#define write_c0_pwbase(val)   __write_ulong_c0_register($5, 5, val)
+
+#define read_c0_pwfield()      __read_ulong_c0_register($5, 6)
+#define write_c0_pwfield(val)  __write_ulong_c0_register($5, 6, val)
+
+#define read_c0_pwsize()       __read_ulong_c0_register($5, 7)
+#define write_c0_pwsize(val)   __write_ulong_c0_register($5, 7, val)
+
+#define read_c0_pwctl()                __read_32bit_c0_register($6, 6)
+#define write_c0_pwctl(val)    __write_32bit_c0_register($6, 6, val)
+
 /* Cavium OCTEON (cnMIPS) */
 #define read_c0_cvmcount()     __read_ulong_c0_register($9, 6)
 #define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val)
index 2e373da..2f82568 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
 
+#define htw_set_pwbase(pgd)                                            \
+do {                                                                   \
+       if (cpu_has_htw) {                                              \
+               write_c0_pwbase(pgd);                                   \
+               back_to_back_c0_hazard();                               \
+               htw_reset();                                            \
+       }                                                               \
+} while (0)
+
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)                                 \
 do {                                                                   \
        extern void tlbmiss_handler_setup_pgd(unsigned long);           \
        tlbmiss_handler_setup_pgd((unsigned long)(pgd));                \
+       htw_set_pwbase((unsigned long)pgd);                             \
 } while (0)
 
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
index 538f6d4..af5638b 100644 (file)
 
 #include <asm/mipsregs.h>
 
+#ifndef __ASSEMBLY__
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
 
 static inline void enable_msa(void)
 {
@@ -112,10 +115,10 @@ static inline unsigned int read_msa_##name(void)          \
        "       .set    push\n"                                 \
        "       .set    noat\n"                                 \
        "       .insn\n"                                        \
-       "       .word   #CFC_MSA_INSN | (" #cs " << 11)\n"      \
+       "       .word   %1 | (" #cs " << 11)\n"                 \
        "       move    %0, $1\n"                               \
        "       .set    pop\n"                                  \
-       : "=r"(reg));                                           \
+       : "=r"(reg) : "i"(CFC_MSA_INSN));                       \
        return reg;                                             \
 }                                                              \
                                                                \
@@ -126,22 +129,13 @@ static inline void write_msa_##name(unsigned int val)             \
        "       .set    noat\n"                                 \
        "       move    $1, %0\n"                               \
        "       .insn\n"                                        \
-       "       .word   #CTC_MSA_INSN | (" #cs " << 6)\n"       \
+       "       .word   %1 | (" #cs " << 6)\n"                  \
        "       .set    pop\n"                                  \
-       : : "r"(val));                                          \
+       : : "r"(val), "i"(CTC_MSA_INSN));                       \
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
 
-#define MSA_IR         0
-#define MSA_CSR                1
-#define MSA_ACCESS     2
-#define MSA_SAVE       3
-#define MSA_MODIFY     4
-#define MSA_REQUEST    5
-#define MSA_MAP                6
-#define MSA_UNMAP      7
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +145,17 @@ __BUILD_MSA_CTL_REG(request, 5)
 __BUILD_MSA_CTL_REG(map, 6)
 __BUILD_MSA_CTL_REG(unmap, 7)
 
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR         0
+#define MSA_CSR                1
+#define MSA_ACCESS     2
+#define MSA_SAVE       3
+#define MSA_MODIFY     4
+#define MSA_REQUEST    5
+#define MSA_MAP                6
+#define MSA_UNMAP      7
+
 /* MSA Implementation Register (MSAIR) */
 #define MSA_IR_REVB            0
 #define MSA_IR_REVF            (_ULCAST_(0xff) << MSA_IR_REVB)
index 7b7818d..2298199 100644 (file)
@@ -228,6 +228,7 @@ enum cvmx_board_types_enum {
         */
        CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
        CVMX_BOARD_TYPE_UBNT_E100 = 20002,
+       CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
        CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
 
        /* The remaining range is reserved for future use. */
@@ -327,6 +328,7 @@ static inline const char *cvmx_board_type_to_string(enum
                    /* Customer private range */
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
+               ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
                ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
        }
        return "Unsupported Board";
index b4204c1..cd7d606 100644 (file)
 
 #include <asm-generic/pgtable-nopmd.h>
 
+extern int temp_tlb_entry __cpuinitdata;
+
+/*
+ * - add_temporary_entry() add a temporary TLB entry. We use TLB entries
+ *     starting at the top and working down. This is for populating the
+ *     TLB before trap_init() puts the TLB miss handler in place. It
+ *     should be used only for entries matching the actual page tables,
+ *     to prevent inconsistencies.
+ */
+extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+                              unsigned long entryhi, unsigned long pagemask);
+
 /*
  * Basically we have the same two-level (which is the logical three level
  * Linux page table layout folded) page tables as the i386.  Some day
index 539ddd1..027c74d 100644 (file)
@@ -97,6 +97,31 @@ extern void paging_init(void);
 
 #define pmd_page_vaddr(pmd)    pmd_val(pmd)
 
+#define htw_stop()                                                     \
+do {                                                                   \
+       if (cpu_has_htw)                                                \
+               write_c0_pwctl(read_c0_pwctl() &                        \
+                              ~(1 << MIPS_PWCTL_PWEN_SHIFT));          \
+} while(0)
+
+#define htw_start()                                                    \
+do {                                                                   \
+       if (cpu_has_htw)                                                \
+               write_c0_pwctl(read_c0_pwctl() |                        \
+                              (1 << MIPS_PWCTL_PWEN_SHIFT));           \
+} while(0)
+
+
+#define htw_reset()                                                    \
+do {                                                                   \
+       if (cpu_has_htw) {                                              \
+               htw_stop();                                             \
+               back_to_back_c0_hazard();                               \
+               htw_start();                                            \
+               back_to_back_c0_hazard();                               \
+       }                                                               \
+} while(0)
+
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 
 #define pte_none(pte)          (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
@@ -131,6 +156,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
                null.pte_low = null.pte_high = _PAGE_GLOBAL;
 
        set_pte_at(mm, addr, ptep, null);
+       htw_reset();
 }
 #else
 
@@ -168,6 +194,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
        else
 #endif
                set_pte_at(mm, addr, ptep, __pte(0));
+       htw_reset();
 }
 #endif
 
index d5098bc..05f0843 100644 (file)
@@ -238,7 +238,13 @@ typedef struct {
        unsigned long seg;
 } mm_segment_t;
 
-#define ARCH_MIN_TASKALIGN     8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN    16
+# define FPU_ALIGN             __aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN    8
+# define FPU_ALIGN
+#endif
 
 struct mips_abi;
 
@@ -255,7 +261,7 @@ struct thread_struct {
        unsigned long cp0_status;
 
        /* Saved fpu/fpu emulator stuff. */
-       struct mips_fpu_struct fpu;
+       struct mips_fpu_struct fpu FPU_ALIGN;
 #ifdef CONFIG_MIPS_MT_FPAFF
        /* Emulated instruction count */
        unsigned long emulated_fp;
index 7e6e682..fc783f8 100644 (file)
@@ -23,7 +23,7 @@
 struct pt_regs {
 #ifdef CONFIG_32BIT
        /* Pad bytes for argument save space on the stack. */
-       unsigned long pad0[6];
+       unsigned long pad0[8];
 #endif
 
        /* Saved main processor registers. */
@@ -47,8 +47,10 @@ struct pt_regs {
 
 struct task_struct;
 
-extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
-extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
+extern int ptrace_getregs(struct task_struct *child,
+       struct user_pt_regs __user *data);
+extern int ptrace_setregs(struct task_struct *child,
+       struct user_pt_regs __user *data);
 
 extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
 extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
index 910e71a..84dc7e2 100644 (file)
@@ -1,128 +1 @@
-/*
- * Various register offset definitions for debuggers, core file
- * examiners and whatnot.
- *
- * 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) 1995, 1999 Ralf Baechle
- * Copyright (C) 1995, 1999 Silicon Graphics
- */
-#ifndef __ASM_MIPS_REG_H
-#define __ASM_MIPS_REG_H
-
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0                  6
-#define EF_R1                  7
-#define EF_R2                  8
-#define EF_R3                  9
-#define EF_R4                  10
-#define EF_R5                  11
-#define EF_R6                  12
-#define EF_R7                  13
-#define EF_R8                  14
-#define EF_R9                  15
-#define EF_R10                 16
-#define EF_R11                 17
-#define EF_R12                 18
-#define EF_R13                 19
-#define EF_R14                 20
-#define EF_R15                 21
-#define EF_R16                 22
-#define EF_R17                 23
-#define EF_R18                 24
-#define EF_R19                 25
-#define EF_R20                 26
-#define EF_R21                 27
-#define EF_R22                 28
-#define EF_R23                 29
-#define EF_R24                 30
-#define EF_R25                 31
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26                 32
-#define EF_R27                 33
-
-#define EF_R28                 34
-#define EF_R29                 35
-#define EF_R30                 36
-#define EF_R31                 37
-
-/*
- * Saved special registers
- */
-#define EF_LO                  38
-#define EF_HI                  39
-
-#define EF_CP0_EPC             40
-#define EF_CP0_BADVADDR                41
-#define EF_CP0_STATUS          42
-#define EF_CP0_CAUSE           43
-#define EF_UNUSED0             44
-
-#define EF_SIZE                        180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0                   0
-#define EF_R1                   1
-#define EF_R2                   2
-#define EF_R3                   3
-#define EF_R4                   4
-#define EF_R5                   5
-#define EF_R6                   6
-#define EF_R7                   7
-#define EF_R8                   8
-#define EF_R9                   9
-#define EF_R10                 10
-#define EF_R11                 11
-#define EF_R12                 12
-#define EF_R13                 13
-#define EF_R14                 14
-#define EF_R15                 15
-#define EF_R16                 16
-#define EF_R17                 17
-#define EF_R18                 18
-#define EF_R19                 19
-#define EF_R20                 20
-#define EF_R21                 21
-#define EF_R22                 22
-#define EF_R23                 23
-#define EF_R24                 24
-#define EF_R25                 25
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26                 26
-#define EF_R27                 27
-
-
-#define EF_R28                 28
-#define EF_R29                 29
-#define EF_R30                 30
-#define EF_R31                 31
-
-/*
- * Saved special registers
- */
-#define EF_LO                  32
-#define EF_HI                  33
-
-#define EF_CP0_EPC             34
-#define EF_CP0_BADVADDR                35
-#define EF_CP0_STATUS          36
-#define EF_CP0_CAUSE           37
-
-#define EF_SIZE                        304     /* size in bytes */
-
-#endif /* CONFIG_64BIT */
-
-#endif /* __ASM_MIPS_REG_H */
+#include <uapi/asm/reg.h>
index a06a08a..326c16e 100644 (file)
@@ -31,11 +31,19 @@ extern void mips_cps_core_init(void);
 
 extern struct vpe_boot_config *mips_cps_boot_vpes(void);
 
-extern bool mips_cps_smp_in_use(void);
-
 extern void mips_cps_pm_save(void);
 extern void mips_cps_pm_restore(void);
 
+#ifdef CONFIG_MIPS_CPS
+
+extern bool mips_cps_smp_in_use(void);
+
+#else /* !CONFIG_MIPS_CPS */
+
+static inline bool mips_cps_smp_in_use(void) { return false; }
+
+#endif /* !CONFIG_MIPS_CPS */
+
 #else /* __ASSEMBLY__ */
 
 .extern mips_cps_bootcfg;
index b037334..1e0f20a 100644 (file)
@@ -22,6 +22,7 @@
 
 extern int smp_num_siblings;
 extern cpumask_t cpu_sibling_map[];
+extern cpumask_t cpu_core_map[];
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
@@ -36,6 +37,11 @@ extern int __cpu_logical_map[NR_CPUS];
 
 #define NO_PROC_ID     (-1)
 
+#define topology_physical_package_id(cpu)      (cpu_data[cpu].package)
+#define topology_core_id(cpu)                  (cpu_data[cpu].core)
+#define topology_core_cpumask(cpu)             (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu)           (&cpu_sibling_map[cpu])
+
 #define SMP_RESCHEDULE_YOURSELF 0x1    /* XXX braindead */
 #define SMP_CALL_FUNCTION      0x2
 /* Octeon - Tell another core to flush its icache */
index d2da53c..b1071c1 100644 (file)
@@ -11,7 +11,7 @@
 #else
 # define SECTION_SIZE_BITS     28
 #endif
-#define MAX_PHYSMEM_BITS       35
+#define MAX_PHYSMEM_BITS       48
 
 #endif /* CONFIG_SPARSEMEM */
 #endif /* _MIPS_SPARSEMEM_H */
diff --git a/arch/mips/include/asm/user.h b/arch/mips/include/asm/user.h
deleted file mode 100644 (file)
index 6bad61b..0000000
+++ /dev/null
@@ -1,58 +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) 1994, 1995, 1996, 1999 by Ralf Baechle
- */
-#ifndef _ASM_USER_H
-#define _ASM_USER_H
-
-#include <asm/page.h>
-#include <asm/reg.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the irix-core).  The file
- * contents are as follows:
- *
- *  upage: 1 page consisting of a user struct that tells gdb
- *     what is present in the file.  Directly after this is a
- *     copy of the task_struct, which is currently not used by gdb,
- *     but it may come in handy at some point.  All of the registers
- *     are stored as part of the upage.  The upage should always be
- *     only one page long.
- *  data: The data segment follows next.  We use current->end_text to
- *     current->brk to pick up all of the user variables, plus any memory
- *     that may have been sbrk'ed.  No attempt is made to determine if a
- *     page is demand-zero or if a page is totally unused, we just cover
- *     the entire range.  All of the addresses are rounded in such a way
- *     that an integral number of pages is written.
- *  stack: We need the stack information in order to get a meaningful
- *     backtrace.  We need to write the data from usp to
- *     current->start_stack, so we round each of these in order to be able
- *     to write an integer number of pages.
- */
-struct user {
-       unsigned long   regs[EF_SIZE /          /* integer and fp regs */
-                       sizeof(unsigned long) + 64];
-       size_t          u_tsize;                /* text size (pages) */
-       size_t          u_dsize;                /* data size (pages) */
-       size_t          u_ssize;                /* stack size (pages) */
-       unsigned long   start_code;             /* text starting address */
-       unsigned long   start_data;             /* data starting address */
-       unsigned long   start_stack;            /* stack starting address */
-       long int        signal;                 /* signal causing core dump */
-       unsigned long   u_ar0;                  /* help gdb find registers */
-       unsigned long   magic;                  /* identifies a core file */
-       char            u_comm[32];             /* user command name */
-};
-
-#define NBPG                   PAGE_SIZE
-#define UPAGES                 1
-#define HOST_TEXT_START_ADDR   (u.start_code)
-#define HOST_DATA_START_ADDR   (u.start_data)
-#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _ASM_USER_H */
index b26f7e3..bbcfb8b 100644 (file)
 #define DSP_CONTROL    77
 #define ACX            78
 
-#ifndef __KERNEL__
 /*
- * This struct defines the way the registers are stored on the stack during a
- * system call/exception. As usual the registers k0/k1 aren't being saved.
+ * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
+ * format is the same for both 32- and 64-bit processes. Registers for 32-bit
+ * processes are sign extended.
  */
+#ifdef __KERNEL__
+struct user_pt_regs {
+#else
 struct pt_regs {
+#endif
        /* Saved main processor registers. */
-       unsigned long regs[32];
+       __u64 regs[32];
 
        /* Saved special registers. */
-       unsigned long cp0_status;
-       unsigned long hi;
-       unsigned long lo;
-       unsigned long cp0_badvaddr;
-       unsigned long cp0_cause;
-       unsigned long cp0_epc;
+       __u64 lo;
+       __u64 hi;
+       __u64 cp0_epc;
+       __u64 cp0_badvaddr;
+       __u64 cp0_status;
+       __u64 cp0_cause;
 } __attribute__ ((aligned (8)));
-#endif /* __KERNEL__ */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS         12
diff --git a/arch/mips/include/uapi/asm/reg.h b/arch/mips/include/uapi/asm/reg.h
new file mode 100644 (file)
index 0000000..081e377
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
+ *
+ * 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) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999 Silicon Graphics
+ */
+#ifndef __UAPI_ASM_MIPS_REG_H
+#define __UAPI_ASM_MIPS_REG_H
+
+#define MIPS32_EF_R0           6
+#define MIPS32_EF_R1           7
+#define MIPS32_EF_R2           8
+#define MIPS32_EF_R3           9
+#define MIPS32_EF_R4           10
+#define MIPS32_EF_R5           11
+#define MIPS32_EF_R6           12
+#define MIPS32_EF_R7           13
+#define MIPS32_EF_R8           14
+#define MIPS32_EF_R9           15
+#define MIPS32_EF_R10          16
+#define MIPS32_EF_R11          17
+#define MIPS32_EF_R12          18
+#define MIPS32_EF_R13          19
+#define MIPS32_EF_R14          20
+#define MIPS32_EF_R15          21
+#define MIPS32_EF_R16          22
+#define MIPS32_EF_R17          23
+#define MIPS32_EF_R18          24
+#define MIPS32_EF_R19          25
+#define MIPS32_EF_R20          26
+#define MIPS32_EF_R21          27
+#define MIPS32_EF_R22          28
+#define MIPS32_EF_R23          29
+#define MIPS32_EF_R24          30
+#define MIPS32_EF_R25          31
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS32_EF_R26          32
+#define MIPS32_EF_R27          33
+
+#define MIPS32_EF_R28          34
+#define MIPS32_EF_R29          35
+#define MIPS32_EF_R30          36
+#define MIPS32_EF_R31          37
+
+/*
+ * Saved special registers
+ */
+#define MIPS32_EF_LO           38
+#define MIPS32_EF_HI           39
+
+#define MIPS32_EF_CP0_EPC      40
+#define MIPS32_EF_CP0_BADVADDR 41
+#define MIPS32_EF_CP0_STATUS   42
+#define MIPS32_EF_CP0_CAUSE    43
+#define MIPS32_EF_UNUSED0      44
+
+#define MIPS32_EF_SIZE         180
+
+#define MIPS64_EF_R0           0
+#define MIPS64_EF_R1           1
+#define MIPS64_EF_R2           2
+#define MIPS64_EF_R3           3
+#define MIPS64_EF_R4           4
+#define MIPS64_EF_R5           5
+#define MIPS64_EF_R6           6
+#define MIPS64_EF_R7           7
+#define MIPS64_EF_R8           8
+#define MIPS64_EF_R9           9
+#define MIPS64_EF_R10          10
+#define MIPS64_EF_R11          11
+#define MIPS64_EF_R12          12
+#define MIPS64_EF_R13          13
+#define MIPS64_EF_R14          14
+#define MIPS64_EF_R15          15
+#define MIPS64_EF_R16          16
+#define MIPS64_EF_R17          17
+#define MIPS64_EF_R18          18
+#define MIPS64_EF_R19          19
+#define MIPS64_EF_R20          20
+#define MIPS64_EF_R21          21
+#define MIPS64_EF_R22          22
+#define MIPS64_EF_R23          23
+#define MIPS64_EF_R24          24
+#define MIPS64_EF_R25          25
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS64_EF_R26          26
+#define MIPS64_EF_R27          27
+
+
+#define MIPS64_EF_R28          28
+#define MIPS64_EF_R29          29
+#define MIPS64_EF_R30          30
+#define MIPS64_EF_R31          31
+
+/*
+ * Saved special registers
+ */
+#define MIPS64_EF_LO           32
+#define MIPS64_EF_HI           33
+
+#define MIPS64_EF_CP0_EPC      34
+#define MIPS64_EF_CP0_BADVADDR 35
+#define MIPS64_EF_CP0_STATUS   36
+#define MIPS64_EF_CP0_CAUSE    37
+
+#define MIPS64_EF_SIZE         304     /* size in bytes */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+#define EF_R0                  MIPS32_EF_R0
+#define EF_R1                  MIPS32_EF_R1
+#define EF_R2                  MIPS32_EF_R2
+#define EF_R3                  MIPS32_EF_R3
+#define EF_R4                  MIPS32_EF_R4
+#define EF_R5                  MIPS32_EF_R5
+#define EF_R6                  MIPS32_EF_R6
+#define EF_R7                  MIPS32_EF_R7
+#define EF_R8                  MIPS32_EF_R8
+#define EF_R9                  MIPS32_EF_R9
+#define EF_R10                 MIPS32_EF_R10
+#define EF_R11                 MIPS32_EF_R11
+#define EF_R12                 MIPS32_EF_R12
+#define EF_R13                 MIPS32_EF_R13
+#define EF_R14                 MIPS32_EF_R14
+#define EF_R15                 MIPS32_EF_R15
+#define EF_R16                 MIPS32_EF_R16
+#define EF_R17                 MIPS32_EF_R17
+#define EF_R18                 MIPS32_EF_R18
+#define EF_R19                 MIPS32_EF_R19
+#define EF_R20                 MIPS32_EF_R20
+#define EF_R21                 MIPS32_EF_R21
+#define EF_R22                 MIPS32_EF_R22
+#define EF_R23                 MIPS32_EF_R23
+#define EF_R24                 MIPS32_EF_R24
+#define EF_R25                 MIPS32_EF_R25
+#define EF_R26                 MIPS32_EF_R26
+#define EF_R27                 MIPS32_EF_R27
+#define EF_R28                 MIPS32_EF_R28
+#define EF_R29                 MIPS32_EF_R29
+#define EF_R30                 MIPS32_EF_R30
+#define EF_R31                 MIPS32_EF_R31
+#define EF_LO                  MIPS32_EF_LO
+#define EF_HI                  MIPS32_EF_HI
+#define EF_CP0_EPC             MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR                MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS          MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE           MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0             MIPS32_EF_UNUSED0
+#define EF_SIZE                        MIPS32_EF_SIZE
+
+#elif _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+
+#define EF_R0                  MIPS64_EF_R0
+#define EF_R1                  MIPS64_EF_R1
+#define EF_R2                  MIPS64_EF_R2
+#define EF_R3                  MIPS64_EF_R3
+#define EF_R4                  MIPS64_EF_R4
+#define EF_R5                  MIPS64_EF_R5
+#define EF_R6                  MIPS64_EF_R6
+#define EF_R7                  MIPS64_EF_R7
+#define EF_R8                  MIPS64_EF_R8
+#define EF_R9                  MIPS64_EF_R9
+#define EF_R10                 MIPS64_EF_R10
+#define EF_R11                 MIPS64_EF_R11
+#define EF_R12                 MIPS64_EF_R12
+#define EF_R13                 MIPS64_EF_R13
+#define EF_R14                 MIPS64_EF_R14
+#define EF_R15                 MIPS64_EF_R15
+#define EF_R16                 MIPS64_EF_R16
+#define EF_R17                 MIPS64_EF_R17
+#define EF_R18                 MIPS64_EF_R18
+#define EF_R19                 MIPS64_EF_R19
+#define EF_R20                 MIPS64_EF_R20
+#define EF_R21                 MIPS64_EF_R21
+#define EF_R22                 MIPS64_EF_R22
+#define EF_R23                 MIPS64_EF_R23
+#define EF_R24                 MIPS64_EF_R24
+#define EF_R25                 MIPS64_EF_R25
+#define EF_R26                 MIPS64_EF_R26
+#define EF_R27                 MIPS64_EF_R27
+#define EF_R28                 MIPS64_EF_R28
+#define EF_R29                 MIPS64_EF_R29
+#define EF_R30                 MIPS64_EF_R30
+#define EF_R31                 MIPS64_EF_R31
+#define EF_LO                  MIPS64_EF_LO
+#define EF_HI                  MIPS64_EF_HI
+#define EF_CP0_EPC             MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR                MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS          MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE           MIPS64_EF_CP0_CAUSE
+#define EF_SIZE                        MIPS64_EF_SIZE
+
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#endif /* __UAPI_ASM_MIPS_REG_H */
index a8acdef..325422d 100644 (file)
@@ -87,8 +87,7 @@ void jz4740_clock_debugfs_add_clk(struct clk *clk)
 /* TODO: Locking */
 void jz4740_clock_debugfs_update_parent(struct clk *clk)
 {
-       if (clk->debugfs_parent_entry)
-               debugfs_remove(clk->debugfs_parent_entry);
+       debugfs_remove(clk->debugfs_parent_entry);
 
        if (clk->parent) {
                char parent_path[100];
index a447101..0b12f27 100644 (file)
@@ -59,7 +59,7 @@ struct platform_device jz4740_usb_ohci_device = {
 
 /* USB Device Controller */
 struct platform_device jz4740_udc_xceiv_device = {
-       .name = "usb_phy_gen_xceiv",
+       .name = "usb_phy_generic",
        .id   = 0,
 };
 
index 4bb5107..b1d84bd 100644 (file)
@@ -234,6 +234,7 @@ void output_thread_fpu_defines(void)
               thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
 
        OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+       OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
        BLANK();
 }
 
index 7faf5f2..9287678 100644 (file)
@@ -72,22 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #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>
@@ -145,28 +129,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
        value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
-{
-       int i;
-
-       for (i = 0; i < EF_R0; i++)
-               grp[i] = 0;
-       grp[EF_R0] = 0;
-       for (i = 1; i <= 31; i++)
-               grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
-       grp[EF_R26] = 0;
-       grp[EF_R27] = 0;
-       grp[EF_LO] = (elf_greg_t) regs->lo;
-       grp[EF_HI] = (elf_greg_t) regs->hi;
-       grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-       grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-       grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-       grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
-       grp[EF_UNUSED0] = 0;
-#endif
-}
-
 MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
 MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 
index d74f957..e34b10b 100644 (file)
@@ -54,6 +54,20 @@ static int __init dsp_disable(char *s)
 
 __setup("nodsp", dsp_disable);
 
+static int mips_htw_disabled;
+
+static int __init htw_disable(char *s)
+{
+       mips_htw_disabled = 1;
+       cpu_data[0].options &= ~MIPS_CPU_HTW;
+       write_c0_pwctl(read_c0_pwctl() &
+                      ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+
+       return 1;
+}
+
+__setup("nohtw", htw_disable);
+
 static inline void check_errata(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
@@ -130,14 +144,13 @@ static inline int __cpu_has_fpu(void)
 
 static inline unsigned long cpu_get_msa_id(void)
 {
-       unsigned long status, conf5, msa_id;
+       unsigned long status, msa_id;
 
        status = read_c0_status();
        __enable_fpu(FPU_64BIT);
-       conf5 = read_c0_config5();
        enable_msa();
        msa_id = read_msa_ir();
-       write_c0_config5(conf5);
+       disable_msa();
        write_c0_status(status);
        return msa_id;
 }
@@ -321,6 +334,9 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
                c->options |= MIPS_CPU_SEGMENTS;
        if (config3 & MIPS_CONF3_MSA)
                c->ases |= MIPS_ASE_MSA;
+       /* Only tested on 32-bit cores */
+       if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
+               c->options |= MIPS_CPU_HTW;
 
        return config3 & MIPS_CONF_M;
 }
@@ -389,6 +405,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
 
        if (config5 & MIPS_CONF5_EVA)
                c->options |= MIPS_CPU_EVA;
+       if (config5 & MIPS_CONF5_MRP)
+               c->options |= MIPS_CPU_MAAR;
 
        return config5 & MIPS_CONF_M;
 }
@@ -421,6 +439,15 @@ static void decode_configs(struct cpuinfo_mips *c)
 
        mips_probe_watch_registers(c);
 
+       if (cpu_has_rixi) {
+               /* Enable the RIXI exceptions */
+               write_c0_pagegrain(read_c0_pagegrain() | PG_IEC);
+               back_to_back_c0_hazard();
+               /* Verify the IEC bit is set */
+               if (read_c0_pagegrain() & PG_IEC)
+                       c->options |= MIPS_CPU_RIXIEX;
+       }
+
 #ifndef CONFIG_MIPS_CPS
        if (cpu_has_mips_r2) {
                c->core = get_ebase_cpunum();
@@ -740,6 +767,12 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        __cpu_name[cpu] = "ICT Loongson-3";
                        set_elf_platform(cpu, "loongson3a");
                        break;
+               case PRID_REV_LOONGSON3B_R1:
+               case PRID_REV_LOONGSON3B_R2:
+                       c->cputype = CPU_LOONGSON3;
+                       __cpu_name[cpu] = "ICT Loongson-3";
+                       set_elf_platform(cpu, "loongson3b");
+                       break;
                }
 
                set_isa(c, MIPS_CPU_ISA_III);
@@ -1187,6 +1220,12 @@ void cpu_probe(void)
        if (mips_dsp_disabled)
                c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
 
+       if (mips_htw_disabled) {
+               c->options &= ~MIPS_CPU_HTW;
+               write_c0_pwctl(read_c0_pwctl() &
+                              ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+       }
+
        if (c->options & MIPS_CPU_FPU) {
                c->fpu_id = cpu_get_fpu_id();
 
index 8b65387..937c54b 100644 (file)
@@ -63,7 +63,7 @@ static inline int in_kernel_space(unsigned long ip)
        ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
 
 static unsigned int insn_jal_ftrace_caller __read_mostly;
-static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
+static unsigned int insn_la_mcount[2] __read_mostly;
 static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
 
 static inline void ftrace_dyn_arch_init_insns(void)
@@ -71,10 +71,10 @@ static inline void ftrace_dyn_arch_init_insns(void)
        u32 *buf;
        unsigned int v1;
 
-       /* lui v1, hi16_mcount */
+       /* la v1, _mcount */
        v1 = 3;
-       buf = (u32 *)&insn_lui_v1_hi16_mcount;
-       UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
+       buf = (u32 *)&insn_la_mcount[0];
+       UASM_i_LA(&buf, v1, MCOUNT_ADDR);
 
        /* jal (ftrace_caller + 8), jump over the first two instruction */
        buf = (u32 *)&insn_jal_ftrace_caller;
@@ -111,14 +111,47 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
                                unsigned int new_code2)
 {
        int faulted;
+       mm_segment_t old_fs;
 
        safe_store_code(new_code1, ip, faulted);
        if (unlikely(faulted))
                return -EFAULT;
-       safe_store_code(new_code2, ip + 4, faulted);
+
+       ip += 4;
+       safe_store_code(new_code2, ip, faulted);
        if (unlikely(faulted))
                return -EFAULT;
+
+       ip -= 4;
+       old_fs = get_fs();
+       set_fs(get_ds());
        flush_icache_range(ip, ip + 8);
+       set_fs(old_fs);
+
+       return 0;
+}
+
+static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
+                                unsigned int new_code2)
+{
+       int faulted;
+       mm_segment_t old_fs;
+
+       ip += 4;
+       safe_store_code(new_code2, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+
+       ip -= 4;
+       safe_store_code(new_code1, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+
+       old_fs = get_fs();
+       set_fs(get_ds());
+       flush_icache_range(ip, ip + 8);
+       set_fs(old_fs);
+
        return 0;
 }
 #endif
@@ -130,13 +163,14 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
  *
  * move at, ra
  * jal _mcount         --> nop
+ *  sub sp, sp, 8      --> nop  (CONFIG_32BIT)
  *
  * 2. For modules:
  *
  * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
  *
  * lui v1, hi_16bit_of_mcount       --> b 1f (0x10000005)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop  (CONFIG_32BIT)
  * move at, ra
  * move $12, ra_address
  * jalr v1
@@ -145,7 +179,7 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
  * 2.2 For the Other situations
  *
  * lui v1, hi_16bit_of_mcount       --> b 1f (0x10000004)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop  (CONFIG_32BIT)
  * move at, ra
  * jalr v1
  *  nop | move $12, ra_address | sub sp, sp, 8
@@ -184,10 +218,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
        unsigned int new;
        unsigned long ip = rec->ip;
 
-       new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
-               insn_lui_v1_hi16_mcount;
+       new = in_kernel_space(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
 
+#ifdef CONFIG_64BIT
        return ftrace_modify_code(ip, new);
+#else
+       return ftrace_modify_code_2r(ip, new, in_kernel_space(ip) ?
+                                               INSN_NOP : insn_la_mcount[1]);
+#endif
 }
 
 #define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
index 88e4c32..9e9d8b9 100644 (file)
@@ -28,6 +28,18 @@ unsigned int gic_irq_flags[GIC_NUM_INTRS];
 /* The index into this array is the vector # of the interrupt. */
 struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
 
+struct gic_pcpu_mask {
+       DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+};
+
+struct gic_pending_regs {
+       DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+};
+
+struct gic_intrmask_regs {
+       DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+};
+
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
@@ -177,7 +189,7 @@ unsigned int gic_compare_int(void)
                return 0;
 }
 
-unsigned int gic_get_int(void)
+void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 {
        unsigned int i;
        unsigned long *pending, *intrmask, *pcpu_mask;
@@ -202,8 +214,17 @@ unsigned int gic_get_int(void)
 
        bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
        bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+       bitmap_and(dst, src, pending, GIC_NUM_INTRS);
+}
 
-       return find_first_bit(pending, GIC_NUM_INTRS);
+unsigned int gic_get_int(void)
+{
+       DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
+
+       bitmap_fill(interrupts, GIC_NUM_INTRS);
+       gic_get_int_mask(interrupts, interrupts);
+
+       return find_first_bit(interrupts, GIC_NUM_INTRS);
 }
 
 static void gic_mask_irq(struct irq_data *d)
@@ -269,11 +290,13 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
 
        /* Setup Intr to Pin mapping */
        if (pin & GIC_MAP_TO_NMI_MSK) {
+               int i;
+
                GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
                /* FIXME: hack to route NMI to all cpu's */
-               for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
+               for (i = 0; i < NR_CPUS; i += 32) {
                        GICWRITE(GIC_REG_ADDR(SHARED,
-                                         GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
+                                         GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
                                 0xffffffff);
                }
        } else {
@@ -299,9 +322,10 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
 
        /* Init Intr Masks */
        GIC_CLR_INTR_MASK(intr);
+
        /* Initialise per-cpu Interrupt software masks */
-       if (flags & GIC_FLAG_IPI)
-               set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+       set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+
        if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
                GIC_SET_INTR_MASK(intr);
        if (trigtype == GIC_TRIG_EDGE)
@@ -340,8 +364,6 @@ static void __init gic_basic_init(int numintrs, int numvpes,
                cpu = intrmap[i].cpunum;
                if (cpu == GIC_UNUSED)
                        continue;
-               if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
-                       continue;
                gic_setup_intr(i,
                        intrmap[i].cpunum,
                        intrmap[i].pin + pin_offset,
index 00940d1..5d25462 100644 (file)
@@ -80,6 +80,19 @@ _mcount:
 #endif
 
        PTR_SUBU a0, ra, 8      /* arg1: self address */
+       PTR_LA   t1, _stext
+       sltu     t2, a0, t1     /* t2 = (a0 < _stext) */
+       PTR_LA   t1, _etext
+       sltu     t3, t1, a0     /* t3 = (a0 > _etext) */
+       or       t1, t2, t3
+       beqz     t1, ftrace_call
+        nop
+#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
+       PTR_SUBU a0, a0, 16     /* arg1: adjust to module's recorded callsite */
+#else
+       PTR_SUBU a0, a0, 12
+#endif
+
        .globl ftrace_call
 ftrace_call:
        nop     /* a placeholder for the call to a real tracing function */
index 4f2d9de..14bf74b 100644 (file)
@@ -1386,6 +1386,9 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
 /* proAptiv */
 #define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b)                             \
        ((b) == 0 || (b) == 1)
+/* P5600 */
+#define IS_BOTH_COUNTERS_P5600_EVENT(b)                                        \
+       ((b) == 0 || (b) == 1)
 
 /* 1004K */
 #define IS_BOTH_COUNTERS_1004K_EVENT(b)                                        \
@@ -1420,20 +1423,23 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
 
 
 /*
- * User can use 0-255 raw events, where 0-127 for the events of even
- * counters, and 128-255 for odd counters. Note that bit 7 is used to
- * indicate the parity. So, for example, when user wants to take the
- * Event Num of 15 for odd counters (by referring to the user manual),
- * then 128 needs to be added to 15 as the input for the event config,
- * i.e., 143 (0x8F) to be used.
+ * For most cores the user can use 0-255 raw events, where 0-127 for the events
+ * of even counters, and 128-255 for odd counters. Note that bit 7 is used to
+ * indicate the even/odd bank selector. So, for example, when user wants to take
+ * the Event Num of 15 for odd counters (by referring to the user manual), then
+ * 128 needs to be added to 15 as the input for the event config, i.e., 143 (0x8F)
+ * to be used.
+ *
+ * Some newer cores have even more events, in which case the user can use raw
+ * events 0-511, where 0-255 are for the events of even counters, and 256-511
+ * are for odd counters, so bit 8 is used to indicate the even/odd bank selector.
  */
 static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 {
+       /* currently most cores have 7-bit event numbers */
        unsigned int raw_id = config & 0xff;
        unsigned int base_id = raw_id & 0x7f;
 
-       raw_event.event_id = base_id;
-
        switch (current_cpu_type()) {
        case CPU_24K:
                if (IS_BOTH_COUNTERS_24K_EVENT(base_id))
@@ -1483,6 +1489,19 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
                                raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
 #ifdef CONFIG_MIPS_MT_SMP
                raw_event.range = P;
+#endif
+               break;
+       case CPU_P5600:
+               /* 8-bit event numbers */
+               raw_id = config & 0x1ff;
+               base_id = raw_id & 0xff;
+               if (IS_BOTH_COUNTERS_P5600_EVENT(base_id))
+                       raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+               else
+                       raw_event.cntr_mask =
+                               raw_id > 255 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+               raw_event.range = P;
 #endif
                break;
        case CPU_1004K:
@@ -1523,6 +1542,8 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
                                raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
        }
 
+       raw_event.event_id = base_id;
+
        return &raw_event;
 }
 
@@ -1633,6 +1654,11 @@ init_hw_perf_events(void)
                mipspmu.general_event_map = &mipsxxcore_event_map2;
                mipspmu.cache_event_map = &mipsxxcore_cache_map2;
                break;
+       case CPU_P5600:
+               mipspmu.name = "mips/P5600";
+               mipspmu.general_event_map = &mipsxxcore_event_map2;
+               mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+               break;
        case CPU_1004K:
                mipspmu.name = "mips/1004K";
                mipspmu.general_event_map = &mipsxxcore_event_map;
index c4c2069..0614717 100644 (file)
@@ -149,8 +149,12 @@ int cps_pm_enter_state(enum cps_pm_state state)
 
        /* Setup the VPE to run mips_cps_pm_restore when started again */
        if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+               /* Power gating relies upon CPS SMP */
+               if (!mips_cps_smp_in_use())
+                       return -EINVAL;
+
                core_cfg = &mips_cps_core_bootcfg[core];
-               vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id];
+               vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(&current_cpu_data)];
                vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
                vpe_cfg->gp = (unsigned long)current_thread_info();
                vpe_cfg->sp = 0;
@@ -376,6 +380,10 @@ static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
        memset(relocs, 0, sizeof(relocs));
 
        if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+               /* Power gating relies upon CPS SMP */
+               if (!mips_cps_smp_in_use())
+                       goto out_err;
+
                /*
                 * Save CPU state. Note the non-standard calling convention
                 * with the return address placed in v0 to avoid clobbering
index 037a44d..097fc8d 100644 (file)
@@ -113,6 +113,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if (cpu_has_vz)         seq_printf(m, "%s", " vz");
        if (cpu_has_msa)        seq_printf(m, "%s", " msa");
        if (cpu_has_eva)        seq_printf(m, "%s", " eva");
+       if (cpu_has_htw)        seq_printf(m, "%s", " htw");
        seq_printf(m, "\n");
 
        if (cpu_has_mmips) {
@@ -123,6 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                      cpu_data[n].srsets);
        seq_printf(m, "kscratch registers\t: %d\n",
                      hweight8(cpu_data[n].kscratch_mask));
+       seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
        seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
 
        sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
index 0a1ec0f..636b074 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/mman.h>
 #include <linux/personality.h>
 #include <linux/sys.h>
-#include <linux/user.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
@@ -36,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
@@ -66,6 +66,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
        clear_used_math();
        clear_fpu_owner();
        init_dsp();
+       clear_thread_flag(TIF_USEDMSA);
        clear_thread_flag(TIF_MSA_CTX_LIVE);
        disable_msa();
        regs->cp0_epc = pc;
@@ -141,6 +142,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
        clear_tsk_thread_flag(p, TIF_USEDFPU);
+       clear_tsk_thread_flag(p, TIF_USEDMSA);
+       clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
 
 #ifdef CONFIG_MIPS_MT_FPAFF
        clear_tsk_thread_flag(p, TIF_FPUBOUND);
@@ -152,61 +155,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-/* Fill in the fpu structure for a core dump.. */
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
-{
-       int i;
-
-       for (i = 0; i < NUM_FPU_REGS; i++)
-               memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
-
-       memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
-              sizeof(current->thread.fpu.fcr31));
-
-       return 1;
-}
-
-void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
-{
-       int i;
-
-       for (i = 0; i < EF_R0; i++)
-               gp[i] = 0;
-       gp[EF_R0] = 0;
-       for (i = 1; i <= 31; i++)
-               gp[EF_R0 + i] = regs->regs[i];
-       gp[EF_R26] = 0;
-       gp[EF_R27] = 0;
-       gp[EF_LO] = regs->lo;
-       gp[EF_HI] = regs->hi;
-       gp[EF_CP0_EPC] = regs->cp0_epc;
-       gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
-       gp[EF_CP0_STATUS] = regs->cp0_status;
-       gp[EF_CP0_CAUSE] = regs->cp0_cause;
-#ifdef EF_UNUSED0
-       gp[EF_UNUSED0] = 0;
-#endif
-}
-
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       elf_dump_regs(*regs, task_pt_regs(tsk));
-       return 1;
-}
-
-int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
-{
-       int i;
-
-       for (i = 0; i < NUM_FPU_REGS; i++)
-               memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
-
-       memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
-              sizeof(t->thread.fpu.fcr31));
-
-       return 1;
-}
-
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
 unsigned long __stack_chk_guard __read_mostly;
index f639ccd..645b3c4 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 #include <linux/tracehook.h>
 #include <linux/audit.h>
@@ -63,7 +62,7 @@ void ptrace_disable(struct task_struct *child)
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
  */
-int ptrace_getregs(struct task_struct *child, __s64 __user *data)
+int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
        struct pt_regs *regs;
        int i;
@@ -74,13 +73,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
        regs = task_pt_regs(child);
 
        for (i = 0; i < 32; i++)
-               __put_user((long)regs->regs[i], data + i);
-       __put_user((long)regs->lo, data + EF_LO - EF_R0);
-       __put_user((long)regs->hi, data + EF_HI - EF_R0);
-       __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
-       __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
-       __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
-       __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+               __put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
+       __put_user((long)regs->lo, (__s64 __user *)&data->lo);
+       __put_user((long)regs->hi, (__s64 __user *)&data->hi);
+       __put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
+       __put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
+       __put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
+       __put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
 
        return 0;
 }
@@ -90,7 +89,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
  * the 64-bit format.  On a 32-bit kernel only the lower order half
  * (according to endianness) will be used.
  */
-int ptrace_setregs(struct task_struct *child, __s64 __user *data)
+int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
        struct pt_regs *regs;
        int i;
@@ -101,10 +100,10 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
        regs = task_pt_regs(child);
 
        for (i = 0; i < 32; i++)
-               __get_user(regs->regs[i], data + i);
-       __get_user(regs->lo, data + EF_LO - EF_R0);
-       __get_user(regs->hi, data + EF_HI - EF_R0);
-       __get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+               __get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
+       __get_user(regs->lo, (__s64 __user *)&data->lo);
+       __get_user(regs->hi, (__s64 __user *)&data->hi);
+       __get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
 
        /* badvaddr, status, and cause may not be written.  */
 
@@ -129,7 +128,7 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
        }
 
        __put_user(child->thread.fpu.fcr31, data + 64);
-       __put_user(current_cpu_data.fpu_id, data + 65);
+       __put_user(boot_cpu_data.fpu_id, data + 65);
 
        return 0;
 }
@@ -151,6 +150,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
        }
 
        __get_user(child->thread.fpu.fcr31, data + 64);
+       child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
        /* FIR may not be written.  */
 
@@ -246,36 +246,160 @@ int ptrace_set_watch_regs(struct task_struct *child,
 
 /* regset get/set implementations */
 
-static int gpr_get(struct task_struct *target,
-                  const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+                    const struct user_regset *regset,
+                    unsigned int pos, unsigned int count,
+                    void *kbuf, void __user *ubuf)
 {
        struct pt_regs *regs = task_pt_regs(target);
+       u32 uregs[ELF_NGREG] = {};
+       unsigned i;
+
+       for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+               /* k0/k1 are copied as zero. */
+               if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+                       continue;
+
+               uregs[i] = regs->regs[i - MIPS32_EF_R0];
+       }
 
-       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                  regs, 0, sizeof(*regs));
+       uregs[MIPS32_EF_LO] = regs->lo;
+       uregs[MIPS32_EF_HI] = regs->hi;
+       uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+       uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+       uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+       uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+                                  sizeof(uregs));
 }
 
-static int gpr_set(struct task_struct *target,
-                  const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+                    const struct user_regset *regset,
+                    unsigned int pos, unsigned int count,
+                    const void *kbuf, const void __user *ubuf)
 {
-       struct pt_regs newregs;
-       int ret;
+       struct pt_regs *regs = task_pt_regs(target);
+       u32 uregs[ELF_NGREG];
+       unsigned start, num_regs, i;
+       int err;
+
+       start = pos / sizeof(u32);
+       num_regs = count / sizeof(u32);
+
+       if (start + num_regs > ELF_NGREG)
+               return -EIO;
+
+       err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+                                sizeof(uregs));
+       if (err)
+               return err;
+
+       for (i = start; i < num_regs; i++) {
+               /*
+                * Cast all values to signed here so that if this is a 64-bit
+                * kernel, the supplied 32-bit values will be sign extended.
+                */
+               switch (i) {
+               case MIPS32_EF_R1 ... MIPS32_EF_R25:
+                       /* k0/k1 are ignored. */
+               case MIPS32_EF_R28 ... MIPS32_EF_R31:
+                       regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+                       break;
+               case MIPS32_EF_LO:
+                       regs->lo = (s32)uregs[i];
+                       break;
+               case MIPS32_EF_HI:
+                       regs->hi = (s32)uregs[i];
+                       break;
+               case MIPS32_EF_CP0_EPC:
+                       regs->cp0_epc = (s32)uregs[i];
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+                    const struct user_regset *regset,
+                    unsigned int pos, unsigned int count,
+                    void *kbuf, void __user *ubuf)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+       u64 uregs[ELF_NGREG] = {};
+       unsigned i;
+
+       for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+               /* k0/k1 are copied as zero. */
+               if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+                       continue;
+
+               uregs[i] = regs->regs[i - MIPS64_EF_R0];
+       }
+
+       uregs[MIPS64_EF_LO] = regs->lo;
+       uregs[MIPS64_EF_HI] = regs->hi;
+       uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+       uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+       uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+       uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+                                  sizeof(uregs));
+}
 
-       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                &newregs,
-                                0, sizeof(newregs));
-       if (ret)
-               return ret;
+static int gpr64_set(struct task_struct *target,
+                    const struct user_regset *regset,
+                    unsigned int pos, unsigned int count,
+                    const void *kbuf, const void __user *ubuf)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+       u64 uregs[ELF_NGREG];
+       unsigned start, num_regs, i;
+       int err;
+
+       start = pos / sizeof(u64);
+       num_regs = count / sizeof(u64);
 
-       *task_pt_regs(target) = newregs;
+       if (start + num_regs > ELF_NGREG)
+               return -EIO;
+
+       err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+                                sizeof(uregs));
+       if (err)
+               return err;
+
+       for (i = start; i < num_regs; i++) {
+               switch (i) {
+               case MIPS64_EF_R1 ... MIPS64_EF_R25:
+                       /* k0/k1 are ignored. */
+               case MIPS64_EF_R28 ... MIPS64_EF_R31:
+                       regs->regs[i - MIPS64_EF_R0] = uregs[i];
+                       break;
+               case MIPS64_EF_LO:
+                       regs->lo = uregs[i];
+                       break;
+               case MIPS64_EF_HI:
+                       regs->hi = uregs[i];
+                       break;
+               case MIPS64_EF_CP0_EPC:
+                       regs->cp0_epc = uregs[i];
+                       break;
+               }
+       }
 
        return 0;
 }
 
+#endif /* CONFIG_64BIT */
+
 static int fpr_get(struct task_struct *target,
                   const struct user_regset *regset,
                   unsigned int pos, unsigned int count,
@@ -337,14 +461,16 @@ enum mips_regset {
        REGSET_FPR,
 };
 
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
 static const struct user_regset mips_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
                .n              = ELF_NGREG,
                .size           = sizeof(unsigned int),
                .align          = sizeof(unsigned int),
-               .get            = gpr_get,
-               .set            = gpr_set,
+               .get            = gpr32_get,
+               .set            = gpr32_set,
        },
        [REGSET_FPR] = {
                .core_note_type = NT_PRFPREG,
@@ -364,14 +490,18 @@ static const struct user_regset_view user_mips_view = {
        .n              = ARRAY_SIZE(mips_regsets),
 };
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
 static const struct user_regset mips64_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
                .n              = ELF_NGREG,
                .size           = sizeof(unsigned long),
                .align          = sizeof(unsigned long),
-               .get            = gpr_get,
-               .set            = gpr_set,
+               .get            = gpr64_get,
+               .set            = gpr64_set,
        },
        [REGSET_FPR] = {
                .core_note_type = NT_PRFPREG,
@@ -384,25 +514,26 @@ static const struct user_regset mips64_regsets[] = {
 };
 
 static const struct user_regset_view user_mips64_view = {
-       .name           = "mips",
+       .name           = "mips64",
        .e_machine      = ELF_ARCH,
        .ei_osabi       = ELF_OSABI,
        .regsets        = mips64_regsets,
-       .n              = ARRAY_SIZE(mips_regsets),
+       .n              = ARRAY_SIZE(mips64_regsets),
 };
 
+#endif /* CONFIG_64BIT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_32BIT
        return &user_mips_view;
-#endif
-
+#else
 #ifdef CONFIG_MIPS32_O32
-               if (test_thread_flag(TIF_32BIT_REGS))
-                       return &user_mips_view;
+       if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+               return &user_mips_view;
 #endif
-
        return &user_mips64_view;
+#endif
 }
 
 long arch_ptrace(struct task_struct *child, long request,
@@ -480,7 +611,7 @@ long arch_ptrace(struct task_struct *child, long request,
                        break;
                case FPC_EIR:
                        /* implementation / version register */
-                       tmp = current_cpu_data.fpu_id;
+                       tmp = boot_cpu_data.fpu_id;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
@@ -565,7 +696,7 @@ long arch_ptrace(struct task_struct *child, long request,
                        break;
 #endif
                case FPC_CSR:
-                       child->thread.fpu.fcr31 = data;
+                       child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
index b40c3ca..283b5a1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 
 #include <asm/cpu.h>
@@ -32,6 +31,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
@@ -129,7 +129,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
                case FPC_EIR:
                        /* implementation / version register */
-                       tmp = current_cpu_data.fpu_id;
+                       tmp = boot_cpu_data.fpu_id;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
@@ -256,11 +256,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                }
 
        case PTRACE_GETREGS:
-               ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
+               ret = ptrace_getregs(child,
+                               (struct user_pt_regs __user *) (__u64) data);
                break;
 
        case PTRACE_SETREGS:
-               ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
+               ret = ptrace_setregs(child,
+                               (struct user_pt_regs __user *) (__u64) data);
                break;
 
        case PTRACE_GETFPREGS:
index 81ca3f7..4c4ec18 100644 (file)
        /* Check whether we're saving scalar or vector context. */
        bgtz    a3, 1f
 
-       /* Save 128b MSA vector context. */
+       /* Save 128b MSA vector context + scalar FP control & status. */
+       cfc1    t1, fcr31
        msa_save_all    a0
+       sw      t1, THREAD_FCR31(a0)
        b       2f
 
 1:     /* Save 32b/64b scalar FP context. */
@@ -142,6 +144,11 @@ LEAF(_restore_msa)
        jr      ra
        END(_restore_msa)
 
+LEAF(_init_msa_upper)
+       msa_init_all_upper
+       jr      ra
+       END(_init_msa_upper)
+
 #endif
 
 /*
index 758fb3c..d26dcc4 100644 (file)
@@ -77,6 +77,9 @@ int __init rtlx_module_init(void)
                dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
                                    "%s%d", RTLX_MODULE_NAME, i);
                if (IS_ERR(dev)) {
+                       while (i--)
+                               device_destroy(mt_class, MKDEV(major, i));
+
                        err = PTR_ERR(dev);
                        goto out_chrdev;
                }
index 5a66b97..cb95470 100644 (file)
@@ -103,6 +103,9 @@ int __init rtlx_module_init(void)
                dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
                                    "%s%d", RTLX_MODULE_NAME, i);
                if (IS_ERR(dev)) {
+                       while (i--)
+                               device_destroy(mt_class, MKDEV(major, i));
+
                        err = PTR_ERR(dev);
                        goto out_chrdev;
                }
index ab02d14..f93b4cb 100644 (file)
@@ -67,8 +67,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 
        /*
         * Ok, copy the args from the luser stack to the kernel stack.
-        * t3 is the precomputed number of instruction bytes needed to
-        * load or store arguments 6-8.
         */
 
        .set    push
@@ -495,8 +493,8 @@ EXPORT(sys_call_table)
        PTR     sys_tgkill
        PTR     sys_utimes
        PTR     sys_mbind
-       PTR     sys_ni_syscall                  /* sys_get_mempolicy */
-       PTR     sys_ni_syscall                  /* 4270 sys_set_mempolicy */
+       PTR     sys_get_mempolicy
+       PTR     sys_set_mempolicy               /* 4270 */
        PTR     sys_mq_open
        PTR     sys_mq_unlink
        PTR     sys_mq_timedsend
index 010dccf..03ebd99 100644 (file)
@@ -347,8 +347,8 @@ EXPORT(sys_call_table)
        PTR     sys_tgkill                      /* 5225 */
        PTR     sys_utimes
        PTR     sys_mbind
-       PTR     sys_ni_syscall                  /* sys_get_mempolicy */
-       PTR     sys_ni_syscall                  /* sys_set_mempolicy */
+       PTR     sys_get_mempolicy
+       PTR     sys_set_mempolicy
        PTR     sys_mq_open                     /* 5230 */
        PTR     sys_mq_unlink
        PTR     sys_mq_timedsend
index c3b3b65..ebc9228 100644 (file)
@@ -162,7 +162,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_getpeername
        PTR     sys_socketpair
        PTR     compat_sys_setsockopt
-       PTR     sys_getsockopt
+       PTR     compat_sys_getsockopt
        PTR     __sys_clone                     /* 6055 */
        PTR     __sys_fork
        PTR     compat_sys_execve
@@ -339,9 +339,9 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_clock_nanosleep
        PTR     sys_tgkill
        PTR     compat_sys_utimes               /* 6230 */
-       PTR     sys_ni_syscall                  /* sys_mbind */
-       PTR     sys_ni_syscall                  /* sys_get_mempolicy */
-       PTR     sys_ni_syscall                  /* sys_set_mempolicy */
+       PTR     compat_sys_mbind
+       PTR     compat_sys_get_mempolicy
+       PTR     compat_sys_set_mempolicy
        PTR     compat_sys_mq_open
        PTR     sys_mq_unlink                   /* 6235 */
        PTR     compat_sys_mq_timedsend
@@ -358,7 +358,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_inotify_init
        PTR     sys_inotify_add_watch
        PTR     sys_inotify_rm_watch
-       PTR     sys_migrate_pages               /* 6250 */
+       PTR     compat_sys_migrate_pages        /* 6250 */
        PTR     sys_openat
        PTR     sys_mkdirat
        PTR     sys_mknodat
@@ -379,7 +379,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_sync_file_range
        PTR     sys_tee
        PTR     compat_sys_vmsplice             /* 6270 */
-       PTR     sys_move_pages
+       PTR     compat_sys_move_pages
        PTR     compat_sys_set_robust_list
        PTR     compat_sys_get_robust_list
        PTR     compat_sys_kexec_load
index bb1550b..13b964f 100644 (file)
@@ -473,9 +473,9 @@ EXPORT(sys32_call_table)
        PTR     compat_sys_clock_nanosleep      /* 4265 */
        PTR     sys_tgkill
        PTR     compat_sys_utimes
-       PTR     sys_ni_syscall                  /* sys_mbind */
-       PTR     sys_ni_syscall                  /* sys_get_mempolicy */
-       PTR     sys_ni_syscall                  /* 4270 sys_set_mempolicy */
+       PTR     compat_sys_mbind
+       PTR     compat_sys_get_mempolicy
+       PTR     compat_sys_set_mempolicy        /* 4270 */
        PTR     compat_sys_mq_open
        PTR     sys_mq_unlink
        PTR     compat_sys_mq_timedsend
@@ -492,7 +492,7 @@ EXPORT(sys32_call_table)
        PTR     sys_inotify_init
        PTR     sys_inotify_add_watch           /* 4285 */
        PTR     sys_inotify_rm_watch
-       PTR     sys_migrate_pages
+       PTR     compat_sys_migrate_pages
        PTR     compat_sys_openat
        PTR     sys_mkdirat
        PTR     sys_mknodat                     /* 4290 */
index a842154..7c1fe2b 100644 (file)
@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(void)
  * Initialize the bootmem allocator. It also setup initrd related data
  * if needed.
  */
-#ifdef CONFIG_SGI_IP27
+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
 
 static void __init bootmem_init(void)
 {
@@ -729,6 +729,25 @@ static void __init resource_init(void)
        }
 }
 
+#ifdef CONFIG_SMP
+static void __init prefill_possible_map(void)
+{
+       int i, possible = num_possible_cpus();
+
+       if (possible > nr_cpu_ids)
+               possible = nr_cpu_ids;
+
+       for (i = 0; i < possible; i++)
+               set_cpu_possible(i, true);
+       for (; i < NR_CPUS; i++)
+               set_cpu_possible(i, false);
+
+       nr_cpu_ids = possible;
+}
+#else
+static inline void prefill_possible_map(void) {}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
@@ -752,6 +771,7 @@ void __init setup_arch(char **cmdline_p)
 
        resource_init();
        plat_smp_setup();
+       prefill_possible_map();
 
        cpu_cache_init();
 }
index 949f2c6..e6e16a1 100644 (file)
 #include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/cacheflush.h>
+#include <asm/bcache.h>
 #include <asm/gic.h>
 #include <asm/mips-cm.h>
 #include <asm/mips-cpc.h>
 #include <asm/mips_mt.h>
 #include <asm/mipsregs.h>
 #include <asm/pm-cps.h>
+#include <asm/r4kcache.h>
 #include <asm/smp-cps.h>
 #include <asm/time.h>
 #include <asm/uasm.h>
@@ -132,8 +133,11 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
        entry_code = (u32 *)&mips_cps_core_entry;
        UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
        uasm_i_addiu(&entry_code, 16, 0, cca);
-       dma_cache_wback_inv((unsigned long)&mips_cps_core_entry,
-                           (void *)entry_code - (void *)&mips_cps_core_entry);
+       blast_dcache_range((unsigned long)&mips_cps_core_entry,
+                          (unsigned long)entry_code);
+       bc_wback_inv((unsigned long)&mips_cps_core_entry,
+                    (void *)entry_code - (void *)&mips_cps_core_entry);
+       __sync();
 
        /* Allocate core boot configuration structs */
        mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
@@ -360,7 +364,7 @@ void play_dead(void)
 static void wait_for_sibling_halt(void *ptr_cpu)
 {
        unsigned cpu = (unsigned)ptr_cpu;
-       unsigned vpe_id = cpu_data[cpu].vpe_id;
+       unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
        unsigned halted;
        unsigned long flags;
 
index 3babf6e..21f23ad 100644 (file)
@@ -288,6 +288,7 @@ struct plat_smp_ops vsmp_smp_ops = {
        .prepare_cpus           = vsmp_prepare_cpus,
 };
 
+#ifdef CONFIG_PROC_FS
 static int proc_cpuinfo_chain_call(struct notifier_block *nfb,
        unsigned long action_unused, void *data)
 {
@@ -309,3 +310,4 @@ static int __init proc_cpuinfo_notifier_init(void)
 }
 
 subsys_initcall(proc_cpuinfo_notifier_init);
+#endif
index 9bad52e..c94c4e9 100644 (file)
@@ -59,9 +59,16 @@ EXPORT_SYMBOL(smp_num_siblings);
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_sibling_map);
 
+/* representing the core map of multi-core chips of each logical CPU */
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(cpu_core_map);
+
 /* representing cpus for which sibling maps can be computed */
 static cpumask_t cpu_sibling_setup_map;
 
+/* representing cpus for which core maps can be computed */
+static cpumask_t cpu_core_setup_map;
+
 cpumask_t cpu_coherent_mask;
 
 static inline void set_cpu_sibling_map(int cpu)
@@ -72,7 +79,8 @@ static inline void set_cpu_sibling_map(int cpu)
 
        if (smp_num_siblings > 1) {
                for_each_cpu_mask(i, cpu_sibling_setup_map) {
-                       if (cpu_data[cpu].core == cpu_data[i].core) {
+                       if (cpu_data[cpu].package == cpu_data[i].package &&
+                                   cpu_data[cpu].core == cpu_data[i].core) {
                                cpu_set(i, cpu_sibling_map[cpu]);
                                cpu_set(cpu, cpu_sibling_map[i]);
                        }
@@ -81,6 +89,20 @@ static inline void set_cpu_sibling_map(int cpu)
                cpu_set(cpu, cpu_sibling_map[cpu]);
 }
 
+static inline void set_cpu_core_map(int cpu)
+{
+       int i;
+
+       cpu_set(cpu, cpu_core_setup_map);
+
+       for_each_cpu_mask(i, cpu_core_setup_map) {
+               if (cpu_data[cpu].package == cpu_data[i].package) {
+                       cpu_set(i, cpu_core_map[cpu]);
+                       cpu_set(cpu, cpu_core_map[i]);
+               }
+       }
+}
+
 struct plat_smp_ops *mp_ops;
 EXPORT_SYMBOL(mp_ops);
 
@@ -122,6 +144,7 @@ asmlinkage void start_secondary(void)
        set_cpu_online(cpu, true);
 
        set_cpu_sibling_map(cpu);
+       set_cpu_core_map(cpu);
 
        cpu_set(cpu, cpu_callin_map);
 
@@ -175,6 +198,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        current_thread_info()->cpu = 0;
        mp_ops->prepare_cpus(max_cpus);
        set_cpu_sibling_map(0);
+       set_cpu_core_map(0);
 #ifndef CONFIG_HOTPLUG_CPU
        init_cpu_present(cpu_possible_mask);
 #endif
index 51706d6..22b19c2 100644 (file)
@@ -90,6 +90,7 @@ extern asmlinkage void handle_mt(void);
 extern asmlinkage void handle_dsp(void);
 extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
+extern void tlb_do_page_fault_0(void);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -1088,13 +1089,19 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
 
 static int enable_restore_fp_context(int msa)
 {
-       int err, was_fpu_owner;
+       int err, was_fpu_owner, prior_msa;
 
        if (!used_math()) {
                /* First time FP context user. */
+               preempt_disable();
                err = init_fpu();
-               if (msa && !err)
+               if (msa && !err) {
                        enable_msa();
+                       _init_msa_upper();
+                       set_thread_flag(TIF_USEDMSA);
+                       set_thread_flag(TIF_MSA_CTX_LIVE);
+               }
+               preempt_enable();
                if (!err)
                        set_used_math();
                return err;
@@ -1134,10 +1141,11 @@ static int enable_restore_fp_context(int msa)
         * This task is using or has previously used MSA. Thus we require
         * that Status.FR == 1.
         */
+       preempt_disable();
        was_fpu_owner = is_fpu_owner();
-       err = own_fpu(0);
+       err = own_fpu_inatomic(0);
        if (err)
-               return err;
+               goto out;
 
        enable_msa();
        write_msa_csr(current->thread.fpu.msacsr);
@@ -1146,13 +1154,42 @@ static int enable_restore_fp_context(int msa)
        /*
         * If this is the first time that the task is using MSA and it has
         * previously used scalar FP in this time slice then we already nave
-        * FP context which we shouldn't clobber.
+        * FP context which we shouldn't clobber. We do however need to clear
+        * the upper 64b of each vector register so that this task has no
+        * opportunity to see data left behind by another.
         */
-       if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
-               return 0;
+       prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+       if (!prior_msa && was_fpu_owner) {
+               _init_msa_upper();
+
+               goto out;
+       }
+
+       if (!prior_msa) {
+               /*
+                * Restore the least significant 64b of each vector register
+                * from the existing scalar FP context.
+                */
+               _restore_fp(current);
+
+               /*
+                * The task has not formerly used MSA, so clear the upper 64b
+                * of each vector register such that it cannot see data left
+                * behind by another task.
+                */
+               _init_msa_upper();
+       } else {
+               /* We need to restore the vector context. */
+               restore_msa(current);
+
+               /* Restore the scalar FP control & status register */
+               if (!was_fpu_owner)
+                       asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+       }
+
+out:
+       preempt_enable();
 
-       /* We need to restore the vector context. */
-       restore_msa(current);
        return 0;
 }
 
@@ -2114,6 +2151,12 @@ void __init trap_init(void)
                set_except_vector(15, handle_fpe);
 
        set_except_vector(16, handle_ftlb);
+
+       if (cpu_has_rixiex) {
+               set_except_vector(19, tlb_do_page_fault_0);
+               set_except_vector(20, tlb_do_page_fault_0);
+       }
+
        set_except_vector(21, handle_msa);
        set_except_vector(22, handle_mdmx);
 
index 2b35172..e11906d 100644 (file)
@@ -690,7 +690,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
        case sdc1_op:
                die_if_kernel("Unaligned FP access in kernel code", regs);
                BUG_ON(!used_math());
-               BUG_ON(!is_fpu_owner());
 
                lose_fpu(1);    /* Save FPU state for the emulator. */
                res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
index e6a86cc..1b91fc6 100644 (file)
@@ -60,8 +60,8 @@ config LEMOTE_MACH2F
          These family machines include fuloong2f mini PC, yeeloong2f notebook,
          LingLoong allinone PC and so forth.
 
-config LEMOTE_MACH3A
-       bool "Lemote Loongson 3A family machines"
+config LOONGSON_MACH3X
+       bool "Generic Loongson 3 family machines"
        select ARCH_SPARSEMEM_ENABLE
        select GENERIC_ISA_DMA_SUPPORT_BROKEN
        select BOOT_ELF32
@@ -79,6 +79,7 @@ config LEMOTE_MACH3A
        select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_SMP
        select SYS_SUPPORTS_HOTPLUG_CPU
+       select SYS_SUPPORTS_NUMA
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_HIGHMEM
        select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -86,8 +87,8 @@ config LEMOTE_MACH3A
        select ZONE_DMA32
        select LEFI_FIRMWARE_INTERFACE
        help
-               Lemote Loongson 3A family machines utilize the 3A revision of
-               Loongson processor and RS780/SBX00 chipset.
+               Generic Loongson 3 family machines utilize the 3A/3B revision
+               of Loongson processor and RS780/SBX00 chipset.
 endchoice
 
 config CS5536
index 6205372..0ac20eb 100644 (file)
@@ -30,4 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
 load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
index 0c543ea..f152285 100644 (file)
@@ -27,6 +27,12 @@ EXPORT_SYMBOL(cpu_clock_freq);
 struct efi_memory_map_loongson *loongson_memmap;
 struct loongson_system_configuration loongson_sysconf;
 
+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
+u64 loongson_freqctrl[MAX_PACKAGES];
+
+unsigned long long smp_group[4];
+int cpuhotplug_workaround = 0;
+
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
        unsigned int tmp __maybe_unused;                                \
@@ -77,9 +83,47 @@ void __init prom_init_env(void)
 
        cpu_clock_freq = ecpu->cpu_clock_freq;
        loongson_sysconf.cputype = ecpu->cputype;
+       if (ecpu->cputype == Loongson_3A) {
+               loongson_sysconf.cores_per_node = 4;
+               loongson_sysconf.cores_per_package = 4;
+               smp_group[0] = 0x900000003ff01000;
+               smp_group[1] = 0x900010003ff01000;
+               smp_group[2] = 0x900020003ff01000;
+               smp_group[3] = 0x900030003ff01000;
+               loongson_chipcfg[0] = 0x900000001fe00180;
+               loongson_chipcfg[1] = 0x900010001fe00180;
+               loongson_chipcfg[2] = 0x900020001fe00180;
+               loongson_chipcfg[3] = 0x900030001fe00180;
+               loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+       } else if (ecpu->cputype == Loongson_3B) {
+               loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
+               loongson_sysconf.cores_per_package = 8;
+               smp_group[0] = 0x900000003ff01000;
+               smp_group[1] = 0x900010003ff05000;
+               smp_group[2] = 0x900020003ff09000;
+               smp_group[3] = 0x900030003ff0d000;
+               loongson_chipcfg[0] = 0x900000001fe00180;
+               loongson_chipcfg[1] = 0x900020001fe00180;
+               loongson_chipcfg[2] = 0x900040001fe00180;
+               loongson_chipcfg[3] = 0x900060001fe00180;
+               loongson_freqctrl[0] = 0x900000001fe001d0;
+               loongson_freqctrl[1] = 0x900020001fe001d0;
+               loongson_freqctrl[2] = 0x900040001fe001d0;
+               loongson_freqctrl[3] = 0x900060001fe001d0;
+               loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
+               cpuhotplug_workaround = 1;
+       } else {
+               loongson_sysconf.cores_per_node = 1;
+               loongson_sysconf.cores_per_package = 1;
+               loongson_chipcfg[0] = 0x900000001fe00180;
+       }
+
        loongson_sysconf.nr_cpus = ecpu->nr_cpus;
        if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
                loongson_sysconf.nr_cpus = NR_CPUS;
+       loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
+               loongson_sysconf.cores_per_node - 1) /
+               loongson_sysconf.cores_per_node;
 
        loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
        loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -93,7 +137,6 @@ void __init prom_init_env(void)
        loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
        loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
 
-       loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
        loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
        pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
                loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
@@ -111,6 +154,10 @@ void __init prom_init_env(void)
                case PRID_REV_LOONGSON3A:
                        cpu_clock_freq = 900000000;
                        break;
+               case PRID_REV_LOONGSON3B_R1:
+               case PRID_REV_LOONGSON3B_R2:
+                       cpu_clock_freq = 1000000000;
+                       break;
                default:
                        cpu_clock_freq = 100000000;
                        break;
index f37fe54..f6af3ab 100644 (file)
@@ -30,7 +30,11 @@ void __init prom_init(void)
        set_io_port_base((unsigned long)
                ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+#ifdef CONFIG_NUMA
+       prom_init_numa_memory();
+#else
        prom_init_memory();
+#endif
 
        /*init the uart base address */
        prom_init_uart_base();
index f55e07a..a6b67cc 100644 (file)
@@ -79,7 +79,7 @@ int __weak wakeup_loongson(void)
 static void wait_for_wakeup_events(void)
 {
        while (!wakeup_loongson())
-               LOONGSON_CHIPCFG0 &= ~0x7;
+               LOONGSON_CHIPCFG(0) &= ~0x7;
 }
 
 /*
@@ -102,15 +102,15 @@ static void loongson_suspend_enter(void)
 
        stop_perf_counters();
 
-       cached_cpu_freq = LOONGSON_CHIPCFG0;
+       cached_cpu_freq = LOONGSON_CHIPCFG(0);
 
        /* Put CPU into wait mode */
-       LOONGSON_CHIPCFG0 &= ~0x7;
+       LOONGSON_CHIPCFG(0) &= ~0x7;
 
        /* wait for the given events to wakeup cpu from wait mode */
        wait_for_wakeup_events();
 
-       LOONGSON_CHIPCFG0 = cached_cpu_freq;
+       LOONGSON_CHIPCFG(0) = cached_cpu_freq;
        mmiowb();
 }
 
index 1eed38e..a217061 100644 (file)
@@ -114,9 +114,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 
        clk->rate = rate;
 
-       regval = LOONGSON_CHIPCFG0;
+       regval = LOONGSON_CHIPCFG(0);
        regval = (regval & ~0x7) | (pos->driver_data - 1);
-       LOONGSON_CHIPCFG0 = regval;
+       LOONGSON_CHIPCFG(0) = regval;
 
        return ret;
 }
index 90962a3..79ac694 100644 (file)
@@ -28,7 +28,7 @@ static void reset_cpu(void)
         * reset cpu to full speed, this is needed when enabling cpu frequency
         * scalling
         */
-       LOONGSON_CHIPCFG0 |= 0x7;
+       LOONGSON_CHIPCFG(0) |= 0x7;
 }
 
 /* reset support for fuloong2f */
index 70152b2..b4df775 100644 (file)
@@ -1,6 +1,8 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y                  += irq.o
+obj-y                  += irq.o cop2-ex.o
 
 obj-$(CONFIG_SMP)      += smp.o
+
+obj-$(CONFIG_NUMA)     += numa.o
diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c
new file mode 100644 (file)
index 0000000..9182e8d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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) 2014 Lemote Corporation.
+ *   written by Huacai Chen <chenhc@lemote.com>
+ *
+ * based on arch/mips/cavium-octeon/cpu.c
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+
+#include <asm/fpu.h>
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+
+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
+       void *data)
+{
+       int fpu_enabled;
+       int fr = !test_thread_flag(TIF_32BIT_FPREGS);
+
+       switch (action) {
+       case CU2_EXCEPTION:
+               preempt_disable();
+               fpu_enabled = read_c0_status() & ST0_CU1;
+               if (!fr)
+                       set_c0_status(ST0_CU1 | ST0_CU2);
+               else
+                       set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR);
+               enable_fpu_hazard();
+               KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2);
+               if (fr)
+                       KSTK_STATUS(current) |= ST0_FR;
+               else
+                       KSTK_STATUS(current) &= ~ST0_FR;
+               /* If FPU is enabled, we needn't init or restore fp */
+               if(!fpu_enabled) {
+                       set_thread_flag(TIF_USEDFPU);
+                       if (!used_math()) {
+                               _init_fpu();
+                               set_used_math();
+                       } else
+                               _restore_fp(current);
+               }
+               preempt_enable();
+
+               return NOTIFY_STOP;     /* Don't call default notifier */
+       }
+
+       return NOTIFY_OK;               /* Let default notifier send signals */
+}
+
+static int __init loongson_cu2_setup(void)
+{
+       return cu2_notifier(loongson_cu2_call, 0);
+}
+early_initcall(loongson_cu2_setup);
index f240828..ca1c62a 100644 (file)
@@ -7,6 +7,8 @@
 #include <asm/i8259.h>
 #include <asm/mipsregs.h>
 
+#include "smp.h"
+
 unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
 
 static void ht_irqdispatch(void)
@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(struct irq_data *d)
        /* Workaround: UART IRQ may deliver to any core */
        if (d->irq == LOONGSON_UART_IRQ) {
                int cpu = smp_processor_id();
-
-               LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
-               LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+               int node_id = cpu / loongson_sysconf.cores_per_node;
+               int core_id = cpu % loongson_sysconf.cores_per_node;
+               u64 intenclr_addr = smp_group[node_id] |
+                       (u64)(&LOONGSON_INT_ROUTER_INTENCLR);
+               u64 introuter_lpc_addr = smp_group[node_id] |
+                       (u64)(&LOONGSON_INT_ROUTER_LPC);
+
+               *(volatile u32 *)intenclr_addr = 1 << 10;
+               *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
        }
 }
 
@@ -64,9 +72,15 @@ static inline void unmask_loongson_irq(struct irq_data *d)
        /* Workaround: UART IRQ may deliver to any core */
        if (d->irq == LOONGSON_UART_IRQ) {
                int cpu = smp_processor_id();
-
-               LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
-               LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+               int node_id = cpu / loongson_sysconf.cores_per_node;
+               int core_id = cpu % loongson_sysconf.cores_per_node;
+               u64 intenset_addr = smp_group[node_id] |
+                       (u64)(&LOONGSON_INT_ROUTER_INTENSET);
+               u64 introuter_lpc_addr = smp_group[node_id] |
+                       (u64)(&LOONGSON_INT_ROUTER_LPC);
+
+               *(volatile u32 *)intenset_addr = 1 << 10;
+               *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
        }
 
        set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
new file mode 100644 (file)
index 0000000..ca025a6
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+#include <boot_param.h>
+
+static struct node_data prealloc__node_data[MAX_NUMNODES];
+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+struct node_data *__node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(__node_data);
+
+static void enable_lpa(void)
+{
+       unsigned long value;
+
+       value = __read_32bit_c0_register($16, 3);
+       value |= 0x00000080;
+       __write_32bit_c0_register($16, 3, value);
+       value = __read_32bit_c0_register($16, 3);
+       pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
+
+       value = __read_32bit_c0_register($5, 1);
+       value |= 0x20000000;
+       __write_32bit_c0_register($5, 1, value);
+       value = __read_32bit_c0_register($5, 1);
+       pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
+}
+
+static void cpu_node_probe(void)
+{
+       int i;
+
+       nodes_clear(node_possible_map);
+       nodes_clear(node_online_map);
+       for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
+               node_set_state(num_online_nodes(), N_POSSIBLE);
+               node_set_online(num_online_nodes());
+       }
+
+       pr_info("NUMA: Discovered %d cpus on %d nodes\n",
+               loongson_sysconf.nr_cpus, num_online_nodes());
+}
+
+static int __init compute_node_distance(int row, int col)
+{
+       int package_row = row * loongson_sysconf.cores_per_node /
+                               loongson_sysconf.cores_per_package;
+       int package_col = col * loongson_sysconf.cores_per_node /
+                               loongson_sysconf.cores_per_package;
+
+       if (col == row)
+               return 0;
+       else if (package_row == package_col)
+               return 40;
+       else
+               return 100;
+}
+
+static void __init init_topology_matrix(void)
+{
+       int row, col;
+
+       for (row = 0; row < MAX_NUMNODES; row++)
+               for (col = 0; col < MAX_NUMNODES; col++)
+                       __node_distances[row][col] = -1;
+
+       for_each_online_node(row) {
+               for_each_online_node(col) {
+                       __node_distances[row][col] =
+                               compute_node_distance(row, col);
+               }
+       }
+}
+
+static unsigned long nid_to_addroffset(unsigned int nid)
+{
+       unsigned long result;
+       switch (nid) {
+       case 0:
+       default:
+               result = NODE0_ADDRSPACE_OFFSET;
+               break;
+       case 1:
+               result = NODE1_ADDRSPACE_OFFSET;
+               break;
+       case 2:
+               result = NODE2_ADDRSPACE_OFFSET;
+               break;
+       case 3:
+               result = NODE3_ADDRSPACE_OFFSET;
+               break;
+       }
+       return result;
+}
+
+static void __init szmem(unsigned int node)
+{
+       u32 i, mem_type;
+       static unsigned long num_physpages = 0;
+       u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+
+       /* Parse memory information and activate */
+       for (i = 0; i < loongson_memmap->nr_map; i++) {
+               node_id = loongson_memmap->map[i].node_id;
+               if (node_id != node)
+                       continue;
+
+               mem_type = loongson_memmap->map[i].mem_type;
+               mem_size = loongson_memmap->map[i].mem_size;
+               mem_start = loongson_memmap->map[i].mem_start;
+
+               switch (mem_type) {
+               case SYSTEM_RAM_LOW:
+                       start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+                       node_psize = (mem_size << 20) >> PAGE_SHIFT;
+                       end_pfn  = start_pfn + node_psize;
+                       num_physpages += node_psize;
+                       pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+                               (u32)node_id, mem_type, mem_start, mem_size);
+                       pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+                               start_pfn, end_pfn, num_physpages);
+                       add_memory_region((node_id << 44) + mem_start,
+                               (u64)mem_size << 20, BOOT_MEM_RAM);
+                       memblock_add_node(PFN_PHYS(start_pfn),
+                               PFN_PHYS(end_pfn - start_pfn), node);
+                       break;
+               case SYSTEM_RAM_HIGH:
+                       start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+                       node_psize = (mem_size << 20) >> PAGE_SHIFT;
+                       end_pfn  = start_pfn + node_psize;
+                       num_physpages += node_psize;
+                       pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+                               (u32)node_id, mem_type, mem_start, mem_size);
+                       pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+                               start_pfn, end_pfn, num_physpages);
+                       add_memory_region((node_id << 44) + mem_start,
+                               (u64)mem_size << 20, BOOT_MEM_RAM);
+                       memblock_add_node(PFN_PHYS(start_pfn),
+                               PFN_PHYS(end_pfn - start_pfn), node);
+                       break;
+               case MEM_RESERVED:
+                       pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+                               (u32)node_id, mem_type, mem_start, mem_size);
+                       add_memory_region((node_id << 44) + mem_start,
+                               (u64)mem_size << 20, BOOT_MEM_RESERVED);
+                       memblock_reserve(((node_id << 44) + mem_start),
+                               mem_size << 20);
+                       break;
+               }
+       }
+}
+
+static void __init node_mem_init(unsigned int node)
+{
+       unsigned long bootmap_size;
+       unsigned long node_addrspace_offset;
+       unsigned long start_pfn, end_pfn, freepfn;
+
+       node_addrspace_offset = nid_to_addroffset(node);
+       pr_info("Node%d's addrspace_offset is 0x%lx\n",
+                       node, node_addrspace_offset);
+
+       get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+       freepfn = start_pfn;
+       if (node == 0)
+               freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
+       pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
+               node, start_pfn, end_pfn, freepfn);
+
+       __node_data[node] = prealloc__node_data + node;
+
+       NODE_DATA(node)->bdata = &bootmem_node_data[node];
+       NODE_DATA(node)->node_start_pfn = start_pfn;
+       NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
+
+       bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
+                                       start_pfn, end_pfn);
+       free_bootmem_with_active_regions(node, end_pfn);
+       if (node == 0) /* used by finalize_initrd() */
+               max_low_pfn = end_pfn;
+
+       /* This is reserved for the kernel and bdata->node_bootmem_map */
+       reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
+               ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
+               BOOTMEM_DEFAULT);
+
+       if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
+               /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+               reserve_bootmem_node(NODE_DATA(node),
+                               (node_addrspace_offset | 0xff800000),
+                               8 << 20, BOOTMEM_DEFAULT);
+       }
+
+       sparse_memory_present_with_active_regions(node);
+}
+
+static __init void prom_meminit(void)
+{
+       unsigned int node, cpu;
+
+       cpu_node_probe();
+       init_topology_matrix();
+
+       for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
+               if (node_online(node)) {
+                       szmem(node);
+                       node_mem_init(node);
+                       cpus_clear(__node_data[(node)]->cpumask);
+               }
+       }
+       for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
+               node = cpu / loongson_sysconf.cores_per_node;
+               if (node >= num_online_nodes())
+                       node = 0;
+               pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
+               cpu_set(cpu, __node_data[(node)]->cpumask);
+       }
+}
+
+void __init paging_init(void)
+{
+       unsigned node;
+       unsigned long zones_size[MAX_NR_ZONES] = {0, };
+
+       pagetable_init();
+
+       for_each_online_node(node) {
+               unsigned long  start_pfn, end_pfn;
+
+               get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+
+               if (end_pfn > max_low_pfn)
+                       max_low_pfn = end_pfn;
+       }
+#ifdef CONFIG_ZONE_DMA32
+       zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
+#endif
+       zones_size[ZONE_NORMAL] = max_low_pfn;
+       free_area_init_nodes(zones_size);
+}
+
+void __init mem_init(void)
+{
+       high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
+       free_all_bootmem();
+       setup_zero_pages();     /* This comes from node 0 */
+       mem_init_print_info(NULL);
+}
+
+/* All PCI device belongs to logical Node-0 */
+int pcibus_to_node(struct pci_bus *bus)
+{
+       return 0;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+
+void __init prom_init_numa_memory(void)
+{
+       enable_lpa();
+       prom_meminit();
+}
+EXPORT_SYMBOL(prom_init_numa_memory);
index 1e88940..74e827b 100644 (file)
 DEFINE_PER_CPU(int, cpu_state);
 DEFINE_PER_CPU(uint32_t, core0_c0count);
 
+static void *ipi_set0_regs[16];
+static void *ipi_clear0_regs[16];
+static void *ipi_status0_regs[16];
+static void *ipi_en0_regs[16];
+static void *ipi_mailbox_buf[16];
+
 /* read a 32bit value from ipi register */
 #define loongson3_ipi_read32(addr) readl(addr)
 /* read a 64bit value from ipi register */
@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count);
                __wbflush();                    \
        } while (0)
 
-static void *ipi_set0_regs[] = {
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
-};
+static void ipi_set0_regs_init(void)
+{
+       ipi_set0_regs[0] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
+       ipi_set0_regs[1] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
+       ipi_set0_regs[2] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
+       ipi_set0_regs[3] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
+       ipi_set0_regs[4] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
+       ipi_set0_regs[5] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
+       ipi_set0_regs[6] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
+       ipi_set0_regs[7] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
+       ipi_set0_regs[8] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
+       ipi_set0_regs[9] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
+       ipi_set0_regs[10] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
+       ipi_set0_regs[11] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
+       ipi_set0_regs[12] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
+       ipi_set0_regs[13] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
+       ipi_set0_regs[14] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
+       ipi_set0_regs[15] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
+}
 
-static void *ipi_clear0_regs[] = {
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
-};
+static void ipi_clear0_regs_init(void)
+{
+       ipi_clear0_regs[0] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
+       ipi_clear0_regs[1] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
+       ipi_clear0_regs[2] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
+       ipi_clear0_regs[3] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
+       ipi_clear0_regs[4] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
+       ipi_clear0_regs[5] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
+       ipi_clear0_regs[6] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
+       ipi_clear0_regs[7] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
+       ipi_clear0_regs[8] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
+       ipi_clear0_regs[9] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
+       ipi_clear0_regs[10] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
+       ipi_clear0_regs[11] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
+       ipi_clear0_regs[12] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
+       ipi_clear0_regs[13] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
+       ipi_clear0_regs[14] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
+       ipi_clear0_regs[15] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
+}
 
-static void *ipi_status0_regs[] = {
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
-};
+static void ipi_status0_regs_init(void)
+{
+       ipi_status0_regs[0] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
+       ipi_status0_regs[1] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
+       ipi_status0_regs[2] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
+       ipi_status0_regs[3] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
+       ipi_status0_regs[4] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
+       ipi_status0_regs[5] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
+       ipi_status0_regs[6] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
+       ipi_status0_regs[7] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
+       ipi_status0_regs[8] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
+       ipi_status0_regs[9] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
+       ipi_status0_regs[10] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
+       ipi_status0_regs[11] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
+       ipi_status0_regs[12] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
+       ipi_status0_regs[13] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
+       ipi_status0_regs[14] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
+       ipi_status0_regs[15] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
+}
 
-static void *ipi_en0_regs[] = {
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
-};
+static void ipi_en0_regs_init(void)
+{
+       ipi_en0_regs[0] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
+       ipi_en0_regs[1] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
+       ipi_en0_regs[2] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
+       ipi_en0_regs[3] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
+       ipi_en0_regs[4] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
+       ipi_en0_regs[5] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
+       ipi_en0_regs[6] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
+       ipi_en0_regs[7] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
+       ipi_en0_regs[8] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
+       ipi_en0_regs[9] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
+       ipi_en0_regs[10] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
+       ipi_en0_regs[11] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
+       ipi_en0_regs[12] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
+       ipi_en0_regs[13] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
+       ipi_en0_regs[14] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
+       ipi_en0_regs[15] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
+}
 
-static void *ipi_mailbox_buf[] = {
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
-       (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
-};
+static void ipi_mailbox_buf_init(void)
+{
+       ipi_mailbox_buf[0] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
+       ipi_mailbox_buf[1] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
+       ipi_mailbox_buf[2] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
+       ipi_mailbox_buf[3] = (void *)
+               (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
+       ipi_mailbox_buf[4] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
+       ipi_mailbox_buf[5] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
+       ipi_mailbox_buf[6] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
+       ipi_mailbox_buf[7] = (void *)
+               (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
+       ipi_mailbox_buf[8] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
+       ipi_mailbox_buf[9] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
+       ipi_mailbox_buf[10] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
+       ipi_mailbox_buf[11] = (void *)
+               (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
+       ipi_mailbox_buf[12] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
+       ipi_mailbox_buf[13] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
+       ipi_mailbox_buf[14] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
+       ipi_mailbox_buf[15] = (void *)
+               (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
+}
 
 /*
  * Simple enough, just poke the appropriate ipi register
@@ -203,6 +294,8 @@ static void loongson3_init_secondary(void)
        for (i = 0; i < loongson_sysconf.nr_cpus; i++)
                loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
 
+       cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
+       cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
        per_cpu(cpu_state, cpu) = CPU_ONLINE;
 
        i = 0;
@@ -246,6 +339,11 @@ static void __init loongson3_smp_setup(void)
                __cpu_number_map[i] = ++num;
                __cpu_logical_map[num] = i;
        }
+       ipi_set0_regs_init();
+       ipi_clear0_regs_init();
+       ipi_status0_regs_init();
+       ipi_en0_regs_init();
+       ipi_mailbox_buf_init();
        pr_info("Detected %i available secondary CPU(s)\n", num);
 }
 
@@ -313,7 +411,7 @@ static void loongson3_cpu_die(unsigned int cpu)
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
  * called via CKSEG1 (uncached and unmmaped) */
-static void loongson3_play_dead(int *state_addr)
+static void loongson3a_play_dead(int *state_addr)
 {
        register int val;
        register long cpuid, core, node, count;
@@ -375,6 +473,70 @@ static void loongson3_play_dead(int *state_addr)
                : "a1");
 }
 
+static void loongson3b_play_dead(int *state_addr)
+{
+       register int val;
+       register long cpuid, core, node, count;
+       register void *addr, *base, *initfunc;
+
+       __asm__ __volatile__(
+               "   .set push                     \n"
+               "   .set noreorder                \n"
+               "   li %[addr], 0x80000000        \n" /* KSEG0 */
+               "1: cache 0, 0(%[addr])           \n" /* flush L1 ICache */
+               "   cache 0, 1(%[addr])           \n"
+               "   cache 0, 2(%[addr])           \n"
+               "   cache 0, 3(%[addr])           \n"
+               "   cache 1, 0(%[addr])           \n" /* flush L1 DCache */
+               "   cache 1, 1(%[addr])           \n"
+               "   cache 1, 2(%[addr])           \n"
+               "   cache 1, 3(%[addr])           \n"
+               "   addiu %[sets], %[sets], -1    \n"
+               "   bnez  %[sets], 1b             \n"
+               "   addiu %[addr], %[addr], 0x20  \n"
+               "   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
+               "   sw    %[val], (%[state_addr]) \n"
+               "   sync                          \n"
+               "   cache 21, (%[state_addr])     \n" /* flush entry of *state_addr */
+               "   .set pop                      \n"
+               : [addr] "=&r" (addr), [val] "=&r" (val)
+               : [state_addr] "r" (state_addr),
+                 [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+
+       __asm__ __volatile__(
+               "   .set push                         \n"
+               "   .set noreorder                    \n"
+               "   .set mips64                       \n"
+               "   mfc0  %[cpuid], $15, 1            \n"
+               "   andi  %[cpuid], 0x3ff             \n"
+               "   dli   %[base], 0x900000003ff01000 \n"
+               "   andi  %[core], %[cpuid], 0x3      \n"
+               "   sll   %[core], 8                  \n" /* get core id */
+               "   or    %[base], %[base], %[core]   \n"
+               "   andi  %[node], %[cpuid], 0xc      \n"
+               "   dsll  %[node], 42                 \n" /* get node id */
+               "   or    %[base], %[base], %[node]   \n"
+               "   dsrl  %[node], 30                 \n" /* 15:14 */
+               "   or    %[base], %[base], %[node]   \n"
+               "1: li    %[count], 0x100             \n" /* wait for init loop */
+               "2: bnez  %[count], 2b                \n" /* limit mailbox access */
+               "   addiu %[count], -1                \n"
+               "   ld    %[initfunc], 0x20(%[base])  \n" /* get PC via mailbox */
+               "   beqz  %[initfunc], 1b             \n"
+               "   nop                               \n"
+               "   ld    $sp, 0x28(%[base])          \n" /* get SP via mailbox */
+               "   ld    $gp, 0x30(%[base])          \n" /* get GP via mailbox */
+               "   ld    $a1, 0x38(%[base])          \n"
+               "   jr    %[initfunc]                 \n" /* jump to initial PC */
+               "   nop                               \n"
+               "   .set pop                          \n"
+               : [core] "=&r" (core), [node] "=&r" (node),
+                 [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+                 [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+               : /* No Input */
+               : "a1");
+}
+
 void play_dead(void)
 {
        int *state_addr;
@@ -382,13 +544,48 @@ void play_dead(void)
        void (*play_dead_at_ckseg1)(int *);
 
        idle_task_exit();
-       play_dead_at_ckseg1 =
-               (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+       switch (loongson_sysconf.cputype) {
+       case Loongson_3A:
+       default:
+               play_dead_at_ckseg1 =
+                       (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+               break;
+       case Loongson_3B:
+               play_dead_at_ckseg1 =
+                       (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
+               break;
+       }
        state_addr = &per_cpu(cpu_state, cpu);
        mb();
        play_dead_at_ckseg1(state_addr);
 }
 
+void loongson3_disable_clock(int cpu)
+{
+       uint64_t core_id = cpu_data[cpu].core;
+       uint64_t package_id = cpu_data[cpu].package;
+
+       if (loongson_sysconf.cputype == Loongson_3A) {
+               LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
+       } else if (loongson_sysconf.cputype == Loongson_3B) {
+               if (!cpuhotplug_workaround)
+                       LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
+       }
+}
+
+void loongson3_enable_clock(int cpu)
+{
+       uint64_t core_id = cpu_data[cpu].core;
+       uint64_t package_id = cpu_data[cpu].package;
+
+       if (loongson_sysconf.cputype == Loongson_3A) {
+               LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
+       } else if (loongson_sysconf.cputype == Loongson_3B) {
+               if (!cpuhotplug_workaround)
+                       LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
+       }
+}
+
 #define CPU_POST_DEAD_FROZEN   (CPU_POST_DEAD | CPU_TASKS_FROZEN)
 static int loongson3_cpu_callback(struct notifier_block *nfb,
        unsigned long action, void *hcpu)
@@ -399,12 +596,12 @@ static int loongson3_cpu_callback(struct notifier_block *nfb,
        case CPU_POST_DEAD:
        case CPU_POST_DEAD_FROZEN:
                pr_info("Disable clock for CPU#%d\n", cpu);
-               LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+               loongson3_disable_clock(cpu);
                break;
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
                pr_info("Enable clock for CPU#%d\n", cpu);
-               LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+               loongson3_enable_clock(cpu);
                break;
        }
 
index 3453e8c..d98ff65 100644 (file)
@@ -1,29 +1,30 @@
 #ifndef __LOONGSON_SMP_H_
 #define __LOONGSON_SMP_H_
 
-/* for Loongson-3A smp support */
+/* for Loongson-3 smp support */
+extern unsigned long long smp_group[4];
 
 /* 4 groups(nodes) in maximum in numa case */
-#define  SMP_CORE_GROUP0_BASE    0x900000003ff01000
-#define  SMP_CORE_GROUP1_BASE    0x900010003ff01000
-#define  SMP_CORE_GROUP2_BASE    0x900020003ff01000
-#define  SMP_CORE_GROUP3_BASE    0x900030003ff01000
+#define SMP_CORE_GROUP0_BASE   (smp_group[0])
+#define SMP_CORE_GROUP1_BASE   (smp_group[1])
+#define SMP_CORE_GROUP2_BASE   (smp_group[2])
+#define SMP_CORE_GROUP3_BASE   (smp_group[3])
 
 /* 4 cores in each group(node) */
-#define  SMP_CORE0_OFFSET  0x000
-#define  SMP_CORE1_OFFSET  0x100
-#define  SMP_CORE2_OFFSET  0x200
-#define  SMP_CORE3_OFFSET  0x300
+#define SMP_CORE0_OFFSET  0x000
+#define SMP_CORE1_OFFSET  0x100
+#define SMP_CORE2_OFFSET  0x200
+#define SMP_CORE3_OFFSET  0x300
 
 /* ipi registers offsets */
-#define  STATUS0  0x00
-#define  EN0      0x04
-#define  SET0     0x08
-#define  CLEAR0   0x0c
-#define  STATUS1  0x10
-#define  MASK1    0x14
-#define  SET1     0x18
-#define  CLEAR1   0x1c
-#define  BUF      0x20
+#define STATUS0  0x00
+#define EN0      0x04
+#define SET0     0x08
+#define CLEAR0   0x0c
+#define STATUS1  0x10
+#define MASK1    0x14
+#define SET1     0x18
+#define CLEAR1   0x1c
+#define BUF      0x20
 
 #endif
index 736c17a..bf0fc6b 100644 (file)
@@ -1827,7 +1827,7 @@ dcopuop:
        case -1:
 
                if (cpu_has_mips_4_5_r)
-                       cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
+                       cbit = fpucondbit[MIPSInst_FD(ir) >> 2];
                else
                        cbit = FPU_CSR_COND;
                if (rv.w)
index f2e8302..fbcd867 100644 (file)
@@ -1230,19 +1230,19 @@ static void probe_pcache(void)
        case CPU_R14000:
                break;
 
+       case CPU_74K:
+       case CPU_1074K:
+               alias_74k_erratum(c);
+               /* Fall through. */
        case CPU_M14KC:
        case CPU_M14KEC:
        case CPU_24K:
        case CPU_34K:
-       case CPU_74K:
        case CPU_1004K:
-       case CPU_1074K:
        case CPU_INTERAPTIV:
        case CPU_P5600:
        case CPU_PROAPTIV:
        case CPU_M5150:
-               if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
-                       alias_74k_erratum(c);
                if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
                    (c->icache.waysize > PAGE_SIZE))
                        c->icache.flags |= MIPS_CACHE_ALIASES;
index 6e44133..571aab0 100644 (file)
@@ -325,6 +325,38 @@ static inline void mem_init_free_highmem(void)
 #endif
 }
 
+unsigned __weak platform_maar_init(unsigned num_maars)
+{
+       return 0;
+}
+
+static void maar_init(void)
+{
+       unsigned num_maars, used, i;
+
+       if (!cpu_has_maar)
+               return;
+
+       /* Detect the number of MAARs */
+       write_c0_maari(~0);
+       back_to_back_c0_hazard();
+       num_maars = read_c0_maari() + 1;
+
+       /* MAARs should be in pairs */
+       WARN_ON(num_maars % 2);
+
+       /* Configure the required MAARs */
+       used = platform_maar_init(num_maars / 2);
+
+       /* Disable any further MAARs */
+       for (i = (used * 2); i < num_maars; i++) {
+               write_c0_maari(i);
+               back_to_back_c0_hazard();
+               write_c0_maar(0);
+               back_to_back_c0_hazard();
+       }
+}
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -337,6 +369,7 @@ void __init mem_init(void)
 #endif
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
+       maar_init();
        free_all_bootmem();
        setup_zero_pages();     /* Setup zeroed pages.  */
        mem_init_free_highmem();
index d657493..4094bbd 100644 (file)
@@ -158,7 +158,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
        int cpu = smp_processor_id();
 
-       if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+       if (cpu_context(cpu, vma->vm_mm) != 0) {
                unsigned long flags;
                int oldpid, newpid, idx;
 
index 3914e27..fa6ebd4 100644 (file)
@@ -57,6 +57,7 @@ void local_flush_tlb_all(void)
        local_irq_save(flags);
        /* Save old context and create impossible VPN2 value */
        old_ctx = read_c0_entryhi();
+       htw_stop();
        write_c0_entrylo0(0);
        write_c0_entrylo1(0);
 
@@ -90,6 +91,7 @@ void local_flush_tlb_all(void)
        }
        tlbw_use_hazard();
        write_c0_entryhi(old_ctx);
+       htw_start();
        flush_itlb();
        local_irq_restore(flags);
 }
@@ -131,6 +133,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                        int oldpid = read_c0_entryhi();
                        int newpid = cpu_asid(cpu, mm);
 
+                       htw_stop();
                        while (start < end) {
                                int idx;
 
@@ -151,6 +154,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                        }
                        tlbw_use_hazard();
                        write_c0_entryhi(oldpid);
+                       htw_start();
                } else {
                        drop_mmu_context(mm, cpu);
                }
@@ -174,6 +178,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
                start &= (PAGE_MASK << 1);
                end += ((PAGE_SIZE << 1) - 1);
                end &= (PAGE_MASK << 1);
+               htw_stop();
 
                while (start < end) {
                        int idx;
@@ -195,6 +200,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
                }
                tlbw_use_hazard();
                write_c0_entryhi(pid);
+               htw_start();
        } else {
                local_flush_tlb_all();
        }
@@ -214,6 +220,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
                page &= (PAGE_MASK << 1);
                local_irq_save(flags);
                oldpid = read_c0_entryhi();
+               htw_stop();
                write_c0_entryhi(page | newpid);
                mtc0_tlbw_hazard();
                tlb_probe();
@@ -231,6 +238,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
        finish:
                write_c0_entryhi(oldpid);
+               htw_start();
                flush_itlb_vm(vma);
                local_irq_restore(flags);
        }
@@ -247,6 +255,7 @@ void local_flush_tlb_one(unsigned long page)
 
        local_irq_save(flags);
        oldpid = read_c0_entryhi();
+       htw_stop();
        page &= (PAGE_MASK << 1);
        write_c0_entryhi(page);
        mtc0_tlbw_hazard();
@@ -263,6 +272,7 @@ void local_flush_tlb_one(unsigned long page)
                tlbw_use_hazard();
        }
        write_c0_entryhi(oldpid);
+       htw_start();
        flush_itlb();
        local_irq_restore(flags);
 }
@@ -351,6 +361,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        local_irq_save(flags);
        /* Save old context and create impossible VPN2 value */
        old_ctx = read_c0_entryhi();
+       htw_stop();
        old_pagemask = read_c0_pagemask();
        wired = read_c0_wired();
        write_c0_wired(wired + 1);
@@ -366,6 +377,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 
        write_c0_entryhi(old_ctx);
        tlbw_use_hazard();      /* What is the hazard here? */
+       htw_start();
        write_c0_pagemask(old_pagemask);
        local_flush_tlb_all();
        local_irq_restore(flags);
@@ -391,6 +403,51 @@ int __init has_transparent_hugepage(void)
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
 
+/*
+ * Used for loading TLB entries before trap_init() has started, when we
+ * don't actually want to add a wired entry which remains throughout the
+ * lifetime of the system
+ */
+
+int temp_tlb_entry __cpuinitdata;
+
+__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+                              unsigned long entryhi, unsigned long pagemask)
+{
+       int ret = 0;
+       unsigned long flags;
+       unsigned long wired;
+       unsigned long old_pagemask;
+       unsigned long old_ctx;
+
+       local_irq_save(flags);
+       /* Save old context and create impossible VPN2 value */
+       old_ctx = read_c0_entryhi();
+       old_pagemask = read_c0_pagemask();
+       wired = read_c0_wired();
+       if (--temp_tlb_entry < wired) {
+               printk(KERN_WARNING
+                      "No TLB space left for add_temporary_entry\n");
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       write_c0_index(temp_tlb_entry);
+       write_c0_pagemask(pagemask);
+       write_c0_entryhi(entryhi);
+       write_c0_entrylo0(entrylo0);
+       write_c0_entrylo1(entrylo1);
+       mtc0_tlbw_hazard();
+       tlb_write_indexed();
+       tlbw_use_hazard();
+
+       write_c0_entryhi(old_ctx);
+       write_c0_pagemask(old_pagemask);
+out:
+       local_irq_restore(flags);
+       return ret;
+}
+
 static int ntlb;
 static int __init set_ntlb(char *str)
 {
@@ -431,6 +488,8 @@ static void r4k_tlb_configure(void)
                write_c0_pagegrain(pg);
        }
 
+       temp_tlb_entry = current_cpu_data.tlbsize - 1;
+
        /* From this point on the ARC firmware is dead.  */
        local_flush_tlb_all();
 
index e80e10b..a08dd53 100644 (file)
@@ -429,6 +429,7 @@ static void build_r3000_tlb_refill_handler(void)
                 (unsigned int)(p - tlb_handler));
 
        memcpy((void *)ebase, tlb_handler, 0x80);
+       local_flush_icache_range(ebase, ebase + 0x80);
 
        dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
 }
@@ -1299,6 +1300,7 @@ static void build_r4000_tlb_refill_handler(void)
        }
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_l_tlb_huge_update(&l, p);
+       UASM_i_LW(&p, K0, 0, K1);
        build_huge_update_entries(&p, htlb_info.huge_pte, K1);
        build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
                                   htlb_info.restore_scratch);
@@ -1415,6 +1417,7 @@ static void build_r4000_tlb_refill_handler(void)
                 final_len);
 
        memcpy((void *)ebase, final_handler, 0x100);
+       local_flush_icache_range(ebase, ebase + 0x100);
 
        dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
@@ -1919,7 +1922,7 @@ static void build_r4000_tlb_load_handler(void)
        if (m4kc_tlbp_war())
                build_tlb_probe_entry(&p);
 
-       if (cpu_has_rixi) {
+       if (cpu_has_rixi && !cpu_has_rixiex) {
                /*
                 * If the page is not _PAGE_VALID, RI or XI could not
                 * have triggered it.  Skip the expensive test..
@@ -1986,7 +1989,7 @@ static void build_r4000_tlb_load_handler(void)
        build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
        build_tlb_probe_entry(&p);
 
-       if (cpu_has_rixi) {
+       if (cpu_has_rixi && !cpu_has_rixiex) {
                /*
                 * If the page is not _PAGE_VALID, RI or XI could not
                 * have triggered it.  Skip the expensive test..
@@ -2194,6 +2197,94 @@ static void flush_tlb_handlers(void)
                           (unsigned long)tlbmiss_handler_setup_pgd_end);
 }
 
+static void print_htw_config(void)
+{
+       unsigned long config;
+       unsigned int pwctl;
+       const int field = 2 * sizeof(unsigned long);
+
+       config = read_c0_pwfield();
+       pr_debug("PWField (0x%0*lx): GDI: 0x%02lx  UDI: 0x%02lx  MDI: 0x%02lx  PTI: 0x%02lx  PTEI: 0x%02lx\n",
+               field, config,
+               (config & MIPS_PWFIELD_GDI_MASK) >> MIPS_PWFIELD_GDI_SHIFT,
+               (config & MIPS_PWFIELD_UDI_MASK) >> MIPS_PWFIELD_UDI_SHIFT,
+               (config & MIPS_PWFIELD_MDI_MASK) >> MIPS_PWFIELD_MDI_SHIFT,
+               (config & MIPS_PWFIELD_PTI_MASK) >> MIPS_PWFIELD_PTI_SHIFT,
+               (config & MIPS_PWFIELD_PTEI_MASK) >> MIPS_PWFIELD_PTEI_SHIFT);
+
+       config = read_c0_pwsize();
+       pr_debug("PWSize  (0x%0*lx): GDW: 0x%02lx  UDW: 0x%02lx  MDW: 0x%02lx  PTW: 0x%02lx  PTEW: 0x%02lx\n",
+               field, config,
+               (config & MIPS_PWSIZE_GDW_MASK) >> MIPS_PWSIZE_GDW_SHIFT,
+               (config & MIPS_PWSIZE_UDW_MASK) >> MIPS_PWSIZE_UDW_SHIFT,
+               (config & MIPS_PWSIZE_MDW_MASK) >> MIPS_PWSIZE_MDW_SHIFT,
+               (config & MIPS_PWSIZE_PTW_MASK) >> MIPS_PWSIZE_PTW_SHIFT,
+               (config & MIPS_PWSIZE_PTEW_MASK) >> MIPS_PWSIZE_PTEW_SHIFT);
+
+       pwctl = read_c0_pwctl();
+       pr_debug("PWCtl   (0x%x): PWEn: 0x%x  DPH: 0x%x  HugePg: 0x%x  Psn: 0x%x\n",
+               pwctl,
+               (pwctl & MIPS_PWCTL_PWEN_MASK) >> MIPS_PWCTL_PWEN_SHIFT,
+               (pwctl & MIPS_PWCTL_DPH_MASK) >> MIPS_PWCTL_DPH_SHIFT,
+               (pwctl & MIPS_PWCTL_HUGEPG_MASK) >> MIPS_PWCTL_HUGEPG_SHIFT,
+               (pwctl & MIPS_PWCTL_PSN_MASK) >> MIPS_PWCTL_PSN_SHIFT);
+}
+
+static void config_htw_params(void)
+{
+       unsigned long pwfield, pwsize, ptei;
+       unsigned int config;
+
+       /*
+        * We are using 2-level page tables, so we only need to
+        * setup GDW and PTW appropriately. UDW and MDW will remain 0.
+        * The default value of GDI/UDI/MDI/PTI is 0xc. It is illegal to
+        * write values less than 0xc in these fields because the entire
+        * write will be dropped. As a result of which, we must preserve
+        * the original reset values and overwrite only what we really want.
+        */
+
+       pwfield = read_c0_pwfield();
+       /* re-initialize the GDI field */
+       pwfield &= ~MIPS_PWFIELD_GDI_MASK;
+       pwfield |= PGDIR_SHIFT << MIPS_PWFIELD_GDI_SHIFT;
+       /* re-initialize the PTI field including the even/odd bit */
+       pwfield &= ~MIPS_PWFIELD_PTI_MASK;
+       pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+       /* Set the PTEI right shift */
+       ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
+       pwfield |= ptei;
+       write_c0_pwfield(pwfield);
+       /* Check whether the PTEI value is supported */
+       back_to_back_c0_hazard();
+       pwfield = read_c0_pwfield();
+       if (((pwfield & MIPS_PWFIELD_PTEI_MASK) << MIPS_PWFIELD_PTEI_SHIFT)
+               != ptei) {
+               pr_warn("Unsupported PTEI field value: 0x%lx. HTW will not be enabled",
+                       ptei);
+               /*
+                * Drop option to avoid HTW being enabled via another path
+                * (eg htw_reset())
+                */
+               current_cpu_data.options &= ~MIPS_CPU_HTW;
+               return;
+       }
+
+       pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
+       pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+       write_c0_pwsize(pwsize);
+
+       /* Make sure everything is set before we enable the HTW */
+       back_to_back_c0_hazard();
+
+       /* Enable HTW and disable the rest of the pwctl fields */
+       config = 1 << MIPS_PWCTL_PWEN_SHIFT;
+       write_c0_pwctl(config);
+       pr_info("Hardware Page Table Walker enabled\n");
+
+       print_htw_config();
+}
+
 void build_tlb_refill_handler(void)
 {
        /*
@@ -2258,5 +2349,8 @@ void build_tlb_refill_handler(void)
                }
                if (cpu_has_local_ebase)
                        build_r4000_tlb_refill_handler();
+               if (cpu_has_htw)
+                       config_htw_params();
+
        }
 }
index ecc2785..e4f43ba 100644 (file)
@@ -42,6 +42,10 @@ static unsigned int ipi_map[NR_CPUS];
 
 static DEFINE_RAW_SPINLOCK(mips_irq_lock);
 
+#ifdef CONFIG_MIPS_GIC_IPI
+DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS);
+#endif
+
 static inline int mips_pcibios_iack(void)
 {
        int irq;
@@ -125,16 +129,22 @@ static void malta_hw0_irqdispatch(void)
 
 static void malta_ipi_irqdispatch(void)
 {
-       int irq;
+#ifdef CONFIG_MIPS_GIC_IPI
+       unsigned long irq;
+       DECLARE_BITMAP(pending, GIC_NUM_INTRS);
 
-       if (gic_compare_int())
-               do_IRQ(MIPS_GIC_IRQ_BASE);
+       gic_get_int_mask(pending, ipi_ints);
+
+       irq = find_first_bit(pending, GIC_NUM_INTRS);
 
-       irq = gic_get_int();
-       if (irq < 0)
-               return;  /* interrupt has already been cleared */
+       while (irq < GIC_NUM_INTRS) {
+               do_IRQ(MIPS_GIC_IRQ_BASE + irq);
 
-       do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+               irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1);
+       }
+#endif
+       if (gic_compare_int())
+               do_IRQ(MIPS_GIC_IRQ_BASE);
 }
 
 static void corehi_irqdispatch(void)
@@ -427,8 +437,9 @@ static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
        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].flags = GIC_FLAG_IPI;
+       gic_intr_map[intr].flags = 0;
        ipi_map[cpu] |= (1 << (cpupin + 2));
+       bitmap_set(ipi_ints, intr, 1);
 }
 
 static void __init fill_ipi_map(void)
index 6d97730..0c35dee 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/maar.h>
 #include <asm/sections.h>
 #include <asm/fw/fw.h>
 
@@ -164,3 +165,28 @@ void __init prom_free_prom_memory(void)
                                addr, addr + boot_mem_map.map[i].size);
        }
 }
+
+unsigned platform_maar_init(unsigned num_pairs)
+{
+       phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
+       struct maar_config cfg[] = {
+               /* DRAM preceding I/O */
+               { 0x00000000, 0x0fffffff, MIPS_MAAR_S },
+
+               /* DRAM following I/O */
+               { 0x20000000, mem_end, MIPS_MAAR_S },
+
+               /* DRAM alias in upper half of physical */
+               { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
+       };
+       unsigned i, num_cfg = ARRAY_SIZE(cfg);
+
+       /* If DRAM fits before I/O, drop the region following it */
+       if (physical_memsize <= 0x10000000) {
+               num_cfg--;
+               for (i = 1; i < num_cfg; i++)
+                       cfg[i] = cfg[i + 1];
+       }
+
+       return maar_config(cfg, num_cfg, num_pairs);
+}
index ff8a553..6523d55 100644 (file)
@@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT)           += pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)      += fixup-cobalt.o
 obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)    += fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_LEMOTE_MACH3A)    += fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_LOONGSON_MACH3X)  += fixup-loongson3.o ops-loongson3.o
 obj-$(CONFIG_MIPS_MALTA)       += fixup-malta.o pci-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)   += fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
index 0e046d8..d54ea93 100644 (file)
@@ -199,8 +199,6 @@ static struct {
 
 char *tx4927_pcibios_setup(char *str)
 {
-       unsigned long val;
-
        if (!strncmp(str, "trdyto=", 7)) {
                u8 val = 0;
                if (kstrtou8(str + 7, 0, &val) == 0)
index 563d1f6..c19600a 100644 (file)
@@ -7,6 +7,7 @@
  * Support for all devices (greater than 16) added by David Gathright.
  */
 
+#include <linux/clk.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -364,6 +365,7 @@ static int alchemy_pci_probe(struct platform_device *pdev)
        void __iomem *virt_io;
        unsigned long val;
        struct resource *r;
+       struct clk *c;
        int ret;
 
        /* need at least PCI IRQ mapping table */
@@ -393,11 +395,24 @@ static int alchemy_pci_probe(struct platform_device *pdev)
                goto out1;
        }
 
+       c = clk_get(&pdev->dev, "pci_clko");
+       if (IS_ERR(c)) {
+               dev_err(&pdev->dev, "unable to find PCI clock\n");
+               ret = PTR_ERR(c);
+               goto out2;
+       }
+
+       ret = clk_prepare_enable(c);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot enable PCI clock\n");
+               goto out6;
+       }
+
        ctx->regs = ioremap_nocache(r->start, resource_size(r));
        if (!ctx->regs) {
                dev_err(&pdev->dev, "cannot map pci regs\n");
                ret = -ENODEV;
-               goto out2;
+               goto out5;
        }
 
        /* map parts of the PCI IO area */
@@ -465,12 +480,19 @@ static int alchemy_pci_probe(struct platform_device *pdev)
        register_syscore_ops(&alchemy_pci_pmops);
        register_pci_controller(&ctx->alchemy_pci_ctrl);
 
+       dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
+                clk_get_rate(c) / 1000000);
+
        return 0;
 
 out4:
        iounmap(virt_io);
 out3:
        iounmap(ctx->regs);
+out5:
+       clk_disable_unprepare(c);
+out6:
+       clk_put(c);
 out2:
        release_mem_region(r->start, resource_size(r));
 out1:
index 2513952..7c4598c 100644 (file)
@@ -81,7 +81,7 @@ static int __init plat_of_setup(void)
                panic("device tree not present");
 
        strlcpy(of_ids[0].compatible, soc_info.compatible, len);
-       strncpy(of_ids[1].compatible, "palmbus", len);
+       strlcpy(of_ids[1].compatible, "palmbus", len);
 
        if (of_platform_populate(NULL, of_ids, NULL, NULL))
                panic("failed to populate DT");
index 3af00b2..e31e8cd 100644 (file)
@@ -223,6 +223,7 @@ static struct platform_device rb532_wdt = {
 
 static struct plat_serial8250_port rb532_uart_res[] = {
        {
+               .type           = PORT_16550A,
                .membase        = (char *)KSEG1ADDR(REGBASE + UART0BASE),
                .irq            = UART0_IRQ,
                .regshift       = 2,
@@ -250,28 +251,6 @@ static struct platform_device *rb532_devs[] = {
        &rb532_wdt
 };
 
-static void __init parse_mac_addr(char *macstr)
-{
-       int i, h, l;
-
-       for (i = 0; i < 6; i++) {
-               if (i != 5 && *(macstr + 2) != ':')
-                       return;
-
-               h = hex_to_bin(*macstr++);
-               if (h == -1)
-                       return;
-
-               l = hex_to_bin(*macstr++);
-               if (l == -1)
-                       return;
-
-               macstr++;
-               korina_dev0_data.mac[i] = (h << 4) + l;
-       }
-}
-
-
 /* NAND definitions */
 #define NAND_CHIP_DELAY 25
 
@@ -333,7 +312,10 @@ static int __init plat_setup_devices(void)
 static int __init setup_kmac(char *s)
 {
        printk(KERN_INFO "korina mac = %s\n", s);
-       parse_mac_addr(s);
+       if (!mac_pton(s, korina_dev0_data.mac)) {
+               printk(KERN_ERR "Invalid mac\n");
+               return -EINVAL;
+       }
        return 0;
 }
 
index 8e52446..8f1b86d 100644 (file)
@@ -27,8 +27,14 @@ static struct {
        { .name = "SGI GR2/GR3", .id = 0x7f },
 };
 
+static void gio_bus_release(struct device *dev)
+{
+       kfree(dev);
+}
+
 static struct device gio_bus = {
        .init_name = "gio",
+       .release = &gio_bus_release,
 };
 
 /**
@@ -413,8 +419,10 @@ int __init ip22_gio_init(void)
        int ret;
 
        ret = device_register(&gio_bus);
-       if (ret)
+       if (ret) {
+               put_device(&gio_bus);
                return ret;
+       }
 
        ret = bus_register(&gio_bus_type);
        if (!ret) {
index 4642f56..566c58b 100644 (file)
@@ -83,6 +83,11 @@ static struct bus_type tx_7segled_subsys = {
        .dev_name       = "7segled",
 };
 
+static void tx_7segled_release(struct device *dev)
+{
+       kfree(dev);
+}
+
 static int __init tx_7segled_init_sysfs(void)
 {
        int error, i;
@@ -103,11 +108,14 @@ static int __init tx_7segled_init_sysfs(void)
                }
                dev->id = i;
                dev->bus = &tx_7segled_subsys;
+               dev->release = &tx_7segled_release;
                error = device_register(dev);
-               if (!error) {
-                       device_create_file(dev, &dev_attr_ascii);
-                       device_create_file(dev, &dev_attr_raw);
+               if (error) {
+                       put_device(dev);
+                       return error;
                }
+               device_create_file(dev, &dev_attr_ascii);
+               device_create_file(dev, &dev_attr_raw);
        }
        return error;
 }
index 2871327..a77698f 100644 (file)
@@ -268,7 +268,7 @@ static int txx9_i8259_irq_setup(int irq)
        return err;
 }
 
-static void quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __init_refok quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        int irq;        /* PCI/ISA Bridge interrupt */
        u8 reg_64;
@@ -331,7 +331,7 @@ static void quirk_slc90e66_ide(struct pci_dev *dev)
         * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
         */
        dat |= 0x01;
-       pci_write_config_byte(dev, regs[i], dat);
+       pci_write_config_byte(dev, 0x5c, dat);
        pci_read_config_byte(dev, 0x5c, &dat);
        printk(KERN_CONT " REG5C %02x", dat);
        printk(KERN_CONT "\n");
index dd2cf25..9ff200a 100644 (file)
@@ -937,6 +937,14 @@ static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj,
        return size;
 }
 
+static void txx9_device_release(struct device *dev)
+{
+       struct txx9_sramc_dev *tdev;
+
+       tdev = container_of(dev, struct txx9_sramc_dev, dev);
+       kfree(tdev);
+}
+
 void __init txx9_sramc_init(struct resource *r)
 {
        struct txx9_sramc_dev *dev;
@@ -951,8 +959,11 @@ void __init txx9_sramc_init(struct resource *r)
                return;
        size = resource_size(r);
        dev->base = ioremap(r->start, size);
-       if (!dev->base)
-               goto exit;
+       if (!dev->base) {
+               kfree(dev);
+               return;
+       }
+       dev->dev.release = &txx9_device_release;
        dev->dev.bus = &txx9_sramc_subsys;
        sysfs_bin_attr_init(&dev->bindata_attr);
        dev->bindata_attr.attr.name = "bindata";
@@ -963,17 +974,15 @@ void __init txx9_sramc_init(struct resource *r)
        dev->bindata_attr.private = dev;
        err = device_register(&dev->dev);
        if (err)
-               goto exit;
+               goto exit_put;
        err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
        if (err) {
                device_unregister(&dev->dev);
-               goto exit;
-       }
-       return;
-exit:
-       if (dev) {
-               if (dev->base)
-                       iounmap(dev->base);
+               iounmap(dev->base);
                kfree(dev);
        }
+       return;
+exit_put:
+       put_device(&dev->dev);
+       return;
 }
index d4add86..9fa1772 100644 (file)
@@ -148,9 +148,9 @@ static void loongson2_cpu_wait(void)
        u32 cpu_freq;
 
        spin_lock_irqsave(&loongson2_wait_lock, flags);
-       cpu_freq = LOONGSON_CHIPCFG0;
-       LOONGSON_CHIPCFG0 &= ~0x7;      /* Put CPU into wait mode */
-       LOONGSON_CHIPCFG0 = cpu_freq;   /* Restore CPU state */
+       cpu_freq = LOONGSON_CHIPCFG(0);
+       LOONGSON_CHIPCFG(0) &= ~0x7;    /* Put CPU into wait mode */
+       LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */
        spin_unlock_irqrestore(&loongson2_wait_lock, flags);
        local_irq_enable();
 }
index f5443a6..9c9f6af 100644 (file)
@@ -32,6 +32,7 @@
  * (the low to high transition will not occur).
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -90,7 +91,7 @@ struct au1xmmc_host {
        struct mmc_request *mrq;
 
        u32 flags;
-       u32 iobase;
+       void __iomem *iobase;
        u32 clock;
        u32 bus_width;
        u32 power_mode;
@@ -118,6 +119,7 @@ struct au1xmmc_host {
        struct au1xmmc_platform_data *platdata;
        struct platform_device *pdev;
        struct resource *ioarea;
+       struct clk *clk;
 };
 
 /* Status flags used by the host structure */
@@ -162,32 +164,33 @@ static inline int has_dbdma(void)
 
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
-       u32 val = au_readl(HOST_CONFIG(host));
+       u32 val = __raw_readl(HOST_CONFIG(host));
        val |= mask;
-       au_writel(val, HOST_CONFIG(host));
-       au_sync();
+       __raw_writel(val, HOST_CONFIG(host));
+       wmb(); /* drain writebuffer */
 }
 
 static inline void FLUSH_FIFO(struct au1xmmc_host *host)
 {
-       u32 val = au_readl(HOST_CONFIG2(host));
+       u32 val = __raw_readl(HOST_CONFIG2(host));
 
-       au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
-       au_sync_delay(1);
+       __raw_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
+       mdelay(1);
 
        /* SEND_STOP will turn off clock control - this re-enables it */
        val &= ~SD_CONFIG2_DF;
 
-       au_writel(val, HOST_CONFIG2(host));
-       au_sync();
+       __raw_writel(val, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 }
 
 static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
 {
-       u32 val = au_readl(HOST_CONFIG(host));
+       u32 val = __raw_readl(HOST_CONFIG(host));
        val &= ~mask;
-       au_writel(val, HOST_CONFIG(host));
-       au_sync();
+       __raw_writel(val, HOST_CONFIG(host));
+       wmb(); /* drain writebuffer */
 }
 
 static inline void SEND_STOP(struct au1xmmc_host *host)
@@ -197,12 +200,13 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
        WARN_ON(host->status != HOST_S_DATA);
        host->status = HOST_S_STOP;
 
-       config2 = au_readl(HOST_CONFIG2(host));
-       au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
-       au_sync();
+       config2 = __raw_readl(HOST_CONFIG2(host));
+       __raw_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 
        /* Send the stop command */
-       au_writel(STOP_CMD, HOST_CMD(host));
+       __raw_writel(STOP_CMD, HOST_CMD(host));
+       wmb(); /* drain writebuffer */
 }
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
@@ -296,28 +300,28 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
                }
        }
 
-       au_writel(cmd->arg, HOST_CMDARG(host));
-       au_sync();
+       __raw_writel(cmd->arg, HOST_CMDARG(host));
+       wmb(); /* drain writebuffer */
 
        if (wait)
                IRQ_OFF(host, SD_CONFIG_CR);
 
-       au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
-       au_sync();
+       __raw_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+       wmb(); /* drain writebuffer */
 
        /* Wait for the command to go on the line */
-       while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
+       while (__raw_readl(HOST_CMD(host)) & SD_CMD_GO)
                /* nop */;
 
        /* Wait for the command to come back */
        if (wait) {
-               u32 status = au_readl(HOST_STATUS(host));
+               u32 status = __raw_readl(HOST_STATUS(host));
 
                while (!(status & SD_STATUS_CR))
-                       status = au_readl(HOST_STATUS(host));
+                       status = __raw_readl(HOST_STATUS(host));
 
                /* Clear the CR status */
-               au_writel(SD_STATUS_CR, HOST_STATUS(host));
+               __raw_writel(SD_STATUS_CR, HOST_STATUS(host));
 
                IRQ_ON(host, SD_CONFIG_CR);
        }
@@ -339,11 +343,11 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
        data = mrq->cmd->data;
 
        if (status == 0)
-               status = au_readl(HOST_STATUS(host));
+               status = __raw_readl(HOST_STATUS(host));
 
        /* The transaction is really over when the SD_STATUS_DB bit is clear */
        while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
-               status = au_readl(HOST_STATUS(host));
+               status = __raw_readl(HOST_STATUS(host));
 
        data->error = 0;
        dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
@@ -357,7 +361,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
                data->error = -EILSEQ;
 
        /* Clear the CRC bits */
-       au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+       __raw_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
 
        data->bytes_xfered = 0;
 
@@ -380,7 +384,7 @@ static void au1xmmc_tasklet_data(unsigned long param)
 {
        struct au1xmmc_host *host = (struct au1xmmc_host *)param;
 
-       u32 status = au_readl(HOST_STATUS(host));
+       u32 status = __raw_readl(HOST_STATUS(host));
        au1xmmc_data_complete(host, status);
 }
 
@@ -412,15 +416,15 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
                max = AU1XMMC_MAX_TRANSFER;
 
        for (count = 0; count < max; count++) {
-               status = au_readl(HOST_STATUS(host));
+               status = __raw_readl(HOST_STATUS(host));
 
                if (!(status & SD_STATUS_TH))
                        break;
 
                val = *sg_ptr++;
 
-               au_writel((unsigned long)val, HOST_TXPORT(host));
-               au_sync();
+               __raw_writel((unsigned long)val, HOST_TXPORT(host));
+               wmb(); /* drain writebuffer */
        }
 
        host->pio.len -= count;
@@ -472,7 +476,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
                max = AU1XMMC_MAX_TRANSFER;
 
        for (count = 0; count < max; count++) {
-               status = au_readl(HOST_STATUS(host));
+               status = __raw_readl(HOST_STATUS(host));
 
                if (!(status & SD_STATUS_NE))
                        break;
@@ -494,7 +498,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
                        break;
                }
 
-               val = au_readl(HOST_RXPORT(host));
+               val = __raw_readl(HOST_RXPORT(host));
 
                if (sg_ptr)
                        *sg_ptr++ = (unsigned char)(val & 0xFF);
@@ -537,10 +541,10 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 
        if (cmd->flags & MMC_RSP_PRESENT) {
                if (cmd->flags & MMC_RSP_136) {
-                       r[0] = au_readl(host->iobase + SD_RESP3);
-                       r[1] = au_readl(host->iobase + SD_RESP2);
-                       r[2] = au_readl(host->iobase + SD_RESP1);
-                       r[3] = au_readl(host->iobase + SD_RESP0);
+                       r[0] = __raw_readl(host->iobase + SD_RESP3);
+                       r[1] = __raw_readl(host->iobase + SD_RESP2);
+                       r[2] = __raw_readl(host->iobase + SD_RESP1);
+                       r[3] = __raw_readl(host->iobase + SD_RESP0);
 
                        /* The CRC is omitted from the response, so really
                         * we only got 120 bytes, but the engine expects
@@ -559,7 +563,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
                         * that means that the OSR data starts at bit 31,
                         * so we can just read RESP0 and return that.
                         */
-                       cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+                       cmd->resp[0] = __raw_readl(host->iobase + SD_RESP0);
                }
        }
 
@@ -586,7 +590,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
                        u32 mask = SD_STATUS_DB | SD_STATUS_NE;
 
                        while((status & mask) != mask)
-                               status = au_readl(HOST_STATUS(host));
+                               status = __raw_readl(HOST_STATUS(host));
                }
 
                au1xxx_dbdma_start(channel);
@@ -595,24 +599,17 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
 
 static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 {
-       unsigned int pbus = get_au1x00_speed();
-       unsigned int divisor;
+       unsigned int pbus = clk_get_rate(host->clk);
+       unsigned int divisor = ((pbus / rate) / 2) - 1;
        u32 config;
 
-       /* From databook:
-        * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
-        */
-       pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
-       pbus /= 2;
-       divisor = ((pbus / rate) / 2) - 1;
-
-       config = au_readl(HOST_CONFIG(host));
+       config = __raw_readl(HOST_CONFIG(host));
 
        config &= ~(SD_CONFIG_DIV);
        config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
 
-       au_writel(config, HOST_CONFIG(host));
-       au_sync();
+       __raw_writel(config, HOST_CONFIG(host));
+       wmb(); /* drain writebuffer */
 }
 
 static int au1xmmc_prepare_data(struct au1xmmc_host *host,
@@ -636,7 +633,7 @@ static int au1xmmc_prepare_data(struct au1xmmc_host *host,
        if (host->dma.len == 0)
                return -ETIMEDOUT;
 
-       au_writel(data->blksz - 1, HOST_BLKSIZE(host));
+       __raw_writel(data->blksz - 1, HOST_BLKSIZE(host));
 
        if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
                int i;
@@ -723,31 +720,34 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
 static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 {
        /* Apply the clock */
-       au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
-        au_sync_delay(1);
+       __raw_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+       wmb(); /* drain writebuffer */
+       mdelay(1);
 
-       au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
-       au_sync_delay(5);
+       __raw_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+       wmb(); /* drain writebuffer */
+       mdelay(5);
 
-       au_writel(~0, HOST_STATUS(host));
-       au_sync();
+       __raw_writel(~0, HOST_STATUS(host));
+       wmb(); /* drain writebuffer */
 
-       au_writel(0, HOST_BLKSIZE(host));
-       au_writel(0x001fffff, HOST_TIMEOUT(host));
-       au_sync();
+       __raw_writel(0, HOST_BLKSIZE(host));
+       __raw_writel(0x001fffff, HOST_TIMEOUT(host));
+       wmb(); /* drain writebuffer */
 
-       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-        au_sync();
+       __raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 
-       au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
-       au_sync_delay(1);
+       __raw_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
+       mdelay(1);
 
-       au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-       au_sync();
+       __raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 
        /* Configure interrupts */
-       au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
-       au_sync();
+       __raw_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+       wmb(); /* drain writebuffer */
 }
 
 
@@ -767,7 +767,7 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                host->clock = ios->clock;
        }
 
-       config2 = au_readl(HOST_CONFIG2(host));
+       config2 = __raw_readl(HOST_CONFIG2(host));
        switch (ios->bus_width) {
        case MMC_BUS_WIDTH_8:
                config2 |= SD_CONFIG2_BB;
@@ -780,8 +780,8 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
                break;
        }
-       au_writel(config2, HOST_CONFIG2(host));
-       au_sync();
+       __raw_writel(config2, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 }
 
 #define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
@@ -793,7 +793,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
        struct au1xmmc_host *host = dev_id;
        u32 status;
 
-       status = au_readl(HOST_STATUS(host));
+       status = __raw_readl(HOST_STATUS(host));
 
        if (!(status & SD_STATUS_I))
                return IRQ_NONE;        /* not ours */
@@ -839,8 +839,8 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
                                status);
        }
 
-       au_writel(status, HOST_STATUS(host));
-       au_sync();
+       __raw_writel(status, HOST_STATUS(host));
+       wmb(); /* drain writebuffer */
 
        return IRQ_HANDLED;
 }
@@ -976,7 +976,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
                goto out1;
        }
 
-       host->iobase = (unsigned long)ioremap(r->start, 0x3c);
+       host->iobase = ioremap(r->start, 0x3c);
        if (!host->iobase) {
                dev_err(&pdev->dev, "cannot remap mmio\n");
                goto out2;
@@ -1025,6 +1025,16 @@ static int au1xmmc_probe(struct platform_device *pdev)
                goto out3;
        }
 
+       host->clk = clk_get(&pdev->dev, ALCHEMY_PERIPH_CLK);
+       if (IS_ERR(host->clk)) {
+               dev_err(&pdev->dev, "cannot find clock\n");
+               goto out_irq;
+       }
+       if (clk_prepare_enable(host->clk)) {
+               dev_err(&pdev->dev, "cannot enable clock\n");
+               goto out_clk;
+       }
+
        host->status = HOST_S_IDLE;
 
        /* board-specific carddetect setup, if any */
@@ -1075,7 +1085,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, host);
 
-       pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+       pr_info(DRIVER_NAME ": MMC Controller %d set up at %p"
                " (mode=%s)\n", pdev->id, host->iobase,
                host->flags & HOST_F_DMA ? "dma" : "pio");
 
@@ -1087,10 +1097,10 @@ out6:
                led_classdev_unregister(host->platdata->led);
 out5:
 #endif
-       au_writel(0, HOST_ENABLE(host));
-       au_writel(0, HOST_CONFIG(host));
-       au_writel(0, HOST_CONFIG2(host));
-       au_sync();
+       __raw_writel(0, HOST_ENABLE(host));
+       __raw_writel(0, HOST_CONFIG(host));
+       __raw_writel(0, HOST_CONFIG2(host));
+       wmb(); /* drain writebuffer */
 
        if (host->flags & HOST_F_DBDMA)
                au1xmmc_dbdma_shutdown(host);
@@ -1101,7 +1111,10 @@ out5:
        if (host->platdata && host->platdata->cd_setup &&
            !(mmc->caps & MMC_CAP_NEEDS_POLL))
                host->platdata->cd_setup(mmc, 0);
-
+out_clk:
+       clk_disable_unprepare(host->clk);
+       clk_put(host->clk);
+out_irq:
        free_irq(host->irq, host);
 out3:
        iounmap((void *)host->iobase);
@@ -1130,10 +1143,10 @@ static int au1xmmc_remove(struct platform_device *pdev)
                    !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
                        host->platdata->cd_setup(host->mmc, 0);
 
-               au_writel(0, HOST_ENABLE(host));
-               au_writel(0, HOST_CONFIG(host));
-               au_writel(0, HOST_CONFIG2(host));
-               au_sync();
+               __raw_writel(0, HOST_ENABLE(host));
+               __raw_writel(0, HOST_CONFIG(host));
+               __raw_writel(0, HOST_CONFIG2(host));
+               wmb(); /* drain writebuffer */
 
                tasklet_kill(&host->data_task);
                tasklet_kill(&host->finish_task);
@@ -1143,6 +1156,9 @@ static int au1xmmc_remove(struct platform_device *pdev)
 
                au1xmmc_set_power(host, 0);
 
+               clk_disable_unprepare(host->clk);
+               clk_put(host->clk);
+
                free_irq(host->irq, host);
                iounmap((void *)host->iobase);
                release_resource(host->ioarea);
@@ -1158,11 +1174,11 @@ static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct au1xmmc_host *host = platform_get_drvdata(pdev);
 
-       au_writel(0, HOST_CONFIG2(host));
-       au_writel(0, HOST_CONFIG(host));
-       au_writel(0xffffffff, HOST_STATUS(host));
-       au_writel(0, HOST_ENABLE(host));
-       au_sync();
+       __raw_writel(0, HOST_CONFIG2(host));
+       __raw_writel(0, HOST_CONFIG(host));
+       __raw_writel(0xffffffff, HOST_STATUS(host));
+       __raw_writel(0, HOST_ENABLE(host));
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
index bc5c518..77d6c17 100644 (file)
@@ -41,7 +41,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        u_char ret = readb(this->IO_ADDR_R);
-       au_sync();
+       wmb(); /* drain writebuffer */
        return ret;
 }
 
@@ -56,7 +56,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
 {
        struct nand_chip *this = mtd->priv;
        writeb(byte, this->IO_ADDR_W);
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 /**
@@ -69,7 +69,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-       au_sync();
+       wmb(); /* drain writebuffer */
        return ret;
 }
 
@@ -84,7 +84,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
 {
        struct nand_chip *this = mtd->priv;
        writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 /**
@@ -97,7 +97,7 @@ static u16 au_read_word(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        u16 ret = readw(this->IO_ADDR_R);
-       au_sync();
+       wmb(); /* drain writebuffer */
        return ret;
 }
 
@@ -116,7 +116,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
        for (i = 0; i < len; i++) {
                writeb(buf[i], this->IO_ADDR_W);
-               au_sync();
+               wmb(); /* drain writebuffer */
        }
 }
 
@@ -135,7 +135,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 
        for (i = 0; i < len; i++) {
                buf[i] = readb(this->IO_ADDR_R);
-               au_sync();
+               wmb(); /* drain writebuffer */
        }
 }
 
@@ -156,7 +156,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 
        for (i = 0; i < len; i++) {
                writew(p[i], this->IO_ADDR_W);
-               au_sync();
+               wmb(); /* drain writebuffer */
        }
 
 }
@@ -178,7 +178,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 
        for (i = 0; i < len; i++) {
                p[i] = readw(this->IO_ADDR_R);
-               au_sync();
+               wmb(); /* drain writebuffer */
        }
 }
 
@@ -223,26 +223,23 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
 
        case NAND_CTL_SETNCE:
                /* assert (force assert) chip enable */
-               au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
+               alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
                break;
 
        case NAND_CTL_CLRNCE:
                /* deassert chip enable */
-               au_writel(0, MEM_STNDCTL);
+               alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
                break;
        }
 
        this->IO_ADDR_R = this->IO_ADDR_W;
 
-       /* Drain the writebuffer */
-       au_sync();
+       wmb(); /* Drain the writebuffer */
 }
 
 int au1550_device_ready(struct mtd_info *mtd)
 {
-       int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
-       au_sync();
-       return ret;
+       return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
 }
 
 /**
index a78e4c1..31c48a7 100644 (file)
@@ -89,6 +89,124 @@ MODULE_DESCRIPTION(DRV_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+/* AU1000 MAC registers and bits */
+#define MAC_CONTROL            0x0
+#  define MAC_RX_ENABLE                (1 << 2)
+#  define MAC_TX_ENABLE                (1 << 3)
+#  define MAC_DEF_CHECK                (1 << 5)
+#  define MAC_SET_BL(X)                (((X) & 0x3) << 6)
+#  define MAC_AUTO_PAD         (1 << 8)
+#  define MAC_DISABLE_RETRY    (1 << 10)
+#  define MAC_DISABLE_BCAST    (1 << 11)
+#  define MAC_LATE_COL         (1 << 12)
+#  define MAC_HASH_MODE                (1 << 13)
+#  define MAC_HASH_ONLY                (1 << 15)
+#  define MAC_PASS_ALL         (1 << 16)
+#  define MAC_INVERSE_FILTER   (1 << 17)
+#  define MAC_PROMISCUOUS      (1 << 18)
+#  define MAC_PASS_ALL_MULTI   (1 << 19)
+#  define MAC_FULL_DUPLEX      (1 << 20)
+#  define MAC_NORMAL_MODE      0
+#  define MAC_INT_LOOPBACK     (1 << 21)
+#  define MAC_EXT_LOOPBACK     (1 << 22)
+#  define MAC_DISABLE_RX_OWN   (1 << 23)
+#  define MAC_BIG_ENDIAN       (1 << 30)
+#  define MAC_RX_ALL           (1 << 31)
+#define MAC_ADDRESS_HIGH       0x4
+#define MAC_ADDRESS_LOW                0x8
+#define MAC_MCAST_HIGH         0xC
+#define MAC_MCAST_LOW          0x10
+#define MAC_MII_CNTRL          0x14
+#  define MAC_MII_BUSY         (1 << 0)
+#  define MAC_MII_READ         0
+#  define MAC_MII_WRITE                (1 << 1)
+#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
+#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
+#define MAC_MII_DATA           0x18
+#define MAC_FLOW_CNTRL         0x1C
+#  define MAC_FLOW_CNTRL_BUSY  (1 << 0)
+#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
+#  define MAC_PASS_CONTROL     (1 << 2)
+#  define MAC_SET_PAUSE(X)     (((X) & 0xffff) << 16)
+#define MAC_VLAN1_TAG          0x20
+#define MAC_VLAN2_TAG          0x24
+
+/* Ethernet Controller Enable */
+#  define MAC_EN_CLOCK_ENABLE  (1 << 0)
+#  define MAC_EN_RESET0                (1 << 1)
+#  define MAC_EN_TOSS          (0 << 2)
+#  define MAC_EN_CACHEABLE     (1 << 3)
+#  define MAC_EN_RESET1                (1 << 4)
+#  define MAC_EN_RESET2                (1 << 5)
+#  define MAC_DMA_RESET                (1 << 6)
+
+/* Ethernet Controller DMA Channels */
+/* offsets from MAC_TX_RING_ADDR address */
+#define MAC_TX_BUFF0_STATUS    0x0
+#  define TX_FRAME_ABORTED     (1 << 0)
+#  define TX_JAB_TIMEOUT       (1 << 1)
+#  define TX_NO_CARRIER                (1 << 2)
+#  define TX_LOSS_CARRIER      (1 << 3)
+#  define TX_EXC_DEF           (1 << 4)
+#  define TX_LATE_COLL_ABORT   (1 << 5)
+#  define TX_EXC_COLL          (1 << 6)
+#  define TX_UNDERRUN          (1 << 7)
+#  define TX_DEFERRED          (1 << 8)
+#  define TX_LATE_COLL         (1 << 9)
+#  define TX_COLL_CNT_MASK     (0xF << 10)
+#  define TX_PKT_RETRY         (1 << 31)
+#define MAC_TX_BUFF0_ADDR      0x4
+#  define TX_DMA_ENABLE                (1 << 0)
+#  define TX_T_DONE            (1 << 1)
+#  define TX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
+#define MAC_TX_BUFF0_LEN       0x8
+#define MAC_TX_BUFF1_STATUS    0x10
+#define MAC_TX_BUFF1_ADDR      0x14
+#define MAC_TX_BUFF1_LEN       0x18
+#define MAC_TX_BUFF2_STATUS    0x20
+#define MAC_TX_BUFF2_ADDR      0x24
+#define MAC_TX_BUFF2_LEN       0x28
+#define MAC_TX_BUFF3_STATUS    0x30
+#define MAC_TX_BUFF3_ADDR      0x34
+#define MAC_TX_BUFF3_LEN       0x38
+
+/* offsets from MAC_RX_RING_ADDR */
+#define MAC_RX_BUFF0_STATUS    0x0
+#  define RX_FRAME_LEN_MASK    0x3fff
+#  define RX_WDOG_TIMER                (1 << 14)
+#  define RX_RUNT              (1 << 15)
+#  define RX_OVERLEN           (1 << 16)
+#  define RX_COLL              (1 << 17)
+#  define RX_ETHER             (1 << 18)
+#  define RX_MII_ERROR         (1 << 19)
+#  define RX_DRIBBLING         (1 << 20)
+#  define RX_CRC_ERROR         (1 << 21)
+#  define RX_VLAN1             (1 << 22)
+#  define RX_VLAN2             (1 << 23)
+#  define RX_LEN_ERROR         (1 << 24)
+#  define RX_CNTRL_FRAME       (1 << 25)
+#  define RX_U_CNTRL_FRAME     (1 << 26)
+#  define RX_MCAST_FRAME       (1 << 27)
+#  define RX_BCAST_FRAME       (1 << 28)
+#  define RX_FILTER_FAIL       (1 << 29)
+#  define RX_PACKET_FILTER     (1 << 30)
+#  define RX_MISSED_FRAME      (1 << 31)
+
+#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
+                   RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
+                   RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
+#define MAC_RX_BUFF0_ADDR      0x4
+#  define RX_DMA_ENABLE                (1 << 0)
+#  define RX_T_DONE            (1 << 1)
+#  define RX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
+#  define RX_SET_BUFF_ADDR(X)  ((X) & 0xffffffc0)
+#define MAC_RX_BUFF1_STATUS    0x10
+#define MAC_RX_BUFF1_ADDR      0x14
+#define MAC_RX_BUFF2_STATUS    0x20
+#define MAC_RX_BUFF2_ADDR      0x24
+#define MAC_RX_BUFF3_STATUS    0x30
+#define MAC_RX_BUFF3_ADDR      0x34
+
 /*
  * Theory of operation
  *
@@ -152,10 +270,12 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
 
        if (force_reset || (!aup->mac_enabled)) {
                writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-               au_sync_delay(2);
+               wmb(); /* drain writebuffer */
+               mdelay(2);
                writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
                                | MAC_EN_CLOCK_ENABLE), aup->enable);
-               au_sync_delay(2);
+               wmb(); /* drain writebuffer */
+               mdelay(2);
 
                aup->mac_enabled = 1;
        }
@@ -273,7 +393,8 @@ static void au1000_hard_stop(struct net_device *dev)
        reg = readl(&aup->mac->control);
        reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
        writel(reg, &aup->mac->control);
-       au_sync_delay(10);
+       wmb(); /* drain writebuffer */
+       mdelay(10);
 }
 
 static void au1000_enable_rx_tx(struct net_device *dev)
@@ -286,7 +407,8 @@ static void au1000_enable_rx_tx(struct net_device *dev)
        reg = readl(&aup->mac->control);
        reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
        writel(reg, &aup->mac->control);
-       au_sync_delay(10);
+       wmb(); /* drain writebuffer */
+       mdelay(10);
 }
 
 static void
@@ -336,7 +458,8 @@ au1000_adjust_link(struct net_device *dev)
                        reg |= MAC_DISABLE_RX_OWN;
                }
                writel(reg, &aup->mac->control);
-               au_sync_delay(1);
+               wmb(); /* drain writebuffer */
+               mdelay(1);
 
                au1000_enable_rx_tx(dev);
                aup->old_duplex = phydev->duplex;
@@ -500,9 +623,11 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
        au1000_hard_stop(dev);
 
        writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-       au_sync_delay(2);
+       wmb(); /* drain writebuffer */
+       mdelay(2);
        writel(0, aup->enable);
-       au_sync_delay(2);
+       wmb(); /* drain writebuffer */
+       mdelay(2);
 
        aup->tx_full = 0;
        for (i = 0; i < NUM_RX_DMA; i++) {
@@ -652,7 +777,7 @@ static int au1000_init(struct net_device *dev)
        for (i = 0; i < NUM_RX_DMA; i++)
                aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
 
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        control = MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
@@ -669,7 +794,7 @@ static int au1000_init(struct net_device *dev)
 
        writel(control, &aup->mac->control);
        writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        spin_unlock_irqrestore(&aup->lock, flags);
        return 0;
@@ -760,7 +885,7 @@ static int au1000_rx(struct net_device *dev)
                }
                prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
                aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                /* next descriptor */
                prxd = aup->rx_dma_ring[aup->rx_head];
@@ -808,7 +933,7 @@ static void au1000_tx_ack(struct net_device *dev)
                au1000_update_tx_stats(dev, ptxd->status);
                ptxd->buff_stat &= ~TX_T_DONE;
                ptxd->len = 0;
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
                ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -939,7 +1064,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
        ps->tx_bytes += ptxd->len;
 
        ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-       au_sync();
+       wmb(); /* drain writebuffer */
        dev_kfree_skb(skb);
        aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
        return NETDEV_TX_OK;
index 5f91e3e..aab2cf7 100644 (file)
@@ -18,6 +18,7 @@
  *  with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/interrupt.h>
@@ -175,6 +176,7 @@ struct au1k_private {
 
        struct resource *ioarea;
        struct au1k_irda_platform_data *platdata;
+       struct clk *irda_clk;
 };
 
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -514,9 +516,39 @@ static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id)
 static int au1k_init(struct net_device *dev)
 {
        struct au1k_private *aup = netdev_priv(dev);
-       u32 enable, ring_address;
+       u32 enable, ring_address, phyck;
+       struct clk *c;
        int i;
 
+       c = clk_get(NULL, "irda_clk");
+       if (IS_ERR(c))
+               return PTR_ERR(c);
+       i = clk_prepare_enable(c);
+       if (i) {
+               clk_put(c);
+               return i;
+       }
+
+       switch (clk_get_rate(c)) {
+       case 40000000:
+               phyck = IR_PHYCLK_40MHZ;
+               break;
+       case 48000000:
+               phyck = IR_PHYCLK_48MHZ;
+               break;
+       case 56000000:
+               phyck = IR_PHYCLK_56MHZ;
+               break;
+       case 64000000:
+               phyck = IR_PHYCLK_64MHZ;
+               break;
+       default:
+               clk_disable_unprepare(c);
+               clk_put(c);
+               return -EINVAL;
+       }
+       aup->irda_clk = c;
+
        enable = IR_HC | IR_CE | IR_C;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
        enable |= IR_BE;
@@ -545,7 +577,7 @@ static int au1k_init(struct net_device *dev)
        irda_write(aup, IR_RING_SIZE,
                                (RING_SIZE_64 << 8) | (RING_SIZE_64 << 12));
 
-       irda_write(aup, IR_CONFIG_2, IR_PHYCLK_48MHZ | IR_ONE_PIN);
+       irda_write(aup, IR_CONFIG_2, phyck | IR_ONE_PIN);
        irda_write(aup, IR_RING_ADDR_CMPR, 0);
 
        au1k_irda_set_speed(dev, 9600);
@@ -619,6 +651,9 @@ static int au1k_irda_stop(struct net_device *dev)
        free_irq(aup->irq_tx, dev);
        free_irq(aup->irq_rx, dev);
 
+       clk_disable_unprepare(aup->irda_clk);
+       clk_put(aup->irda_clk);
+
        return 0;
 }
 
@@ -853,6 +888,7 @@ static int au1k_irda_probe(struct platform_device *pdev)
        struct au1k_private *aup;
        struct net_device *dev;
        struct resource *r;
+       struct clk *c;
        int err;
 
        dev = alloc_irdadev(sizeof(struct au1k_private));
@@ -886,6 +922,14 @@ static int au1k_irda_probe(struct platform_device *pdev)
        if (!aup->ioarea)
                goto out;
 
+       /* bail out early if clock doesn't exist */
+       c = clk_get(NULL, "irda_clk");
+       if (IS_ERR(c)) {
+               err = PTR_ERR(c);
+               goto out;
+       }
+       clk_put(c);
+
        aup->iobase = ioremap_nocache(r->start, resource_size(r));
        if (!aup->iobase)
                goto out2;
index ed526a1..fd25e23 100644 (file)
@@ -32,7 +32,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        unsigned long t;
 
-       t = au_readl(SYS_TOYREAD);
+       t = alchemy_rdsys(AU1000_SYS_TOYREAD);
 
        rtc_time_to_tm(t, tm);
 
@@ -45,13 +45,12 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
        rtc_tm_to_time(tm, &t);
 
-       au_writel(t, SYS_TOYWRITE);
-       au_sync();
+       alchemy_wrsys(t, AU1000_SYS_TOYWRITE);
 
        /* wait for the pending register write to succeed.  This can
         * take up to 6 seconds...
         */
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+       while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
                msleep(1);
 
        return 0;
@@ -68,7 +67,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
        unsigned long t;
        int ret;
 
-       t = au_readl(SYS_COUNTER_CNTRL);
+       t = alchemy_rdsys(AU1000_SYS_CNTRCTRL);
        if (!(t & CNTR_OK)) {
                dev_err(&pdev->dev, "counters not working; aborting.\n");
                ret = -ENODEV;
@@ -78,10 +77,10 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
        ret = -ETIMEDOUT;
 
        /* set counter0 tickrate to 1Hz if necessary */
-       if (au_readl(SYS_TOYTRIM) != 32767) {
+       if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) {
                /* wait until hardware gives access to TRIM register */
                t = 0x00100000;
-               while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t)
+               while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T0S) && --t)
                        msleep(1);
 
                if (!t) {
@@ -93,12 +92,11 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
                }
 
                /* set 1Hz TOY tick rate */
-               au_writel(32767, SYS_TOYTRIM);
-               au_sync();
+               alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
        }
 
        /* wait until the hardware allows writes to the counter reg */
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+       while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
                msleep(1);
 
        rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
index fb61464..40c3d43 100644 (file)
@@ -141,13 +141,13 @@ static inline void au1550_spi_mask_ack_all(struct au1550_spi *hw)
                  PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
                | PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
                | PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        hw->regs->psc_spievent =
                  PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
                | PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
                | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 static void au1550_spi_reset_fifos(struct au1550_spi *hw)
@@ -155,10 +155,10 @@ static void au1550_spi_reset_fifos(struct au1550_spi *hw)
        u32 pcr;
 
        hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
-       au_sync();
+       wmb(); /* drain writebuffer */
        do {
                pcr = hw->regs->psc_spipcr;
-               au_sync();
+               wmb(); /* drain writebuffer */
        } while (pcr != 0);
 }
 
@@ -188,9 +188,9 @@ static void au1550_spi_chipsel(struct spi_device *spi, int value)
                au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
                cfg = hw->regs->psc_spicfg;
-               au_sync();
+               wmb(); /* drain writebuffer */
                hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                if (spi->mode & SPI_CPOL)
                        cfg |= PSC_SPICFG_BI;
@@ -218,10 +218,10 @@ static void au1550_spi_chipsel(struct spi_device *spi, int value)
                cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
 
                hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
-               au_sync();
+               wmb(); /* drain writebuffer */
                do {
                        stat = hw->regs->psc_spistat;
-                       au_sync();
+                       wmb(); /* drain writebuffer */
                } while ((stat & PSC_SPISTAT_DR) == 0);
 
                if (hw->pdata->activate_cs)
@@ -252,9 +252,9 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
        au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
        cfg = hw->regs->psc_spicfg;
-       au_sync();
+       wmb(); /* drain writebuffer */
        hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        if (hw->usedma && bpw <= 8)
                cfg &= ~PSC_SPICFG_DD_DISABLE;
@@ -268,12 +268,12 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
        cfg |= au1550_spi_baudcfg(hw, hz);
 
        hw->regs->psc_spicfg = cfg;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        if (cfg & PSC_SPICFG_DE_ENABLE) {
                do {
                        stat = hw->regs->psc_spistat;
-                       au_sync();
+                       wmb(); /* drain writebuffer */
                } while ((stat & PSC_SPISTAT_DR) == 0);
        }
 
@@ -396,11 +396,11 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
 
        /* by default enable nearly all events interrupt */
        hw->regs->psc_spimsk = PSC_SPIMSK_SD;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        /* start the transfer */
        hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        wait_for_completion(&hw->master_done);
 
@@ -429,7 +429,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
 
        stat = hw->regs->psc_spistat;
        evnt = hw->regs->psc_spievent;
-       au_sync();
+       wmb(); /* drain writebuffer */
        if ((stat & PSC_SPISTAT_DI) == 0) {
                dev_err(hw->dev, "Unexpected IRQ!\n");
                return IRQ_NONE;
@@ -484,7 +484,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
 static void au1550_spi_rx_word_##size(struct au1550_spi *hw)           \
 {                                                                      \
        u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);             \
-       au_sync();                                                      \
+       wmb(); /* drain writebuffer */                                  \
        if (hw->rx) {                                                   \
                *(u##size *)hw->rx = (u##size)fifoword;                 \
                hw->rx += (size) / 8;                                   \
@@ -504,7 +504,7 @@ static void au1550_spi_tx_word_##size(struct au1550_spi *hw)                \
        if (hw->tx_count >= hw->len)                                    \
                fifoword |= PSC_SPITXRX_LC;                             \
        hw->regs->psc_spitxrx = fifoword;                               \
-       au_sync();                                                      \
+       wmb(); /* drain writebuffer */                                  \
 }
 
 AU1550_SPI_RX_WORD(8,0xff)
@@ -539,18 +539,18 @@ static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
                }
 
                stat = hw->regs->psc_spistat;
-               au_sync();
+               wmb(); /* drain writebuffer */
                if (stat & PSC_SPISTAT_TF)
                        break;
        }
 
        /* enable event interrupts */
        hw->regs->psc_spimsk = mask;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        /* start the transfer */
        hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        wait_for_completion(&hw->master_done);
 
@@ -564,7 +564,7 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
 
        stat = hw->regs->psc_spistat;
        evnt = hw->regs->psc_spievent;
-       au_sync();
+       wmb(); /* drain writebuffer */
        if ((stat & PSC_SPISTAT_DI) == 0) {
                dev_err(hw->dev, "Unexpected IRQ!\n");
                return IRQ_NONE;
@@ -594,7 +594,7 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
        do {
                busy = 0;
                stat = hw->regs->psc_spistat;
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                /*
                 * Take care to not let the Rx FIFO overflow.
@@ -615,7 +615,7 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
        } while (busy);
 
        hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        /*
         * Restart the SPI transmission in case of a transmit underflow.
@@ -634,9 +634,9 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
         */
        if (evnt & PSC_SPIEVNT_TU) {
                hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
-               au_sync();
+               wmb(); /* drain writebuffer */
                hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-               au_sync();
+               wmb(); /* drain writebuffer */
        }
 
        if (hw->rx_count >= hw->len) {
@@ -690,19 +690,19 @@ static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
 
        /* set up the PSC for SPI mode */
        hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
+       wmb(); /* drain writebuffer */
        hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        hw->regs->psc_spicfg = 0;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        do {
                stat = hw->regs->psc_spistat;
-               au_sync();
+               wmb(); /* drain writebuffer */
        } while ((stat & PSC_SPISTAT_SR) == 0);
 
 
@@ -717,16 +717,16 @@ static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
 #endif
 
        hw->regs->psc_spicfg = cfg;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        au1550_spi_mask_ack_all(hw);
 
        hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        do {
                stat = hw->regs->psc_spistat;
-               au_sync();
+               wmb(); /* drain writebuffer */
        } while ((stat & PSC_SPISTAT_DR) == 0);
 
        au1550_spi_reset_fifos(hw);
index 372d4ae..0676746 100644 (file)
@@ -41,6 +41,7 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -113,7 +114,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
        case VESA_NO_BLANKING:
                /* Turn on panel */
                fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-               au_sync();
+               wmb(); /* drain writebuffer */
                break;
 
        case VESA_VSYNC_SUSPEND:
@@ -121,7 +122,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
        case VESA_POWERDOWN:
                /* Turn off panel */
                fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-               au_sync();
+               wmb(); /* drain writebuffer */
                break;
        default:
                break;
@@ -434,7 +435,7 @@ static int au1100fb_drv_probe(struct platform_device *dev)
        struct au1100fb_device *fbdev = NULL;
        struct resource *regs_res;
        unsigned long page;
-       u32 sys_clksrc;
+       struct clk *c;
 
        /* Allocate new device private */
        fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
@@ -473,6 +474,13 @@ static int au1100fb_drv_probe(struct platform_device *dev)
        print_dbg("Register memory map at %p", fbdev->regs);
        print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
 
+       c = clk_get(NULL, "lcd_intclk");
+       if (!IS_ERR(c)) {
+               fbdev->lcdclk = c;
+               clk_set_rate(c, 48000000);
+               clk_prepare_enable(c);
+       }
+
        /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
        fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
                        (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
@@ -506,10 +514,6 @@ static int au1100fb_drv_probe(struct platform_device *dev)
        print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
        print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
 
-       /* Setup LCD clock to AUX (48 MHz) */
-       sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
-       au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
-
        /* load the panel info into the var struct */
        au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
        au1100fb_var.xres = fbdev->panel->xres;
@@ -546,6 +550,10 @@ static int au1100fb_drv_probe(struct platform_device *dev)
        return 0;
 
 failed:
+       if (fbdev->lcdclk) {
+               clk_disable_unprepare(fbdev->lcdclk);
+               clk_put(fbdev->lcdclk);
+       }
        if (fbdev->fb_mem) {
                dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
                                     fbdev->fb_phys);
@@ -576,11 +584,15 @@ int au1100fb_drv_remove(struct platform_device *dev)
 
        fb_dealloc_cmap(&fbdev->info.cmap);
 
+       if (fbdev->lcdclk) {
+               clk_disable_unprepare(fbdev->lcdclk);
+               clk_put(fbdev->lcdclk);
+       }
+
        return 0;
 }
 
 #ifdef CONFIG_PM
-static u32 sys_clksrc;
 static struct au1100fb_regs fbregs;
 
 int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
@@ -590,14 +602,11 @@ int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
        if (!fbdev)
                return 0;
 
-       /* Save the clock source state */
-       sys_clksrc = au_readl(SYS_CLKSRC);
-
        /* Blank the LCD */
        au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
 
-       /* Stop LCD clocking */
-       au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC);
+       if (fbdev->lcdclk)
+               clk_disable(fbdev->lcdclk);
 
        memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs));
 
@@ -613,8 +622,8 @@ int au1100fb_drv_resume(struct platform_device *dev)
 
        memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs));
 
-       /* Restart LCD clocking */
-       au_writel(sys_clksrc, SYS_CLKSRC);
+       if (fbdev->lcdclk)
+               clk_enable(fbdev->lcdclk);
 
        /* Unblank the LCD */
        au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info);
index 12d9642..9af1993 100644 (file)
@@ -109,6 +109,7 @@ struct au1100fb_device {
        size_t                  fb_len;
        dma_addr_t              fb_phys;
        int                     panel_idx;
+       struct clk              *lcdclk;
 };
 
 /********************************************************************/
index 4cfba78..40494db 100644 (file)
@@ -30,6 +30,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
@@ -330,9 +331,8 @@ struct panel_settings
        uint32 mode_pwmhi;
        uint32 mode_outmask;
        uint32 mode_fifoctrl;
-       uint32 mode_toyclksrc;
        uint32 mode_backlight;
-       uint32 mode_auxpll;
+       uint32 lcdclk;
 #define Xres min_xres
 #define Yres min_yres
        u32     min_xres;               /* Minimum horizontal resolution */
@@ -379,9 +379,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                320, 320,
                240, 240,
        },
@@ -407,9 +406,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                640, 480,
                640, 480,
        },
@@ -435,9 +433,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                800, 800,
                600, 600,
        },
@@ -463,9 +460,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 6, /* 72MHz AUXPLL */
+               .lcdclk         = 72,
                1024, 1024,
                768, 768,
        },
@@ -491,9 +487,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 10, /* 120MHz AUXPLL */
+               .lcdclk         = 120,
                1280, 1280,
                1024, 1024,
        },
@@ -519,9 +514,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x03400000, /* SCB 0x0 */
                .mode_outmask   = 0x00FFFFFF,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                1024, 1024,
                768, 768,
        },
@@ -550,9 +544,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x03400000,
                .mode_outmask   = 0x00fcfcfc,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                640, 480,
                640, 480,
        },
@@ -581,9 +574,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x03400000,
                .mode_outmask   = 0x00fcfcfc,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96, /* 96MHz AUXPLL */
                320, 320,
                240, 240,
        },
@@ -612,9 +604,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x03400000,
                .mode_outmask   = 0x00fcfcfc,
                .mode_fifoctrl  = 0x2f2f2f2f,
-               .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
                .mode_backlight = 0x00000000,
-               .mode_auxpll            = 8, /* 96MHz AUXPLL */
+               .lcdclk         = 96,
                856, 856,
                480, 480,
        },
@@ -646,9 +637,8 @@ static struct panel_settings known_lcd_panels[] =
                .mode_pwmhi             = 0x00000000,
                .mode_outmask           = 0x00FFFFFF,
                .mode_fifoctrl          = 0x2f2f2f2f,
-               .mode_toyclksrc         = 0x00000004, /* AUXPLL directly */
                .mode_backlight         = 0x00000000,
-               .mode_auxpll            = (48/12) * 2,
+               .lcdclk                 = 96,
                800, 800,
                480, 480,
        },
@@ -764,7 +754,7 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
 
        /* Disable the window while making changes, then restore WINEN */
        winenable = lcd->winenable & (1 << plane);
-       au_sync();
+       wmb(); /* drain writebuffer */
        lcd->winenable &= ~(1 << plane);
        lcd->window[plane].winctrl0 = winctrl0;
        lcd->window[plane].winctrl1 = winctrl1;
@@ -772,7 +762,7 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
        lcd->window[plane].winbuf1 = fbdev->fb_phys;
        lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
        lcd->winenable |= winenable;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
@@ -788,22 +778,21 @@ static void au1200_setpanel(struct panel_settings *newpanel,
        /* Make sure all windows disabled */
        winenable = lcd->winenable;
        lcd->winenable = 0;
-       au_sync();
+       wmb(); /* drain writebuffer */
        /*
         * Ensure everything is disabled before reconfiguring
         */
        if (lcd->screen & LCD_SCREEN_SEN) {
                /* Wait for vertical sync period */
                lcd->intstatus = LCD_INT_SS;
-               while ((lcd->intstatus & LCD_INT_SS) == 0) {
-                       au_sync();
-               }
+               while ((lcd->intstatus & LCD_INT_SS) == 0)
+                       ;
 
                lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
 
                do {
                        lcd->intstatus = lcd->intstatus; /*clear interrupts*/
-                       au_sync();
+                       wmb(); /* drain writebuffer */
                /*wait for controller to shut down*/
                } while ((lcd->intstatus & LCD_INT_SD) == 0);
 
@@ -829,11 +818,17 @@ static void au1200_setpanel(struct panel_settings *newpanel,
         */
        if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
        {
-               uint32 sys_clksrc;
-               au_writel(panel->mode_auxpll, SYS_AUXPLL);
-               sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
-               sys_clksrc |= panel->mode_toyclksrc;
-               au_writel(sys_clksrc, SYS_CLKSRC);
+               struct clk *c = clk_get(NULL, "lcd_intclk");
+               long r, pc = panel->lcdclk * 1000000;
+
+               if (!IS_ERR(c)) {
+                       r = clk_round_rate(c, pc);
+                       if ((pc - r) < (pc / 10)) {     /* 10% slack */
+                               clk_set_rate(c, r);
+                               clk_prepare_enable(c);
+                       }
+                       clk_put(c);
+               }
        }
 
        /*
@@ -847,7 +842,7 @@ static void au1200_setpanel(struct panel_settings *newpanel,
        lcd->pwmhi = panel->mode_pwmhi;
        lcd->outmask = panel->mode_outmask;
        lcd->fifoctrl = panel->mode_fifoctrl;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        /* fixme: Check window settings to make sure still valid
         * for new geometry */
@@ -863,7 +858,7 @@ static void au1200_setpanel(struct panel_settings *newpanel,
         * Re-enable screen now that it is configured
         */
        lcd->screen |= LCD_SCREEN_SEN;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        /* Call init of panel */
        if (pd->panel_init)
@@ -956,7 +951,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev)
                | LCD_WINCTRL2_SCY_1
                ) ;
        lcd->winenable |= win->w[plane].mode_winenable;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 
@@ -1270,7 +1265,7 @@ static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
 
        if (pdata->flags & SCREEN_MASK)
                lcd->colorkeymsk = pdata->mask;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
@@ -1288,7 +1283,7 @@ static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
        hi1 = (lcd->pwmhi >> 16) + 1;
        divider = (lcd->pwmdiv & 0x3FFFF) + 1;
        pdata->brightness = ((hi1 << 8) / divider) - 1;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 static void set_window(unsigned int plane,
@@ -1387,7 +1382,7 @@ static void set_window(unsigned int plane,
                val |= (pdata->enable & 1) << plane;
                lcd->winenable = val;
        }
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 static void get_window(unsigned int plane,
@@ -1414,7 +1409,7 @@ static void get_window(unsigned int plane,
        pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
 
        pdata->enable = (lcd->winenable >> plane) & 1;
-       au_sync();
+       wmb(); /* drain writebuffer */
 }
 
 static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
@@ -1511,7 +1506,7 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
 {
        /* Nothing to do for now, just clear any pending interrupt */
        lcd->intstatus = lcd->intstatus;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        return IRQ_HANDLED;
 }
@@ -1809,7 +1804,7 @@ static int au1200fb_drv_suspend(struct device *dev)
        au1200_setpanel(NULL, pd);
 
        lcd->outmask = 0;
-       au_sync();
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
index 4baf2d7..8453531 100644 (file)
@@ -145,35 +145,39 @@ static void __init octeon_wdt_build_stage1(void)
 
        uasm_i_mfc0(&p, K0, C0_STATUS);
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
+       if (octeon_bootloader_entry_addr)
+               uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI),
+                             label_enter_bootloader);
 #endif
        /* Force 64-bit addressing enabled */
        uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
        uasm_i_mtc0(&p, K0, C0_STATUS);
 
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_i_mfc0(&p, K0, C0_EBASE);
-       /* Coreid number in K0 */
-       uasm_i_andi(&p, K0, K0, 0xf);
-       /* 8 * coreid in bits 16-31 */
-       uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
-       uasm_i_ori(&p, K0, K0, 0x8001);
-       uasm_i_dsll_safe(&p, K0, K0, 16);
-       uasm_i_ori(&p, K0, K0, 0x0700);
-       uasm_i_drotr_safe(&p, K0, K0, 32);
-       /*
-        * Should result in: 0x8001,0700,0000,8*coreid which is
-        * CVMX_CIU_WDOGX(coreid) - 0x0500
-        *
-        * Now ld K0, CVMX_CIU_WDOGX(coreid)
-        */
-       uasm_i_ld(&p, K0, 0x500, K0);
-       /*
-        * If bit one set handle the NMI as a watchdog event.
-        * otherwise transfer control to bootloader.
-        */
-       uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
-       uasm_i_nop(&p);
+       if (octeon_bootloader_entry_addr) {
+               uasm_i_mfc0(&p, K0, C0_EBASE);
+               /* Coreid number in K0 */
+               uasm_i_andi(&p, K0, K0, 0xf);
+               /* 8 * coreid in bits 16-31 */
+               uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
+               uasm_i_ori(&p, K0, K0, 0x8001);
+               uasm_i_dsll_safe(&p, K0, K0, 16);
+               uasm_i_ori(&p, K0, K0, 0x0700);
+               uasm_i_drotr_safe(&p, K0, K0, 32);
+               /*
+                * Should result in: 0x8001,0700,0000,8*coreid which is
+                * CVMX_CIU_WDOGX(coreid) - 0x0500
+                *
+                * Now ld K0, CVMX_CIU_WDOGX(coreid)
+                */
+               uasm_i_ld(&p, K0, 0x500, K0);
+               /*
+                * If bit one set handle the NMI as a watchdog event.
+                * otherwise transfer control to bootloader.
+                */
+               uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
+               uasm_i_nop(&p);
+       }
 #endif
 
        /* Clear Dcache so cvmseg works right. */
@@ -194,11 +198,13 @@ static void __init octeon_wdt_build_stage1(void)
        uasm_i_dmfc0(&p, K0, C0_DESAVE);
 
 #ifdef CONFIG_HOTPLUG_CPU
-       uasm_build_label(&l, p, label_enter_bootloader);
-       /* Jump to the bootloader and restore K0 */
-       UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
-       uasm_i_jr(&p, K0);
-       uasm_i_dmfc0(&p, K0, C0_DESAVE);
+       if (octeon_bootloader_entry_addr) {
+               uasm_build_label(&l, p, label_enter_bootloader);
+               /* Jump to the bootloader and restore K0 */
+               UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
+               uasm_i_jr(&p, K0);
+               uasm_i_dmfc0(&p, K0, C0_DESAVE);
+       }
 #endif
        uasm_resolve_relocs(relocs, labels);
 
index 986dcec..84f31e1 100644 (file)
@@ -79,28 +79,28 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
        unsigned short retry, tmo;
        unsigned long data;
 
-       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-       au_sync();
+       __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+       wmb(); /* drain writebuffer */
 
        retry = AC97_RW_RETRIES;
        do {
                mutex_lock(&pscdata->lock);
 
-               au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
+               __raw_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
                          AC97_CDC(pscdata));
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                tmo = 20;
                do {
                        udelay(21);
-                       if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+                       if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
                                break;
                } while (--tmo);
 
-               data = au_readl(AC97_CDC(pscdata));
+               data = __raw_readl(AC97_CDC(pscdata));
 
-               au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-               au_sync();
+               __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+               wmb(); /* drain writebuffer */
 
                mutex_unlock(&pscdata->lock);
 
@@ -119,26 +119,26 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
        unsigned int tmo, retry;
 
-       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-       au_sync();
+       __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+       wmb(); /* drain writebuffer */
 
        retry = AC97_RW_RETRIES;
        do {
                mutex_lock(&pscdata->lock);
 
-               au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
+               __raw_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
                          AC97_CDC(pscdata));
-               au_sync();
+               wmb(); /* drain writebuffer */
 
                tmo = 20;
                do {
                        udelay(21);
-                       if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+                       if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
                                break;
                } while (--tmo);
 
-               au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-               au_sync();
+               __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+               wmb(); /* drain writebuffer */
 
                mutex_unlock(&pscdata->lock);
        } while (--retry && !tmo);
@@ -149,11 +149,11 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
 {
        struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
 
-       au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
-       au_sync();
+       __raw_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
+       wmb(); /* drain writebuffer */
        msleep(10);
-       au_writel(0, AC97_RST(pscdata));
-       au_sync();
+       __raw_writel(0, AC97_RST(pscdata));
+       wmb(); /* drain writebuffer */
 }
 
 static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
@@ -162,25 +162,25 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
        int i;
 
        /* disable PSC during cold reset */
-       au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
-       au_sync();
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
-       au_sync();
+       __raw_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* issue cold reset */
-       au_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
-       au_sync();
+       __raw_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
+       wmb(); /* drain writebuffer */
        msleep(500);
-       au_writel(0, AC97_RST(pscdata));
-       au_sync();
+       __raw_writel(0, AC97_RST(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* enable PSC */
-       au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
-       au_sync();
+       __raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* wait for PSC to indicate it's ready */
        i = 1000;
-       while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
+       while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
                msleep(1);
 
        if (i == 0) {
@@ -189,12 +189,12 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
        }
 
        /* enable the ac97 function */
-       au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-       au_sync();
+       __raw_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* wait for AC97 core to become ready */
        i = 1000;
-       while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
+       while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
                msleep(1);
        if (i == 0)
                printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
@@ -218,8 +218,8 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
 
        chans = params_channels(params);
 
-       r = ro = au_readl(AC97_CFG(pscdata));
-       stat = au_readl(AC97_STAT(pscdata));
+       r = ro = __raw_readl(AC97_CFG(pscdata));
+       stat = __raw_readl(AC97_STAT(pscdata));
 
        /* already active? */
        if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
@@ -252,28 +252,28 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                mutex_lock(&pscdata->lock);
 
                /* disable AC97 device controller first... */
-               au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-               au_sync();
+               __raw_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+               wmb(); /* drain writebuffer */
 
                /* ...wait for it... */
                t = 100;
-               while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
+               while ((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
                        msleep(1);
 
                if (!t)
                        printk(KERN_ERR "PSC-AC97: can't disable!\n");
 
                /* ...write config... */
-               au_writel(r, AC97_CFG(pscdata));
-               au_sync();
+               __raw_writel(r, AC97_CFG(pscdata));
+               wmb(); /* drain writebuffer */
 
                /* ...enable the AC97 controller again... */
-               au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-               au_sync();
+               __raw_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+               wmb(); /* drain writebuffer */
 
                /* ...and wait for ready bit */
                t = 100;
-               while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
+               while ((!(__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
                        msleep(1);
 
                if (!t)
@@ -300,21 +300,21 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
-               au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
-               au_sync();
-               au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
-               au_sync();
+               __raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+               wmb(); /* drain writebuffer */
+               __raw_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
+               wmb(); /* drain writebuffer */
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
-               au_sync();
+               __raw_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
+               wmb(); /* drain writebuffer */
 
-               while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
+               while (__raw_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
                        asm volatile ("nop");
 
-               au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
-               au_sync();
+               __raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+               wmb(); /* drain writebuffer */
 
                break;
        default:
@@ -398,13 +398,13 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
                  PSC_AC97CFG_DE_ENABLE;
 
        /* preserve PSC clock source set up by platform  */
-       sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
-       au_writel(0, PSC_SEL(wd));
-       au_sync();
-       au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
-       au_sync();
+       sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(0, PSC_SEL(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
+       wmb(); /* drain writebuffer */
 
        /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
        memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
@@ -433,10 +433,10 @@ static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
        snd_soc_unregister_component(&pdev->dev);
 
        /* disable PSC completely */
-       au_writel(0, AC97_CFG(wd));
-       au_sync();
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
+       __raw_writel(0, AC97_CFG(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
 
        au1xpsc_ac97_workdata = NULL;   /* MDEV */
 
@@ -449,12 +449,12 @@ static int au1xpsc_ac97_drvsuspend(struct device *dev)
        struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
        /* save interesting registers and disable PSC */
-       wd->pm[0] = au_readl(PSC_SEL(wd));
+       wd->pm[0] = __raw_readl(PSC_SEL(wd));
 
-       au_writel(0, AC97_CFG(wd));
-       au_sync();
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
+       __raw_writel(0, AC97_CFG(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
@@ -464,8 +464,8 @@ static int au1xpsc_ac97_drvresume(struct device *dev)
        struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
        /* restore PSC clock config */
-       au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
-       au_sync();
+       __raw_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
+       wmb(); /* drain writebuffer */
 
        /* after this point the ac97 core will cold-reset the codec.
         * During cold-reset the PSC is reinitialized and the last
index fe923a7..814beff 100644 (file)
@@ -120,10 +120,10 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
        unsigned long stat;
 
        /* check if the PSC is already streaming data */
-       stat = au_readl(I2S_STAT(pscdata));
+       stat = __raw_readl(I2S_STAT(pscdata));
        if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) {
                /* reject parameters not currently set up in hardware */
-               cfgbits = au_readl(I2S_CFG(pscdata));
+               cfgbits = __raw_readl(I2S_CFG(pscdata));
                if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) ||
                    (params_rate(params) != pscdata->rate))
                        return -EINVAL;
@@ -149,33 +149,33 @@ static int au1xpsc_i2s_configure(struct au1xpsc_audio_data *pscdata)
        unsigned long tmo;
 
        /* bring PSC out of sleep, and configure I2S unit */
-       au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
-       au_sync();
+       __raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+       wmb(); /* drain writebuffer */
 
        tmo = 1000000;
-       while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
+       while (!(__raw_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
                tmo--;
 
        if (!tmo)
                goto psc_err;
 
-       au_writel(0, I2S_CFG(pscdata));
-       au_sync();
-       au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
-       au_sync();
+       __raw_writel(0, I2S_CFG(pscdata));
+       wmb(); /* drain writebuffer */
+       __raw_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* wait for I2S controller to become ready */
        tmo = 1000000;
-       while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
+       while (!(__raw_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
                tmo--;
 
        if (tmo)
                return 0;
 
 psc_err:
-       au_writel(0, I2S_CFG(pscdata));
-       au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
-       au_sync();
+       __raw_writel(0, I2S_CFG(pscdata));
+       __raw_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+       wmb(); /* drain writebuffer */
        return -ETIMEDOUT;
 }
 
@@ -187,26 +187,26 @@ static int au1xpsc_i2s_start(struct au1xpsc_audio_data *pscdata, int stype)
        ret = 0;
 
        /* if both TX and RX are idle, configure the PSC  */
-       stat = au_readl(I2S_STAT(pscdata));
+       stat = __raw_readl(I2S_STAT(pscdata));
        if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
                ret = au1xpsc_i2s_configure(pscdata);
                if (ret)
                        goto out;
        }
 
-       au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
-       au_sync();
-       au_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
-       au_sync();
+       __raw_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
+       wmb(); /* drain writebuffer */
+       __raw_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* wait for start confirmation */
        tmo = 1000000;
-       while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+       while (!(__raw_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
                tmo--;
 
        if (!tmo) {
-               au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
-               au_sync();
+               __raw_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+               wmb(); /* drain writebuffer */
                ret = -ETIMEDOUT;
        }
 out:
@@ -217,21 +217,21 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
 {
        unsigned long tmo, stat;
 
-       au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
-       au_sync();
+       __raw_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+       wmb(); /* drain writebuffer */
 
        /* wait for stop confirmation */
        tmo = 1000000;
-       while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+       while ((__raw_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
                tmo--;
 
        /* if both TX and RX are idle, disable PSC */
-       stat = au_readl(I2S_STAT(pscdata));
+       stat = __raw_readl(I2S_STAT(pscdata));
        if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
-               au_writel(0, I2S_CFG(pscdata));
-               au_sync();
-               au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
-               au_sync();
+               __raw_writel(0, I2S_CFG(pscdata));
+               wmb(); /* drain writebuffer */
+               __raw_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+               wmb(); /* drain writebuffer */
        }
        return 0;
 }
@@ -332,12 +332,12 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        /* preserve PSC clock source set up by platform (dev.platform_data
         * is already occupied by soc layer)
         */
-       sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
-       au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
-       au_writel(0, I2S_CFG(wd));
-       au_sync();
+       sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
+       __raw_writel(0, I2S_CFG(wd));
+       wmb(); /* drain writebuffer */
 
        /* preconfigure: set max rx/tx fifo depths */
        wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
@@ -364,10 +364,10 @@ static int au1xpsc_i2s_drvremove(struct platform_device *pdev)
 
        snd_soc_unregister_component(&pdev->dev);
 
-       au_writel(0, I2S_CFG(wd));
-       au_sync();
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
+       __raw_writel(0, I2S_CFG(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
@@ -378,12 +378,12 @@ static int au1xpsc_i2s_drvsuspend(struct device *dev)
        struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
        /* save interesting register and disable PSC */
-       wd->pm[0] = au_readl(PSC_SEL(wd));
+       wd->pm[0] = __raw_readl(PSC_SEL(wd));
 
-       au_writel(0, I2S_CFG(wd));
-       au_sync();
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
+       __raw_writel(0, I2S_CFG(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
@@ -393,12 +393,12 @@ static int au1xpsc_i2s_drvresume(struct device *dev)
        struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
        /* select I2S mode and PSC clock */
-       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-       au_sync();
-       au_writel(0, PSC_SEL(wd));
-       au_sync();
-       au_writel(wd->pm[0], PSC_SEL(wd));
-       au_sync();
+       __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(0, PSC_SEL(wd));
+       wmb(); /* drain writebuffer */
+       __raw_writel(wd->pm[0], PSC_SEL(wd));
+       wmb(); /* drain writebuffer */
 
        return 0;
 }
index b16b2e0..74dffeb 100644 (file)
@@ -27,16 +27,16 @@ struct au1xpsc_audio_data {
 };
 
 /* easy access macros */
-#define PSC_CTRL(x)    ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
-#define PSC_SEL(x)     ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
-#define I2S_STAT(x)    ((unsigned long)((x)->mmio) + PSC_I2SSTAT_OFFSET)
-#define I2S_CFG(x)     ((unsigned long)((x)->mmio) + PSC_I2SCFG_OFFSET)
-#define I2S_PCR(x)     ((unsigned long)((x)->mmio) + PSC_I2SPCR_OFFSET)
-#define AC97_CFG(x)    ((unsigned long)((x)->mmio) + PSC_AC97CFG_OFFSET)
-#define AC97_CDC(x)    ((unsigned long)((x)->mmio) + PSC_AC97CDC_OFFSET)
-#define AC97_EVNT(x)   ((unsigned long)((x)->mmio) + PSC_AC97EVNT_OFFSET)
-#define AC97_PCR(x)    ((unsigned long)((x)->mmio) + PSC_AC97PCR_OFFSET)
-#define AC97_RST(x)    ((unsigned long)((x)->mmio) + PSC_AC97RST_OFFSET)
-#define AC97_STAT(x)   ((unsigned long)((x)->mmio) + PSC_AC97STAT_OFFSET)
+#define PSC_CTRL(x)    ((x)->mmio + PSC_CTRL_OFFSET)
+#define PSC_SEL(x)     ((x)->mmio + PSC_SEL_OFFSET)
+#define I2S_STAT(x)    ((x)->mmio + PSC_I2SSTAT_OFFSET)
+#define I2S_CFG(x)     ((x)->mmio + PSC_I2SCFG_OFFSET)
+#define I2S_PCR(x)     ((x)->mmio + PSC_I2SPCR_OFFSET)
+#define AC97_CFG(x)    ((x)->mmio + PSC_AC97CFG_OFFSET)
+#define AC97_CDC(x)    ((x)->mmio + PSC_AC97CDC_OFFSET)
+#define AC97_EVNT(x)   ((x)->mmio + PSC_AC97EVNT_OFFSET)
+#define AC97_PCR(x)    ((x)->mmio + PSC_AC97PCR_OFFSET)
+#define AC97_RST(x)    ((x)->mmio + PSC_AC97RST_OFFSET)
+#define AC97_STAT(x)   ((x)->mmio + PSC_AC97STAT_OFFSET)
 
 #endif