diff options
Diffstat (limited to 'arch/mips')
332 files changed, 10594 insertions, 4271 deletions
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index e5fc463b36d0..39cf40da5f14 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -4,9 +4,9 @@ platforms += alchemy platforms += ar7 platforms += ath25 platforms += ath79 -platforms += bcm3384 platforms += bcm47xx platforms += bcm63xx +platforms += bmips platforms += cavium-octeon platforms += cobalt platforms += dec @@ -21,6 +21,7 @@ platforms += mti-malta platforms += mti-sead3 platforms += netlogic platforms += paravirt +platforms += pistachio platforms += pmcs-msp71xx platforms += pnx833x platforms += ralink diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c7a16904cd03..2198837c256f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -23,7 +23,7 @@ config MIPS select HAVE_KRETPROBES select HAVE_DEBUG_KMEMLEAK select HAVE_SYSCALL_TRACEPOINTS - select ARCH_BINFMT_ELF_RANDOMIZE_PIE + select ARCH_HAS_ELF_RANDOMIZE select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT select RTC_LIB if !MACH_LOONGSON select GENERIC_ATOMIC64 if !64BIT @@ -43,6 +43,7 @@ config MIPS select GENERIC_SMP_IDLE_THREAD select BUILDTIME_EXTABLE_SORT select GENERIC_CLOCKEVENTS + select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC select GENERIC_CMOS_UPDATE select HAVE_MOD_ARCH_SPECIFIC select VIRT_TO_BUS @@ -55,6 +56,8 @@ config MIPS select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_BINFMT_ELF_STATE select SYSCTL_EXCEPTION_TRACE + select HAVE_VIRT_CPU_ACCOUNTING_GEN + select HAVE_IRQ_TIME_ACCOUNTING menu "Machine selection" @@ -131,8 +134,8 @@ config ATH79 help Support for the Atheros AR71XX/AR724X/AR913X SoCs. -config BCM3384 - bool "Broadcom BCM3384 based boards" +config BMIPS_GENERIC + bool "Broadcom Generic BMIPS kernel" select BOOT_RAW select NO_EXCEPT_FILL select USE_OF @@ -140,22 +143,30 @@ config BCM3384 select CSRC_R4K select SYNC_R4K select COMMON_CLK - select DMA_NONCOHERENT + select BCM7038_L1_IRQ + select BCM7120_L2_IRQ + select BRCMSTB_L2_IRQ select IRQ_CPU + select RAW_IRQ_ACCESSORS + select DMA_NONCOHERENT select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM + select SYS_HAS_CPU_BMIPS32_3300 + select SYS_HAS_CPU_BMIPS4350 + select SYS_HAS_CPU_BMIPS4380 select SYS_HAS_CPU_BMIPS5000 select SWAP_IO_SPACE - select USB_EHCI_BIG_ENDIAN_DESC - select USB_EHCI_BIG_ENDIAN_MMIO - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN + select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN + select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN + select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN help - Support for BCM3384 based boards. BCM3384/BCM33843 is a cable modem - chipset with a Linux application processor that is often used to - provide Samba services, a CUPS print server, and/or advanced routing - features. + Build a generic DT-based kernel image that boots on select + BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top + box chips. Note that CONFIG_CPU_BIG_ENDIAN/CONFIG_CPU_LITTLE_ENDIAN + must be set appropriately for your board. config BCM47XX bool "Broadcom BCM47XX based boards" @@ -352,6 +363,33 @@ config MACH_LOONGSON1 the ICT (Institute of Computing Technology) and the Chinese Academy of Sciences. +config MACH_PISTACHIO + bool "IMG Pistachio SoC based boards" + select ARCH_REQUIRE_GPIOLIB + select BOOT_ELF32 + select BOOT_RAW + select CEVT_R4K + select CLKSRC_MIPS_GIC + select COMMON_CLK + select CSRC_R4K + select DMA_MAYBE_COHERENT + select IRQ_CPU + select LIBFDT + select MFD_SYSCON + select MIPS_CPU_SCACHE + select MIPS_GIC + select PINCTRL + select REGULATOR + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS_CPS + select SYS_SUPPORTS_MULTITHREADING + select SYS_SUPPORTS_ZBOOT + select USE_OF + help + This enables support for the IMG Pistachio SoC platform. + config MIPS_MALTA bool "MIPS Malta board" select ARCH_MAY_HAVE_PC_FDC @@ -377,6 +415,7 @@ config MIPS_MALTA select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 select SYS_HAS_CPU_MIPS32_R3_5 + select SYS_HAS_CPU_MIPS32_R5 select SYS_HAS_CPU_MIPS32_R6 select SYS_HAS_CPU_MIPS64_R1 select SYS_HAS_CPU_MIPS64_R2 @@ -386,6 +425,7 @@ config MIPS_MALTA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_MICROMIPS select SYS_SUPPORTS_MIPS_CMP @@ -779,7 +819,8 @@ config CAVIUM_OCTEON_SOC select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select EDAC_SUPPORT - select SYS_SUPPORTS_HOTPLUG_CPU + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_HOTPLUG_CPU if CPU_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK select SYS_HAS_CPU_CAVIUM_OCTEON select SWAP_IO_SPACE @@ -793,6 +834,7 @@ config CAVIUM_OCTEON_SOC select SYS_SUPPORTS_SMP select NR_CPUS_DEFAULT_16 select BUILTIN_DTB + select MTD_COMPLEX_MAPPINGS help This option supports all of the Octeon reference boards from Cavium Networks. It builds a kernel that dynamically determines the Octeon @@ -887,6 +929,7 @@ source "arch/mips/ath25/Kconfig" source "arch/mips/ath79/Kconfig" source "arch/mips/bcm47xx/Kconfig" source "arch/mips/bcm63xx/Kconfig" +source "arch/mips/bmips/Kconfig" source "arch/mips/jazz/Kconfig" source "arch/mips/jz4740/Kconfig" source "arch/mips/lantiq/Kconfig" @@ -1202,10 +1245,10 @@ config MIPS_L1_CACHE_SHIFT_7 config MIPS_L1_CACHE_SHIFT int - default "4" if MIPS_L1_CACHE_SHIFT_4 - default "5" if MIPS_L1_CACHE_SHIFT_5 - default "6" if MIPS_L1_CACHE_SHIFT_6 default "7" if MIPS_L1_CACHE_SHIFT_7 + default "6" if MIPS_L1_CACHE_SHIFT_6 + default "5" if MIPS_L1_CACHE_SHIFT_5 + default "4" if MIPS_L1_CACHE_SHIFT_4 default "5" config HAVE_STD_PC_SERIAL_PORT @@ -1572,6 +1615,7 @@ config CPU_XLP select WEAK_REORDERING_BEYOND_LLSC select CPU_HAS_PREFETCH select CPU_MIPSR2 + select CPU_SUPPORTS_HUGEPAGES help Netlogic Microsystems XLP processors. endchoice @@ -1596,6 +1640,33 @@ config CPU_MIPS32_3_5_EVA One of its primary benefits is an increase in the maximum size of lowmem (up to 3GB). If unsure, say 'N' here. +config CPU_MIPS32_R5_FEATURES + bool "MIPS32 Release 5 Features" + depends on SYS_HAS_CPU_MIPS32_R5 + depends on CPU_MIPS32_R2 + help + Choose this option to build a kernel for release 2 or later of the + MIPS32 architecture including features from release 5 such as + support for Extended Physical Addressing (XPA). + +config CPU_MIPS32_R5_XPA + bool "Extended Physical Addressing (XPA)" + depends on CPU_MIPS32_R5_FEATURES + depends on !EVA + depends on !PAGE_SIZE_4KB + depends on SYS_SUPPORTS_HIGHMEM + select XPA + select HIGHMEM + select ARCH_PHYS_ADDR_T_64BIT + default n + help + Choose this option if you want to enable the Extended Physical + Addressing (XPA) on your MIPS32 core (such as P5600 series). The + benefit is to increase physical addressing equal to or greater + than 40 bits. Note that this has the side effect of turning on + 64-bit addressing which in turn makes the PTEs 64-bit in size. + If unsure, say 'N' here. + if CPU_LOONGSON2F config CPU_NOP_WORKAROUNDS bool @@ -1699,6 +1770,9 @@ config SYS_HAS_CPU_MIPS32_R2 config SYS_HAS_CPU_MIPS32_R3_5 bool +config SYS_HAS_CPU_MIPS32_R5 + bool + config SYS_HAS_CPU_MIPS32_R6 bool @@ -1836,6 +1910,9 @@ config CPU_MIPSR6 config EVA bool +config XPA + bool + config SYS_SUPPORTS_32BIT_KERNEL bool config SYS_SUPPORTS_64BIT_KERNEL @@ -2072,7 +2149,7 @@ config MIPSR2_TO_R6_EMULATOR help Choose this option if you want to run non-R6 MIPS userland code. Even if you say 'Y' here, the emulator will still be disabled by - default. You can enable it using the 'mipsr2emul' kernel option. + default. You can enable it using the 'mipsr2emu' kernel option. The only reason this is a build-time option is to save ~14K from the final kernel image. comment "MIPS R2-to-R6 emulator is only available for UP kernels" @@ -2142,7 +2219,7 @@ config MIPS_CMP config MIPS_CPS bool "MIPS Coherent Processing System support" - depends on SYS_SUPPORTS_MIPS_CPS + depends on SYS_SUPPORTS_MIPS_CPS && !64BIT select MIPS_CM select MIPS_CPC select MIPS_CPS_PM if HOTPLUG_CPU @@ -2348,7 +2425,7 @@ config NODES_SHIFT config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" - depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP) + depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3) default y help Enable hardware performance counter support for perf events. If @@ -2500,6 +2577,9 @@ config HZ default 1000 if HZ_1000 default 1024 if HZ_1024 +config SCHED_HRTICK + def_bool HIGH_RES_TIMERS + source "kernel/Kconfig.preempt" config KEXEC @@ -2600,6 +2680,11 @@ config STACKTRACE_SUPPORT bool default y +config PGTABLE_LEVELS + int + default 3 if 64BIT && !PAGE_SIZE_64KB + default 2 + source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 8f57fc72d62c..5200f649dd4e 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -197,11 +197,17 @@ endif # Warning: the 64-bit MIPS architecture does not support the `smartmips' extension # Pass -Wa,--no-warn to disable all assembler warnings until the kernel code has # been fixed properly. -mips-cflags := "$(cflags-y)" -cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,$(mips-cflags),-msmartmips) -Wa,--no-warn -cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,$(mips-cflags),-mmicromips) +mips-cflags := $(cflags-y) +ifeq ($(CONFIG_CPU_HAS_SMARTMIPS),y) +smartmips-ase := $(call cc-option-yn,$(mips-cflags) -msmartmips) +cflags-$(smartmips-ase) += -msmartmips -Wa,--no-warn +endif +ifeq ($(CONFIG_CPU_MICROMIPS),y) +micromips-ase := $(call cc-option-yn,$(mips-cflags) -mmicromips) +cflags-$(micromips-ase) += -mmicromips +endif ifeq ($(CONFIG_CPU_HAS_MSA),y) -toolchain-msa := $(call cc-option-yn,-$(mips-cflags),mhard-float -mfp64 -Wa$(comma)-mmsa) +toolchain-msa := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(comma)-mmsa) cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA endif @@ -225,7 +231,7 @@ endif # # Board-dependent options and extra files # -include $(srctree)/arch/mips/Kbuild.platforms +include arch/mips/Kbuild.platforms ifdef CONFIG_PHYSICAL_START load-y = $(CONFIG_PHYSICAL_START) @@ -365,7 +371,11 @@ core-$(CONFIG_BUILTIN_DTB) += arch/mips/boot/dts/ PHONY += dtbs dtbs: scripts - $(Q)$(MAKE) $(build)=arch/mips/boot/dts dtbs + $(Q)$(MAKE) $(build)=arch/mips/boot/dts + +PHONY += dtbs_install +dtbs_install: + $(Q)$(MAKE) $(dtbinst)=arch/mips/boot/dts archprepare: ifdef CONFIG_MIPS32_N32 @@ -407,6 +417,7 @@ define archhelp echo ' uImage.lzma - U-Boot image (lzma)' echo ' uImage.lzo - U-Boot image (lzo)' echo ' dtbs - Device-tree blobs for enabled boards' + echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' echo echo ' These will be default as appropriate for a configured platform.' endef diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index af2441dbfc12..be9ff1673ded 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -307,10 +307,7 @@ static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) } if (mac) { - if (sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", - &dev_addr[0], &dev_addr[1], - &dev_addr[2], &dev_addr[3], - &dev_addr[4], &dev_addr[5]) != 6) { + if (!mac_pton(mac, dev_addr)) { pr_warn("cannot parse mac address, using random address\n"); eth_random_addr(dev_addr); } diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h index a3120714f0b7..c39de61f9b36 100644 --- a/arch/mips/ath79/common.h +++ b/arch/mips/ath79/common.h @@ -17,7 +17,7 @@ #include <linux/types.h> #define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) -#define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) +#define ATH79_MEM_SIZE_MAX (256 * 1024 * 1024) void ath79_clocks_init(void); unsigned long ath79_get_sys_clk_rate(const char *id); diff --git a/arch/mips/bcm3384/Platform b/arch/mips/bcm3384/Platform deleted file mode 100644 index 8e1ca0819e1b..000000000000 --- a/arch/mips/bcm3384/Platform +++ /dev/null @@ -1,7 +0,0 @@ -# -# Broadcom BCM3384 boards -# -platform-$(CONFIG_BCM3384) += bcm3384/ -cflags-$(CONFIG_BCM3384) += \ - -I$(srctree)/arch/mips/include/asm/mach-bcm3384/ -load-$(CONFIG_BCM3384) := 0xffffffff80010000 diff --git a/arch/mips/bcm3384/dma.c b/arch/mips/bcm3384/dma.c deleted file mode 100644 index ea42012fd4f5..000000000000 --- a/arch/mips/bcm3384/dma.c +++ /dev/null @@ -1,81 +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) 2014 Kevin Cernekee <cernekee@gmail.com> - */ - -#include <linux/device.h> -#include <linux/dma-direction.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/of.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <dma-coherence.h> - -/* - * BCM3384 has configurable address translation windows which allow the - * peripherals' DMA addresses to be different from the Zephyr-visible - * physical addresses. e.g. usb_dma_addr = zephyr_pa ^ 0x08000000 - * - * If our DT "memory" node has a "dma-xor-mask" property we will enable this - * translation using the provided offset. - */ -static u32 bcm3384_dma_xor_mask; -static u32 bcm3384_dma_xor_limit = 0xffffffff; - -/* - * PCI collapses the memory hole at 0x10000000 - 0x1fffffff. - * On systems with a dma-xor-mask, this range is guaranteed to live above - * the dma-xor-limit. - */ -#define BCM3384_MEM_HOLE_PA 0x10000000 -#define BCM3384_MEM_HOLE_SIZE 0x10000000 - -static dma_addr_t bcm3384_phys_to_dma(struct device *dev, phys_addr_t pa) -{ - if (dev && dev_is_pci(dev) && - pa >= (BCM3384_MEM_HOLE_PA + BCM3384_MEM_HOLE_SIZE)) - return pa - BCM3384_MEM_HOLE_SIZE; - if (pa <= bcm3384_dma_xor_limit) - return pa ^ bcm3384_dma_xor_mask; - return pa; -} - -dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) -{ - return bcm3384_phys_to_dma(dev, virt_to_phys(addr)); -} - -dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) -{ - return bcm3384_phys_to_dma(dev, page_to_phys(page)); -} - -unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) -{ - if (dev && dev_is_pci(dev) && - dma_addr >= BCM3384_MEM_HOLE_PA) - return dma_addr + BCM3384_MEM_HOLE_SIZE; - if ((dma_addr ^ bcm3384_dma_xor_mask) <= bcm3384_dma_xor_limit) - return dma_addr ^ bcm3384_dma_xor_mask; - return dma_addr; -} - -static int __init bcm3384_init_dma_xor(void) -{ - struct device_node *np = of_find_node_by_type(NULL, "memory"); - - if (!np) - return 0; - - of_property_read_u32(np, "dma-xor-mask", &bcm3384_dma_xor_mask); - of_property_read_u32(np, "dma-xor-limit", &bcm3384_dma_xor_limit); - - of_node_put(np); - return 0; -} -arch_initcall(bcm3384_init_dma_xor); diff --git a/arch/mips/bcm3384/irq.c b/arch/mips/bcm3384/irq.c deleted file mode 100644 index fd94fe849af6..000000000000 --- a/arch/mips/bcm3384/irq.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Partially based on arch/mips/ralink/irq.c - * - * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> - * Copyright (C) 2013 John Crispin <blogic@openwrt.org> - * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> - */ - -#include <linux/io.h> -#include <linux/bitops.h> -#include <linux/of_platform.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/irqdomain.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -#include <asm/bmips.h> -#include <asm/irq_cpu.h> -#include <asm/mipsregs.h> - -/* INTC register offsets */ -#define INTC_REG_ENABLE 0x00 -#define INTC_REG_STATUS 0x04 - -#define MAX_WORDS 2 -#define IRQS_PER_WORD 32 - -struct bcm3384_intc { - int n_words; - void __iomem *reg[MAX_WORDS]; - u32 enable[MAX_WORDS]; - spinlock_t lock; -}; - -static void bcm3384_intc_irq_unmask(struct irq_data *d) -{ - struct bcm3384_intc *priv = d->domain->host_data; - unsigned long flags; - int idx = d->hwirq / IRQS_PER_WORD; - int bit = d->hwirq % IRQS_PER_WORD; - - spin_lock_irqsave(&priv->lock, flags); - priv->enable[idx] |= BIT(bit); - __raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void bcm3384_intc_irq_mask(struct irq_data *d) -{ - struct bcm3384_intc *priv = d->domain->host_data; - unsigned long flags; - int idx = d->hwirq / IRQS_PER_WORD; - int bit = d->hwirq % IRQS_PER_WORD; - - spin_lock_irqsave(&priv->lock, flags); - priv->enable[idx] &= ~BIT(bit); - __raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static struct irq_chip bcm3384_intc_irq_chip = { - .name = "INTC", - .irq_unmask = bcm3384_intc_irq_unmask, - .irq_mask = bcm3384_intc_irq_mask, - .irq_mask_ack = bcm3384_intc_irq_mask, -}; - -unsigned int get_c0_compare_int(void) -{ - return CP0_LEGACY_COMPARE_IRQ; -} - -static void bcm3384_intc_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct irq_domain *domain = irq_get_handler_data(irq); - struct bcm3384_intc *priv = domain->host_data; - unsigned long flags; - unsigned int idx; - - for (idx = 0; idx < priv->n_words; idx++) { - unsigned long pending; - int hwirq; - - spin_lock_irqsave(&priv->lock, flags); - pending = __raw_readl(priv->reg[idx] + INTC_REG_STATUS) & - priv->enable[idx]; - spin_unlock_irqrestore(&priv->lock, flags); - - for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { - generic_handle_irq(irq_find_mapping(domain, - hwirq + idx * IRQS_PER_WORD)); - } - } -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned long pending = - (read_c0_status() & read_c0_cause() & ST0_IM) >> STATUSB_IP0; - int bit; - - for_each_set_bit(bit, &pending, 8) - do_IRQ(MIPS_CPU_IRQ_BASE + bit); -} - -static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -{ - irq_set_chip_and_handler(irq, &bcm3384_intc_irq_chip, handle_level_irq); - return 0; -} - -static const struct irq_domain_ops irq_domain_ops = { - .xlate = irq_domain_xlate_onecell, - .map = intc_map, -}; - -static int __init ioremap_one_pair(struct bcm3384_intc *priv, - struct device_node *node, - int idx) -{ - struct resource res; - - if (of_address_to_resource(node, idx, &res)) - return 0; - - if (request_mem_region(res.start, resource_size(&res), - res.name) < 0) - pr_err("Failed to request INTC register region\n"); - - priv->reg[idx] = ioremap_nocache(res.start, resource_size(&res)); - if (!priv->reg[idx]) - panic("Failed to ioremap INTC register range"); - - /* start up with everything masked before we hook the parent IRQ */ - __raw_writel(0, priv->reg[idx] + INTC_REG_ENABLE); - priv->enable[idx] = 0; - - return IRQS_PER_WORD; -} - -static int __init intc_of_init(struct device_node *node, - struct device_node *parent) -{ - struct irq_domain *domain; - unsigned int parent_irq, n_irqs = 0; - struct bcm3384_intc *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - panic("Failed to allocate bcm3384_intc struct"); - - spin_lock_init(&priv->lock); - - parent_irq = irq_of_parse_and_map(node, 0); - if (!parent_irq) - panic("Failed to get INTC IRQ"); - - n_irqs += ioremap_one_pair(priv, node, 0); - n_irqs += ioremap_one_pair(priv, node, 1); - - if (!n_irqs) - panic("Failed to map INTC registers"); - - priv->n_words = n_irqs / IRQS_PER_WORD; - domain = irq_domain_add_linear(node, n_irqs, &irq_domain_ops, priv); - if (!domain) - panic("Failed to add irqdomain"); - - irq_set_chained_handler(parent_irq, bcm3384_intc_irq_handler); - irq_set_handler_data(parent_irq, domain); - - return 0; -} - -static struct of_device_id of_irq_ids[] __initdata = { - { .compatible = "mti,cpu-interrupt-controller", - .data = mips_cpu_irq_of_init }, - { .compatible = "brcm,bcm3384-intc", - .data = intc_of_init }, - {}, -}; - -void __init arch_init_irq(void) -{ - bmips_tp1_irqs = 0; - of_irq_init(of_irq_ids); -} diff --git a/arch/mips/bcm3384/setup.c b/arch/mips/bcm3384/setup.c deleted file mode 100644 index d84b8400b874..000000000000 --- a/arch/mips/bcm3384/setup.c +++ /dev/null @@ -1,97 +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) 2008 Maxime Bizon <mbizon@freebox.fr> - * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> - */ - -#include <linux/init.h> -#include <linux/bootmem.h> -#include <linux/clk-provider.h> -#include <linux/ioport.h> -#include <linux/of.h> -#include <linux/of_fdt.h> -#include <linux/of_platform.h> -#include <linux/smp.h> -#include <asm/addrspace.h> -#include <asm/bmips.h> -#include <asm/bootinfo.h> -#include <asm/prom.h> -#include <asm/smp-ops.h> -#include <asm/time.h> - -void __init prom_init(void) -{ - register_bmips_smp_ops(); -} - -void __init prom_free_prom_memory(void) -{ -} - -const char *get_system_type(void) -{ - return "BCM3384"; -} - -void __init plat_time_init(void) -{ - struct device_node *np; - u32 freq; - - np = of_find_node_by_name(NULL, "cpus"); - if (!np) - panic("missing 'cpus' DT node"); - if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) - panic("missing 'mips-hpt-frequency' property"); - of_node_put(np); - - mips_hpt_frequency = freq; -} - -void __init plat_mem_setup(void) -{ - void *dtb = __dtb_start; - - set_io_port_base(0); - ioport_resource.start = 0; - ioport_resource.end = ~0; - - /* intended to somewhat resemble ARM; see Documentation/arm/Booting */ - if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) - dtb = phys_to_virt(fw_arg2); - - __dt_setup_arch(dtb); - - strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); -} - -void __init device_tree_init(void) -{ - struct device_node *np; - - unflatten_and_copy_device_tree(); - - /* Disable SMP boot unless both CPUs are listed in DT and !disabled */ - np = of_find_node_by_name(NULL, "cpus"); - if (np && of_get_available_child_count(np) <= 1) - bmips_smp_enabled = 0; - of_node_put(np); -} - -int __init plat_of_setup(void) -{ - return __dt_register_buses("brcm,bcm3384", "simple-bus"); -} - -arch_initcall(plat_of_setup); - -static int __init plat_dev_init(void) -{ - of_clk_init(NULL); - return 0; -} - -device_initcall(plat_dev_init); diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h index ea909a56a3ee..41796befa9df 100644 --- a/arch/mips/bcm47xx/bcm47xx_private.h +++ b/arch/mips/bcm47xx/bcm47xx_private.h @@ -1,6 +1,10 @@ #ifndef LINUX_BCM47XX_PRIVATE_H_ #define LINUX_BCM47XX_PRIVATE_H_ +#ifndef pr_fmt +#define pr_fmt(fmt) "bcm47xx: " fmt +#endif + #include <linux/kernel.h> /* prom.c */ diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c index b3ae068ca4fa..bd56415f2f3b 100644 --- a/arch/mips/bcm47xx/board.c +++ b/arch/mips/bcm47xx/board.c @@ -1,8 +1,8 @@ #include <linux/errno.h> #include <linux/export.h> #include <linux/string.h> +#include <bcm47xx.h> #include <bcm47xx_board.h> -#include <bcm47xx_nvram.h> struct bcm47xx_board_type { const enum bcm47xx_board board; @@ -40,20 +40,6 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_model_name[] __initconst = { { {0}, NULL}, }; -/* model_no */ -static const -struct bcm47xx_board_type_list1 bcm47xx_board_list_model_no[] __initconst = { - {{BCM47XX_BOARD_ASUS_WL700GE, "Asus WL700"}, "WL700"}, - { {0}, NULL}, -}; - -/* machine_name */ -static const -struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst = { - {{BCM47XX_BOARD_LINKSYS_WRTSL54GS, "Linksys WRTSL54GS"}, "WRTSL54GS"}, - { {0}, NULL}, -}; - /* hardware_version */ static const struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = { @@ -165,9 +151,11 @@ static const struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = { {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614_V10, "Netgear WGR614 V10"}, "U12H139T01_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3400_V3, "Netgear WNDR3400 V3"}, "U12H208T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR3400VCNA, "Netgear WNDR3400 Vcna"}, "U12H155T01_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR3700V3, "Netgear WNDR3700 V3"}, "U12H194T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"}, @@ -202,6 +190,20 @@ struct bcm47xx_board_type_list2 bcm47xx_board_list_board_type_rev[] __initconst { {0}, NULL}, }; +/* + * Some devices don't use any common NVRAM entry for identification and they + * have only one model specific variable. + * They don't deserve own arrays, let's group them there using key-value array. + */ +static const +struct bcm47xx_board_type_list2 bcm47xx_board_list_key_value[] __initconst = { + {{BCM47XX_BOARD_ASUS_WL700GE, "Asus WL700"}, "model_no", "WL700"}, + {{BCM47XX_BOARD_LINKSYS_WRT300N_V1, "Linksys WRT300N V1"}, "router_name", "WRT300N"}, + {{BCM47XX_BOARD_LINKSYS_WRT600N_V11, "Linksys WRT600N V1.1"}, "Model_Name", "WRT600N"}, + {{BCM47XX_BOARD_LINKSYS_WRTSL54GS, "Linksys WRTSL54GS"}, "machine_name", "WRTSL54GS"}, + { {0}, NULL}, +}; + static const struct bcm47xx_board_type bcm47xx_board_unknown[] __initconst = { {BCM47XX_BOARD_UNKNOWN, "Unknown Board"}, @@ -225,20 +227,6 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void) } } - if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) { - if (strstarts(buf1, e1->value1)) - return &e1->board; - } - } - - if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) { - for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) { - if (strstarts(buf1, e1->value1)) - return &e1->board; - } - } - if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) { for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) { if (strstarts(buf1, e1->value1)) @@ -247,8 +235,8 @@ 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++) { + bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0) { + for (e2 = bcm47xx_board_list_hw_version_num; e2->value1; e2++) { if (!strstarts(buf1, e2->value1) && !strcmp(buf2, e2->value2)) return &e2->board; @@ -314,6 +302,14 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void) return &e2->board; } } + + for (e2 = bcm47xx_board_list_key_value; e2->value1; e2++) { + if (bcm47xx_nvram_getenv(e2->value1, buf1, sizeof(buf1)) >= 0) { + if (!strcmp(buf1, e2->value2)) + return &e2->board; + } + } + return bcm47xx_board_unknown; } @@ -330,9 +326,8 @@ void __init bcm47xx_board_detect(void) err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)); /* init of nvram failed, probably too early now */ - if (err == -ENXIO) { + if (err == -ENXIO) return; - } board_detected = bcm47xx_board_get_nvram(); bcm47xx_board.board = board_detected->board; diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c index 913182bcafb8..276276a8c6d7 100644 --- a/arch/mips/bcm47xx/buttons.c +++ b/arch/mips/bcm47xx/buttons.c @@ -252,6 +252,12 @@ bcm47xx_buttons_linksys_wrt160nv3[] __initconst = { }; static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt300n_v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button bcm47xx_buttons_linksys_wrt300nv11[] __initconst = { BCM47XX_GPIO_KEY(4, KEY_UNKNOWN), BCM47XX_GPIO_KEY(6, KEY_RESTART), @@ -327,6 +333,12 @@ bcm47xx_buttons_netgear_wndr3400v1[] __initconst = { }; static const struct gpio_keys_button +bcm47xx_buttons_netgear_wndr3400_v3[] __initconst = { + BCM47XX_GPIO_KEY(12, KEY_RESTART), + BCM47XX_GPIO_KEY(23, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button bcm47xx_buttons_netgear_wndr3700v3[] __initconst = { BCM47XX_GPIO_KEY(2, KEY_RFKILL), BCM47XX_GPIO_KEY(3, KEY_RESTART), @@ -516,6 +528,9 @@ int __init bcm47xx_buttons_register(void) case BCM47XX_BOARD_LINKSYS_WRT160NV3: err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv3); break; + case BCM47XX_BOARD_LINKSYS_WRT300N_V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300n_v1); + break; case BCM47XX_BOARD_LINKSYS_WRT300NV11: err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300nv11); break; @@ -557,6 +572,9 @@ int __init bcm47xx_buttons_register(void) case BCM47XX_BOARD_NETGEAR_WNDR3400V1: err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1); break; + case BCM47XX_BOARD_NETGEAR_WNDR3400_V3: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400_v3); + break; case BCM47XX_BOARD_NETGEAR_WNDR3700V3: err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3700v3); break; diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c index 903a656d4119..0e4ade342333 100644 --- a/arch/mips/bcm47xx/leds.c +++ b/arch/mips/bcm47xx/leds.c @@ -292,6 +292,13 @@ bcm47xx_leds_linksys_wrt160nv3[] __initconst = { }; static const struct gpio_led +bcm47xx_leds_linksys_wrt300n_v1[] __initconst = { + BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(5, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led bcm47xx_leds_linksys_wrt300nv11[] __initconst = { BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), @@ -585,6 +592,9 @@ void __init bcm47xx_leds_register(void) case BCM47XX_BOARD_LINKSYS_WRT160NV3: bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt160nv3); break; + case BCM47XX_BOARD_LINKSYS_WRT300N_V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt300n_v1); + break; case BCM47XX_BOARD_LINKSYS_WRT300NV11: bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt300nv11); break; diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index c5c381c43f17..ba632ff08a13 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -11,15 +11,18 @@ * option) any later version. */ +#include <linux/io.h> #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/mtd/mtd.h> -#include <bcm47xx_nvram.h> +#include <linux/bcm47xx_nvram.h> -#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ -#define NVRAM_SPACE 0x8000 +#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ +#define NVRAM_SPACE 0x10000 +#define NVRAM_MAX_GPIO_ENTRIES 32 +#define NVRAM_MAX_GPIO_VALUE_LEN 30 #define FLASH_MIN 0x00020000 /* Minimum flash size */ @@ -91,20 +94,18 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) return -ENXIO; found: - if (header->len > size) pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n"); if (header->len > NVRAM_SPACE) pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", header->len, NVRAM_SPACE); - src = (u32 *) header; - dst = (u32 *) nvram_buf; + src = (u32 *)header; + dst = (u32 *)nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) - *dst++ = *src++; + *dst++ = __raw_readl(src++); for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4) - *dst++ = le32_to_cpu(*src++); - memset(dst, 0x0, NVRAM_SPACE - i); + *dst++ = readl(src++); return 0; } @@ -138,37 +139,28 @@ static int nvram_init(void) struct mtd_info *mtd; struct nvram_header header; size_t bytes_read; - int err, i; + int err; mtd = get_mtd_device_nm("nvram"); if (IS_ERR(mtd)) return -ENODEV; - for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { - loff_t from = mtd->size - nvram_sizes[i]; + err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header); + if (!err && header.magic == NVRAM_MAGIC) { + u8 *dst = (uint8_t *)nvram_buf; + size_t len = header.len; - if (from < 0) - continue; - - err = mtd_read(mtd, from, sizeof(header), &bytes_read, - (uint8_t *)&header); - if (!err && header.magic == NVRAM_MAGIC) { - u8 *dst = (uint8_t *)nvram_buf; - size_t len = header.len; - - if (header.len > NVRAM_SPACE) { - pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", - header.len, NVRAM_SPACE); - len = NVRAM_SPACE; - } + if (header.len > NVRAM_SPACE) { + pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", + header.len, NVRAM_SPACE); + len = NVRAM_SPACE; + } - err = mtd_read(mtd, from, len, &bytes_read, dst); - if (err) - return err; - memset(dst + bytes_read, 0x0, NVRAM_SPACE - bytes_read); + err = mtd_read(mtd, 0, len, &bytes_read, dst); + if (err) + return err; - return 0; - } + return 0; } #endif @@ -178,7 +170,7 @@ static int nvram_init(void) int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) { char *var, *value, *end, *eq; - int err; + int data_left, err; if (!name) return -EINVAL; @@ -192,16 +184,18 @@ int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) /* Look for name=value and return value */ var = &nvram_buf[sizeof(struct nvram_header)]; end = nvram_buf + sizeof(nvram_buf) - 2; - end[0] = end[1] = '\0'; + end[0] = '\0'; + end[1] = '\0'; for (; *var; var = value + strlen(value) + 1) { - eq = strchr(var, '='); + data_left = end - var; + + eq = strnchr(var, data_left, '='); if (!eq) break; value = eq + 1; - if ((eq - var) == strlen(name) && - strncmp(var, name, (eq - var)) == 0) { + if (eq - var == strlen(name) && + strncmp(var, name, eq - var) == 0) return snprintf(val, val_len, "%s", value); - } } return -ENOENT; } @@ -210,10 +204,11 @@ EXPORT_SYMBOL(bcm47xx_nvram_getenv); int bcm47xx_nvram_gpio_pin(const char *name) { int i, err; - char nvram_var[10]; - char buf[30]; + char nvram_var[] = "gpioXX"; + char buf[NVRAM_MAX_GPIO_VALUE_LEN]; - for (i = 0; i < 32; i++) { + /* TODO: Optimize it to don't call getenv so many times */ + for (i = 0; i < NVRAM_MAX_GPIO_ENTRIES; i++) { err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i); if (err <= 0) continue; diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 1b170bf5f7f0..ab698bad6d62 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -35,7 +35,6 @@ #include <bcm47xx.h> #include <bcm47xx_board.h> - static char bcm47xx_system_type[20] = "Broadcom BCM47XX"; const char *get_system_type(void) @@ -83,7 +82,7 @@ static __init void prom_init_mem(void) /* Loop condition may be not enough, off may be over 1 MiB */ if (off + mem >= max) { mem = max; - printk(KERN_DEBUG "assume 128MB RAM\n"); + pr_debug("Assume 128MB RAM\n"); break; } if (!memcmp(prom_init, prom_init + mem, 32)) diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index 2f5bbd68e9a0..df761d38f7fc 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c @@ -36,8 +36,8 @@ static int __init uart8250_init_ssb(void) struct plat_serial8250_port *p = &(uart8250_data[i]); struct ssb_serial_port *ssb_port = &(mcore->serial_ports[i]); - p->mapbase = (unsigned int) ssb_port->regs; - p->membase = (void *) ssb_port->regs; + p->mapbase = (unsigned int)ssb_port->regs; + p->membase = (void *)ssb_port->regs; p->irq = ssb_port->irq + 2; p->uartclk = ssb_port->baud_base; p->regshift = ssb_port->reg_shift; @@ -62,8 +62,8 @@ static int __init uart8250_init_bcma(void) struct bcma_serial_port *bcma_port; bcma_port = &(cc->serial_ports[i]); - p->mapbase = (unsigned int) bcma_port->regs; - p->membase = (void *) bcma_port->regs; + p->mapbase = (unsigned int)bcma_port->regs; + p->membase = (void *)bcma_port->regs; p->irq = bcma_port->irq; p->uartclk = bcma_port->baud_base; p->regshift = bcma_port->reg_shift; diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index e43b5046cb30..82ff9fd2ab6e 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -42,7 +42,6 @@ #include <asm/reboot.h> #include <asm/time.h> #include <bcm47xx.h> -#include <bcm47xx_nvram.h> #include <bcm47xx_board.h> union bcm47xx_bus bcm47xx_bus; @@ -53,7 +52,7 @@ EXPORT_SYMBOL(bcm47xx_bus_type); static void bcm47xx_machine_restart(char *command) { - printk(KERN_ALERT "Please stand by while rebooting the system...\n"); + pr_alert("Please stand by while rebooting the system...\n"); local_irq_disable(); /* Set the watchdog timer to reset immediately */ switch (bcm47xx_bus_type) { @@ -108,7 +107,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, char buf[20]; /* Fill boardinfo structure */ - memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); + memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo)); bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL); @@ -127,7 +126,7 @@ static void __init bcm47xx_register_ssb(void) char buf[100]; struct ssb_mipscore *mcore; - err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, + err = ssb_bus_ssbbus_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE, bcm47xx_get_invariants); if (err) panic("Failed to initialize SSB bus (err %d)", err); @@ -137,7 +136,7 @@ static void __init bcm47xx_register_ssb(void) if (strstr(buf, "console=ttyS1")) { struct ssb_serial_port port; - printk(KERN_DEBUG "Swapping serial ports!\n"); + pr_debug("Swapping serial ports!\n"); /* swap serial ports */ memcpy(&port, &mcore->serial_ports[0], sizeof(port)); memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], @@ -169,7 +168,7 @@ void __init plat_mem_setup(void) struct cpuinfo_mips *c = ¤t_cpu_data; if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K)) { - printk(KERN_INFO "bcm47xx: using bcma bus\n"); + pr_info("Using bcma bus\n"); #ifdef CONFIG_BCM47XX_BCMA bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; bcm47xx_sprom_register_fallbacks(); @@ -180,7 +179,7 @@ void __init plat_mem_setup(void) #endif #endif } else { - printk(KERN_INFO "bcm47xx: using ssb bus\n"); + pr_info("Using ssb bus\n"); #ifdef CONFIG_BCM47XX_SSB bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; bcm47xx_sprom_register_fallbacks(); diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 2eff7fe99c6b..68ebf2322f8b 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -27,7 +27,6 @@ */ #include <bcm47xx.h> -#include <bcm47xx_nvram.h> #include <linux/if_ether.h> #include <linux/etherdevice.h> @@ -181,94 +180,245 @@ static void nvram_read_alpha2(const char *prefix, const char *name, memcpy(val, buf, 2); } +/* This is one-function-only macro, it uses local "sprom" variable! */ +#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \ + if (_revmask & BIT(sprom->revision)) \ + nvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \ + _allset, _fallback) +/* + * Special version of filling function that can be safely called for any SPROM + * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions + * for which the mapping is valid. + * It obviously requires some hexadecimal/bitmasks knowledge, but allows + * writing cleaner code (easy revisions handling). + * Note that while SPROM revision 0 was never used, we still keep BIT(0) + * reserved for it, just to keep numbering sane. + */ +static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom, + const char *prefix, bool fallback) +{ + const char *pre = prefix; + bool fb = fallback; + + ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true); + ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb); + ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true); + ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb); + ENTRY(0x00000002, u8, pre, "cc", country_code, 0, fb); + ENTRY(0xfffffff8, u8, pre, "regrev", regrev, 0, fb); + + ENTRY(0xfffffffe, u8, pre, "ledbh0", gpio0, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh1", gpio1, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh2", gpio2, 0xff, fb); + ENTRY(0xfffffffe, u8, pre, "ledbh3", gpio3, 0xff, fb); + + ENTRY(0x0000070e, u16, pre, "pa0b0", pa0b0, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa0b1", pa0b1, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa0b2", pa0b2, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa0itssit", itssi_bg, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa0maxpwr", maxpwr_bg, 0, fb); + + ENTRY(0x0000070c, u8, pre, "opo", opo, 0, fb); + ENTRY(0xfffffffe, u8, pre, "aa2g", ant_available_bg, 0, fb); + ENTRY(0xfffffffe, u8, pre, "aa5g", ant_available_a, 0, fb); + ENTRY(0x000007fe, s8, pre, "ag0", antenna_gain.a0, 0, fb); + ENTRY(0x000007fe, s8, pre, "ag1", antenna_gain.a1, 0, fb); + ENTRY(0x000007f0, s8, pre, "ag2", antenna_gain.a2, 0, fb); + ENTRY(0x000007f0, s8, pre, "ag3", antenna_gain.a3, 0, fb); + + ENTRY(0x0000070e, u16, pre, "pa1b0", pa1b0, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa1b1", pa1b1, 0, fb); + ENTRY(0x0000070e, u16, pre, "pa1b2", pa1b2, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob0", pa1lob0, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob1", pa1lob1, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1lob2", pa1lob2, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib0", pa1hib0, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib1", pa1hib1, 0, fb); + ENTRY(0x0000070c, u16, pre, "pa1hib2", pa1hib2, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa1itssit", itssi_a, 0, fb); + ENTRY(0x0000070e, u8, pre, "pa1maxpwr", maxpwr_a, 0, fb); + ENTRY(0x0000070c, u8, pre, "pa1lomaxpwr", maxpwr_al, 0, fb); + ENTRY(0x0000070c, u8, pre, "pa1himaxpwr", maxpwr_ah, 0, fb); + + ENTRY(0x00000708, u8, pre, "bxa2g", bxa2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssisav2g", rssisav2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismc2g", rssismc2g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismf2g", rssismf2g, 0, fb); + ENTRY(0x00000708, u8, pre, "bxa5g", bxa5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssisav5g", rssisav5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismc5g", rssismc5g, 0, fb); + ENTRY(0x00000708, u8, pre, "rssismf5g", rssismf5g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri2g", tri2g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5g", tri5g, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5gl", tri5gl, 0, fb); + ENTRY(0x00000708, u8, pre, "tri5gh", tri5gh, 0, fb); + ENTRY(0x00000708, s8, pre, "rxpo2g", rxpo2g, 0, fb); + ENTRY(0x00000708, s8, pre, "rxpo5g", rxpo5g, 0, fb); + ENTRY(0xfffffff0, u8, pre, "txchain", txchain, 0xf, fb); + ENTRY(0xfffffff0, u8, pre, "rxchain", rxchain, 0xf, fb); + ENTRY(0xfffffff0, u8, pre, "antswitch", antswitch, 0xff, fb); + ENTRY(0x00000700, u8, pre, "tssipos2g", fem.ghz2.tssipos, 0, fb); + ENTRY(0x00000700, u8, pre, "extpagain2g", fem.ghz2.extpa_gain, 0, fb); + ENTRY(0x00000700, u8, pre, "pdetrange2g", fem.ghz2.pdet_range, 0, fb); + ENTRY(0x00000700, u8, pre, "triso2g", fem.ghz2.tr_iso, 0, fb); + ENTRY(0x00000700, u8, pre, "antswctl2g", fem.ghz2.antswlut, 0, fb); + ENTRY(0x00000700, u8, pre, "tssipos5g", fem.ghz5.tssipos, 0, fb); + ENTRY(0x00000700, u8, pre, "extpagain5g", fem.ghz5.extpa_gain, 0, fb); + ENTRY(0x00000700, u8, pre, "pdetrange5g", fem.ghz5.pdet_range, 0, fb); + ENTRY(0x00000700, u8, pre, "triso5g", fem.ghz5.tr_iso, 0, fb); + ENTRY(0x00000700, u8, pre, "antswctl5g", fem.ghz5.antswlut, 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga0", txpid2g[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga1", txpid2g[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga2", txpid2g[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid2ga3", txpid2g[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga0", txpid5g[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga1", txpid5g[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga2", txpid5g[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5ga3", txpid5g[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla0", txpid5gl[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla1", txpid5gl[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla2", txpid5gl[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gla3", txpid5gl[3], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha0", txpid5gh[0], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha1", txpid5gh[1], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha2", txpid5gh[2], 0, fb); + ENTRY(0x000000f0, u8, pre, "txpid5gha3", txpid5gh[3], 0, fb); + + ENTRY(0xffffff00, u8, pre, "tempthresh", tempthresh, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempoffset", tempoffset, 0, fb); + ENTRY(0xffffff00, u16, pre, "rawtempsense", rawtempsense, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower", measpower, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempsense_slope", tempsense_slope, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempcorrx", tempcorrx, 0, fb); + ENTRY(0xffffff00, u8, pre, "tempsense_option", tempsense_option, 0, fb); + ENTRY(0x00000700, u8, pre, "freqoffset_corr", freqoffset_corr, 0, fb); + ENTRY(0x00000700, u8, pre, "iqcal_swp_dis", iqcal_swp_dis, 0, fb); + ENTRY(0x00000700, u8, pre, "hw_iqcal_en", hw_iqcal_en, 0, fb); + ENTRY(0x00000700, u8, pre, "elna2g", elna2g, 0, fb); + ENTRY(0x00000700, u8, pre, "elna5g", elna5g, 0, fb); + ENTRY(0xffffff00, u8, pre, "phycal_tempdelta", phycal_tempdelta, 0, fb); + ENTRY(0xffffff00, u8, pre, "temps_period", temps_period, 0, fb); + ENTRY(0xffffff00, u8, pre, "temps_hysteresis", temps_hysteresis, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower1", measpower1, 0, fb); + ENTRY(0xffffff00, u8, pre, "measpower2", measpower2, 0, fb); + + ENTRY(0x000001f0, u16, pre, "cck2gpo", cck2gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm2gpo", ofdm2gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5gpo", ofdm5gpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5glpo", ofdm5glpo, 0, fb); + ENTRY(0x000001f0, u32, pre, "ofdm5ghpo", ofdm5ghpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo0", mcs2gpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo1", mcs2gpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo2", mcs2gpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo3", mcs2gpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo4", mcs2gpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo5", mcs2gpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo6", mcs2gpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs2gpo7", mcs2gpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo0", mcs5gpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo1", mcs5gpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo2", mcs5gpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo3", mcs5gpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo4", mcs5gpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo5", mcs5gpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo6", mcs5gpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5gpo7", mcs5gpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo0", mcs5glpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo1", mcs5glpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo2", mcs5glpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo3", mcs5glpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo4", mcs5glpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo5", mcs5glpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo6", mcs5glpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5glpo7", mcs5glpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo0", mcs5ghpo[0], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo1", mcs5ghpo[1], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo2", mcs5ghpo[2], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo3", mcs5ghpo[3], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo4", mcs5ghpo[4], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo5", mcs5ghpo[5], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo6", mcs5ghpo[6], 0, fb); + ENTRY(0x000001f0, u16, pre, "mcs5ghpo7", mcs5ghpo[7], 0, fb); + ENTRY(0x000001f0, u16, pre, "cddpo", cddpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "stbcpo", stbcpo, 0, fb); + ENTRY(0x000001f0, u16, pre, "bw40po", bw40po, 0, fb); + ENTRY(0x000001f0, u16, pre, "bwduppo", bwduppo, 0, fb); + + ENTRY(0xfffffe00, u16, pre, "cckbw202gpo", cckbw202gpo, 0, fb); + ENTRY(0xfffffe00, u16, pre, "cckbw20ul2gpo", cckbw20ul2gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw202gpo", legofdmbw202gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul2gpo", legofdmbw20ul2gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205glpo", legofdmbw205glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5glpo", legofdmbw20ul5glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205gmpo", legofdmbw205gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5gmpo", legofdmbw20ul5gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw205ghpo", legofdmbw205ghpo, 0, fb); + ENTRY(0x00000600, u32, pre, "legofdmbw20ul5ghpo", legofdmbw20ul5ghpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw202gpo", mcsbw202gpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul2gpo", mcsbw20ul2gpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw402gpo", mcsbw402gpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205glpo", mcsbw205glpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5glpo", mcsbw20ul5glpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405glpo", mcsbw405glpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205gmpo", mcsbw205gmpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5gmpo", mcsbw20ul5gmpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405gmpo", mcsbw405gmpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw205ghpo", mcsbw205ghpo, 0, fb); + ENTRY(0x00000600, u32, pre, "mcsbw20ul5ghpo", mcsbw20ul5ghpo, 0, fb); + ENTRY(0xfffffe00, u32, pre, "mcsbw405ghpo", mcsbw405ghpo, 0, fb); + ENTRY(0x00000600, u16, pre, "mcs32po", mcs32po, 0, fb); + ENTRY(0x00000600, u16, pre, "legofdm40duppo", legofdm40duppo, 0, fb); + ENTRY(0x00000700, u8, pre, "pcieingress_war", pcieingress_war, 0, fb); + + /* TODO: rev 11 support */ + ENTRY(0x00000700, u8, pre, "rxgainerr2ga0", rxgainerr2ga[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr2ga1", rxgainerr2ga[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr2ga2", rxgainerr2ga[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla0", rxgainerr5gla[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla1", rxgainerr5gla[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gla2", rxgainerr5gla[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma0", rxgainerr5gma[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma1", rxgainerr5gma[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gma2", rxgainerr5gma[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha0", rxgainerr5gha[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha1", rxgainerr5gha[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gha2", rxgainerr5gha[2], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua0", rxgainerr5gua[0], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua1", rxgainerr5gua[1], 0, fb); + ENTRY(0x00000700, u8, pre, "rxgainerr5gua2", rxgainerr5gua[2], 0, fb); + + ENTRY(0xfffffe00, u8, pre, "sar2g", sar2g, 0, fb); + ENTRY(0xfffffe00, u8, pre, "sar5g", sar5g, 0, fb); + + /* TODO: rev 11 support */ + ENTRY(0x00000700, u8, pre, "noiselvl2ga0", noiselvl2ga[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl2ga1", noiselvl2ga[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl2ga2", noiselvl2ga[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla0", noiselvl5gla[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla1", noiselvl5gla[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gla2", noiselvl5gla[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma0", noiselvl5gma[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma1", noiselvl5gma[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gma2", noiselvl5gma[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha0", noiselvl5gha[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha1", noiselvl5gha[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gha2", noiselvl5gha[2], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua0", noiselvl5gua[0], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua1", noiselvl5gua[1], 0, fb); + ENTRY(0x00000700, u8, pre, "noiselvl5gua2", noiselvl5gua[2], 0, fb); +} +#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */ + static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, const char *prefix, bool fallback) { nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback); - nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback); - nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback); - nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback); - nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff, fallback); - nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0, - fallback); - nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0, - fallback); - nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0, - fallback); - nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0, - fallback); nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); } -static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0, fallback); - nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0, fallback); - nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0, fallback); - nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0, fallback); - nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0, - fallback); - nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0, fallback); - nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0, fallback); - nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0, fallback); -} - -static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0, - fallback); - nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0, fallback); -} - -static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom, - const char *prefix, bool fallback) -{ - nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0, fallback); - nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0, fallback); - nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0, - fallback); - nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0, - fallback); -} - -static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0, fallback); - nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0, - fallback); - nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0, - fallback); - nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0, - fallback); - nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0, fallback); - nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0, - fallback); - nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0, - fallback); - nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0, - fallback); - nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0, fallback); - nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0, fallback); - nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0, fallback); - nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0, fallback); - nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0, fallback); - nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0, fallback); -} - static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback); nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, &sprom->leddc_off_time, fallback); } @@ -276,309 +426,10 @@ static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix, static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0, fallback); - nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0, - fallback); - nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0, - fallback); - nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf, fallback); - nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf, fallback); - nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff, - fallback); nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time, &sprom->leddc_off_time, fallback); } -static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0, fallback); - nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0, fallback); - nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0, fallback); - nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0, - fallback); - nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0, fallback); - nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0, fallback); - nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0, fallback); - nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0, fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0, - fallback); -} - -static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0, - fallback); - nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0, - fallback); -} - -static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0, - fallback); - nvram_read_u8(prefix, NULL, "extpagain2g", - &sprom->fem.ghz2.extpa_gain, 0, fallback); - nvram_read_u8(prefix, NULL, "pdetrange2g", - &sprom->fem.ghz2.pdet_range, 0, fallback); - nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0, - fallback); - nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0, - fallback); - nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0, - fallback); - nvram_read_u8(prefix, NULL, "extpagain5g", - &sprom->fem.ghz5.extpa_gain, 0, fallback); - nvram_read_u8(prefix, NULL, "pdetrange5g", - &sprom->fem.ghz5.pdet_range, 0, fallback); - nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0, - fallback); - nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0, - fallback); - nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0, - fallback); - nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0, - fallback); - nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0, - fallback); - nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0, - fallback); - nvram_read_u8(prefix, NULL, "tempsense_slope", - &sprom->tempsense_slope, 0, fallback); - nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0, - fallback); - nvram_read_u8(prefix, NULL, "tempsense_option", - &sprom->tempsense_option, 0, fallback); - nvram_read_u8(prefix, NULL, "freqoffset_corr", - &sprom->freqoffset_corr, 0, fallback); - nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0, - fallback); - nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0, - fallback); - nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0, fallback); - nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0, fallback); - nvram_read_u8(prefix, NULL, "phycal_tempdelta", - &sprom->phycal_tempdelta, 0, fallback); - nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0, - fallback); - nvram_read_u8(prefix, NULL, "temps_hysteresis", - &sprom->temps_hysteresis, 0, fallback); - nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0, - fallback); - nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0, - fallback); - nvram_read_u8(prefix, NULL, "rxgainerr2ga0", - &sprom->rxgainerr2ga[0], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr2ga1", - &sprom->rxgainerr2ga[1], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr2ga2", - &sprom->rxgainerr2ga[2], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gla0", - &sprom->rxgainerr5gla[0], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gla1", - &sprom->rxgainerr5gla[1], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gla2", - &sprom->rxgainerr5gla[2], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gma0", - &sprom->rxgainerr5gma[0], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gma1", - &sprom->rxgainerr5gma[1], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gma2", - &sprom->rxgainerr5gma[2], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gha0", - &sprom->rxgainerr5gha[0], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gha1", - &sprom->rxgainerr5gha[1], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gha2", - &sprom->rxgainerr5gha[2], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gua0", - &sprom->rxgainerr5gua[0], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gua1", - &sprom->rxgainerr5gua[1], 0, fallback); - nvram_read_u8(prefix, NULL, "rxgainerr5gua2", - &sprom->rxgainerr5gua[2], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0, - fallback); - nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0, - fallback); - nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0, - fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gla0", - &sprom->noiselvl5gla[0], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gla1", - &sprom->noiselvl5gla[1], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gla2", - &sprom->noiselvl5gla[2], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gma0", - &sprom->noiselvl5gma[0], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gma1", - &sprom->noiselvl5gma[1], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gma2", - &sprom->noiselvl5gma[2], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gha0", - &sprom->noiselvl5gha[0], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gha1", - &sprom->noiselvl5gha[1], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gha2", - &sprom->noiselvl5gha[2], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gua0", - &sprom->noiselvl5gua[0], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gua1", - &sprom->noiselvl5gua[1], 0, fallback); - nvram_read_u8(prefix, NULL, "noiselvl5gua2", - &sprom->noiselvl5gua[2], 0, fallback); - nvram_read_u8(prefix, NULL, "pcieingress_war", - &sprom->pcieingress_war, 0, fallback); -} - -static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix, - bool fallback) -{ - nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0, - fallback); - nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "legofdmbw202gpo", - &sprom->legofdmbw202gpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo", - &sprom->legofdmbw20ul2gpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw205glpo", - &sprom->legofdmbw205glpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo", - &sprom->legofdmbw20ul5glpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw205gmpo", - &sprom->legofdmbw205gmpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo", - &sprom->legofdmbw20ul5gmpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw205ghpo", - &sprom->legofdmbw205ghpo, 0, fallback); - nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo", - &sprom->legofdmbw20ul5ghpo, 0, fallback); - nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo", - &sprom->mcsbw20ul5glpo, 0, fallback); - nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo", - &sprom->mcsbw20ul5gmpo, 0, fallback); - nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0, - fallback); - nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo", - &sprom->mcsbw20ul5ghpo, 0, fallback); - nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0, - fallback); - nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0, fallback); - nvram_read_u16(prefix, NULL, "legofdm40duppo", - &sprom->legofdm40duppo, 0, fallback); - nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0, fallback); - nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0, fallback); -} - static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom, const char *prefix, bool fallback) { @@ -715,10 +566,6 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, true); - nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0, - fallback); - nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, true); nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, &sprom->boardflags_hi, fallback); nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, @@ -736,58 +583,39 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix, switch (sprom->revision) { case 1: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r1(sprom, prefix, fallback); break; case 2: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r2389(sprom, prefix, fallback); break; case 3: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r2389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r389(sprom, prefix, fallback); bcm47xx_fill_sprom_r3(sprom, prefix, fallback); break; case 4: case 5: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r458(sprom, prefix, fallback); - bcm47xx_fill_sprom_r45(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback); break; case 8: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r2389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r389(sprom, prefix, fallback); bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r458(sprom, prefix, fallback); - bcm47xx_fill_sprom_r89(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); break; case 9: bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r2389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r389(sprom, prefix, fallback); bcm47xx_fill_sprom_r4589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r89(sprom, prefix, fallback); - bcm47xx_fill_sprom_r9(sprom, prefix, fallback); bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback); break; default: - pr_warn("Unsupported SPROM revision %d detected. Will extract" - " v1\n", sprom->revision); + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + sprom->revision); sprom->revision = 1; bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback); - bcm47xx_fill_sprom_r12389(sprom, prefix, fallback); - bcm47xx_fill_sprom_r1(sprom, prefix, fallback); } + + bcm47xx_sprom_fill_auto(sprom, prefix, fallback); } #ifdef CONFIG_BCM47XX_SSB @@ -829,13 +657,45 @@ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) bcm47xx_fill_sprom(out, prefix, false); return 0; } else { - pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n"); + pr_warn("Unable to fill SPROM for given bustype.\n"); return -EINVAL; } } #endif #if defined(CONFIG_BCM47XX_BCMA) +/* + * Having many NVRAM entries for PCI devices led to repeating prefixes like + * pci/1/1/ all the time and wasting flash space. So at some point Broadcom + * decided to introduce prefixes like 0: 1: 2: etc. + * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0: + * instead of pci/2/1/. + */ +static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size) +{ + size_t prefix_len = strlen(prefix); + size_t short_len = prefix_len - 1; + char nvram_var[10]; + char buf[20]; + int i; + + /* Passed prefix has to end with a slash */ + if (prefix_len <= 0 || prefix[prefix_len - 1] != '/') + return; + + for (i = 0; i < 3; i++) { + if (snprintf(nvram_var, sizeof(nvram_var), "devpath%d", i) <= 0) + continue; + if (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0) + continue; + if (!strcmp(buf, prefix) || + (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) { + snprintf(prefix, prefix_size, "%d:", i); + return; + } + } +} + static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) { char prefix[10]; @@ -847,6 +707,7 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) snprintf(prefix, sizeof(prefix), "pci/%u/%u/", bus->host_pci->bus->number + 1, PCI_SLOT(bus->host_pci->devfn)); + bcm47xx_sprom_apply_prefix_alias(prefix, sizeof(prefix)); bcm47xx_fill_sprom(out, prefix, false); return 0; case BCMA_HOSTTYPE_SOC: @@ -861,7 +722,7 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) } return 0; default: - pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n"); + pr_warn("Unable to fill SPROM for given bustype.\n"); return -EINVAL; } } diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c index 2c85d9254b5e..74224cf2e84d 100644 --- a/arch/mips/bcm47xx/time.c +++ b/arch/mips/bcm47xx/time.c @@ -22,12 +22,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include <linux/init.h> #include <linux/ssb/ssb.h> #include <asm/time.h> #include <bcm47xx.h> -#include <bcm47xx_nvram.h> #include <bcm47xx_board.h> void __init plat_time_init(void) diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index e1f27d653f60..7019e2967009 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -17,7 +17,6 @@ #include <bcm63xx_cpu.h> #include <bcm63xx_io.h> #include <bcm63xx_regs.h> -#include <bcm63xx_gpio.h> void __init prom_init(void) { @@ -53,9 +52,6 @@ void __init prom_init(void) reg &= ~mask; bcm_perf_writel(reg, PERF_CKCTL_REG); - /* register gpiochip */ - bcm63xx_gpio_init(); - /* do low level board init */ board_prom_init(); diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 6660c7ddf87b..240fb4ffa55c 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -20,6 +20,7 @@ #include <bcm63xx_cpu.h> #include <bcm63xx_regs.h> #include <bcm63xx_io.h> +#include <bcm63xx_gpio.h> void bcm63xx_machine_halt(void) { @@ -160,6 +161,9 @@ void __init plat_mem_setup(void) int __init bcm63xx_register_devices(void) { + /* register gpiochip */ + bcm63xx_gpio_init(); + return board_register_devices(); } diff --git a/arch/mips/bmips/Kconfig b/arch/mips/bmips/Kconfig new file mode 100644 index 000000000000..f35c84c019df --- /dev/null +++ b/arch/mips/bmips/Kconfig @@ -0,0 +1,62 @@ +if BMIPS_GENERIC + +choice + prompt "Built-in device tree" + help + Legacy bootloaders do not pass a DTB pointer to the kernel, so + if a "wrapper" is not being used, the kernel will need to include + a device tree that matches the target board. + + The builtin DTB will only be used if the firmware does not supply + a valid DTB. + +config DT_NONE + bool "None" + +config DT_BCM93384WVG + bool "BCM93384WVG Zephyr CPU" + select BUILTIN_DTB + +config DT_BCM93384WVG_VIPER + bool "BCM93384WVG Viper CPU (EXPERIMENTAL)" + select BUILTIN_DTB + +config DT_BCM96368MVWG + bool "BCM96368MVWG" + select BUILTIN_DTB + +config DT_BCM9EJTAGPRB + bool "BCM9EJTAGPRB" + select BUILTIN_DTB + +config DT_BCM97125CBMB + bool "BCM97125CBMB" + select BUILTIN_DTB + +config DT_BCM97346DBSMB + bool "BCM97346DBSMB" + select BUILTIN_DTB + +config DT_BCM97358SVMB + bool "BCM97358SVMB" + select BUILTIN_DTB + +config DT_BCM97360SVMB + bool "BCM97360SVMB" + select BUILTIN_DTB + +config DT_BCM97362SVMB + bool "BCM97362SVMB" + select BUILTIN_DTB + +config DT_BCM97420C + bool "BCM97420C" + select BUILTIN_DTB + +config DT_BCM97425SVMB + bool "BCM97425SVMB" + select BUILTIN_DTB + +endchoice + +endif diff --git a/arch/mips/bcm3384/Makefile b/arch/mips/bmips/Makefile index a393955cba08..a393955cba08 100644 --- a/arch/mips/bcm3384/Makefile +++ b/arch/mips/bmips/Makefile diff --git a/arch/mips/bmips/Platform b/arch/mips/bmips/Platform new file mode 100644 index 000000000000..5f127fd7f4b5 --- /dev/null +++ b/arch/mips/bmips/Platform @@ -0,0 +1,7 @@ +# +# Broadcom Generic BMIPS kernel +# +platform-$(CONFIG_BMIPS_GENERIC) += bmips/ +cflags-$(CONFIG_BMIPS_GENERIC) += \ + -I$(srctree)/arch/mips/include/asm/mach-bmips/ +load-$(CONFIG_BMIPS_GENERIC) := 0xffffffff80010000 diff --git a/arch/mips/bmips/dma.c b/arch/mips/bmips/dma.c new file mode 100644 index 000000000000..04790f4e1805 --- /dev/null +++ b/arch/mips/bmips/dma.c @@ -0,0 +1,117 @@ +/* + * 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 Kevin Cernekee <cernekee@gmail.com> + */ + +#define pr_fmt(fmt) "bmips-dma: " fmt + +#include <linux/device.h> +#include <linux/dma-direction.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/printk.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <dma-coherence.h> + +/* + * BCM338x has configurable address translation windows which allow the + * peripherals' DMA addresses to be different from the Zephyr-visible + * physical addresses. e.g. usb_dma_addr = zephyr_pa ^ 0x08000000 + * + * If the "brcm,ubus" node has a "dma-ranges" property we will enable this + * translation globally using the provided information. This implements a + * very limited subset of "dma-ranges" support and it will probably be + * replaced by a more generic version later. + */ + +struct bmips_dma_range { + u32 child_addr; + u32 parent_addr; + u32 size; +}; + +static struct bmips_dma_range *bmips_dma_ranges; + +#define FLUSH_RAC 0x100 + +static dma_addr_t bmips_phys_to_dma(struct device *dev, phys_addr_t pa) +{ + struct bmips_dma_range *r; + + for (r = bmips_dma_ranges; r && r->size; r++) { + if (pa >= r->child_addr && + pa < (r->child_addr + r->size)) + return pa - r->child_addr + r->parent_addr; + } + return pa; +} + +dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) +{ + return bmips_phys_to_dma(dev, virt_to_phys(addr)); +} + +dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) +{ + return bmips_phys_to_dma(dev, page_to_phys(page)); +} + +unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) +{ + struct bmips_dma_range *r; + + for (r = bmips_dma_ranges; r && r->size; r++) { + if (dma_addr >= r->parent_addr && + dma_addr < (r->parent_addr + r->size)) + return dma_addr - r->parent_addr + r->child_addr; + } + return dma_addr; +} + +static int __init bmips_init_dma_ranges(void) +{ + struct device_node *np = + of_find_compatible_node(NULL, NULL, "brcm,ubus"); + const __be32 *data; + struct bmips_dma_range *r; + int len; + + if (!np) + return 0; + + data = of_get_property(np, "dma-ranges", &len); + if (!data) + goto out_good; + + len /= sizeof(*data) * 3; + if (!len) + goto out_bad; + + /* add a dummy (zero) entry at the end as a sentinel */ + bmips_dma_ranges = kzalloc(sizeof(struct bmips_dma_range) * (len + 1), + GFP_KERNEL); + if (!bmips_dma_ranges) + goto out_bad; + + for (r = bmips_dma_ranges; len; len--, r++) { + r->child_addr = be32_to_cpup(data++); + r->parent_addr = be32_to_cpup(data++); + r->size = be32_to_cpup(data++); + } + +out_good: + of_node_put(np); + return 0; + +out_bad: + pr_err("error parsing dma-ranges property\n"); + of_node_put(np); + return -EINVAL; +} +arch_initcall(bmips_init_dma_ranges); diff --git a/arch/mips/bmips/irq.c b/arch/mips/bmips/irq.c new file mode 100644 index 000000000000..14552e58ff7e --- /dev/null +++ b/arch/mips/bmips/irq.c @@ -0,0 +1,38 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2014 Broadcom Corporation + * Author: Kevin Cernekee <cernekee@gmail.com> + */ + +#include <linux/of.h> +#include <linux/irqchip.h> + +#include <asm/bmips.h> +#include <asm/irq.h> +#include <asm/irq_cpu.h> +#include <asm/time.h> + +unsigned int get_c0_compare_int(void) +{ + return CP0_LEGACY_COMPARE_IRQ; +} + +void __init arch_init_irq(void) +{ + struct device_node *dn; + + /* Only the STB (bcm7038) controller supports SMP IRQ affinity */ + dn = of_find_compatible_node(NULL, NULL, "brcm,bcm7038-l1-intc"); + if (dn) + of_node_put(dn); + else + bmips_tp1_irqs = 0; + + irqchip_init(); +} + +OF_DECLARE_2(irqchip, mips_cpu_intc, "mti,cpu-interrupt-controller", + mips_cpu_irq_of_init); diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c new file mode 100644 index 000000000000..fae800e8b1e1 --- /dev/null +++ b/arch/mips/bmips/setup.c @@ -0,0 +1,194 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> + * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> + */ + +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/bootmem.h> +#include <linux/clk-provider.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> +#include <linux/smp.h> +#include <asm/addrspace.h> +#include <asm/bmips.h> +#include <asm/bootinfo.h> +#include <asm/cpu-type.h> +#include <asm/mipsregs.h> +#include <asm/prom.h> +#include <asm/smp-ops.h> +#include <asm/time.h> +#include <asm/traps.h> + +#define RELO_NORMAL_VEC BIT(18) + +#define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c)) +#define BCM6328_TP1_DISABLED BIT(9) + +static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000; + +struct bmips_quirk { + const char *compatible; + void (*quirk_fn)(void); +}; + +static void kbase_setup(void) +{ + __raw_writel(kbase | RELO_NORMAL_VEC, + BMIPS_GET_CBR() + BMIPS_RELO_VECTOR_CONTROL_1); + ebase = kbase; +} + +static void bcm3384_viper_quirks(void) +{ + /* + * Some experimental CM boxes are set up to let CM own the Viper TP0 + * and let Linux own TP1. This requires moving the kernel + * load address to a non-conflicting region (e.g. via + * CONFIG_PHYSICAL_START) and supplying an alternate DTB. + * If we detect this condition, we need to move the MIPS exception + * vectors up to an area that we own. + * + * This is distinct from the OTHER special case mentioned in + * smp-bmips.c (boot on TP1, but enable SMP, then TP0 becomes our + * logical CPU#1). For the Viper TP1 case, SMP is off limits. + * + * Also note that many BMIPS435x CPUs do not have a + * BMIPS_RELO_VECTOR_CONTROL_1 register, so it isn't safe to just + * write VMLINUX_LOAD_ADDRESS into that register on every SoC. + */ + board_ebase_setup = &kbase_setup; + bmips_smp_enabled = 0; +} + +static void bcm63xx_fixup_cpu1(void) +{ + /* + * The bootloader has set up the CPU1 reset vector at + * 0xa000_0200. + * This conflicts with the special interrupt vector (IV). + * The bootloader has also set up CPU1 to respond to the wrong + * IPI interrupt. + * Here we will start up CPU1 in the background and ask it to + * reconfigure itself then go back to sleep. + */ + memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20); + __sync(); + set_c0_cause(C_SW0); + cpumask_set_cpu(1, &bmips_booted_mask); +} + +static void bcm6328_quirks(void) +{ + /* Check CPU1 status in OTP (it is usually disabled) */ + if (__raw_readl(REG_BCM6328_OTP) & BCM6328_TP1_DISABLED) + bmips_smp_enabled = 0; + else + bcm63xx_fixup_cpu1(); +} + +static void bcm6368_quirks(void) +{ + bcm63xx_fixup_cpu1(); +} + +static const struct bmips_quirk bmips_quirk_list[] = { + { "brcm,bcm3384-viper", &bcm3384_viper_quirks }, + { "brcm,bcm33843-viper", &bcm3384_viper_quirks }, + { "brcm,bcm6328", &bcm6328_quirks }, + { "brcm,bcm6368", &bcm6368_quirks }, + { }, +}; + +void __init prom_init(void) +{ + register_bmips_smp_ops(); +} + +void __init prom_free_prom_memory(void) +{ +} + +const char *get_system_type(void) +{ + return "Generic BMIPS kernel"; +} + +void __init plat_time_init(void) +{ + struct device_node *np; + u32 freq; + + np = of_find_node_by_name(NULL, "cpus"); + if (!np) + panic("missing 'cpus' DT node"); + if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) + panic("missing 'mips-hpt-frequency' property"); + of_node_put(np); + + mips_hpt_frequency = freq; +} + +void __init plat_mem_setup(void) +{ + void *dtb; + const struct bmips_quirk *q; + + set_io_port_base(0); + ioport_resource.start = 0; + ioport_resource.end = ~0; + + /* intended to somewhat resemble ARM; see Documentation/arm/Booting */ + if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) + dtb = phys_to_virt(fw_arg2); + else if (__dtb_start != __dtb_end) + dtb = (void *)__dtb_start; + else + panic("no dtb found"); + + __dt_setup_arch(dtb); + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + + for (q = bmips_quirk_list; q->quirk_fn; q++) { + if (of_flat_dt_is_compatible(of_get_flat_dt_root(), + q->compatible)) { + q->quirk_fn(); + } + } +} + +void __init device_tree_init(void) +{ + struct device_node *np; + + unflatten_and_copy_device_tree(); + + /* Disable SMP boot unless both CPUs are listed in DT and !disabled */ + np = of_find_node_by_name(NULL, "cpus"); + if (np && of_get_available_child_count(np) <= 1) + bmips_smp_enabled = 0; + of_node_put(np); +} + +int __init plat_of_setup(void) +{ + return __dt_register_buses("simple-bus", NULL); +} + +arch_initcall(plat_of_setup); + +static int __init plat_dev_init(void) +{ + of_clk_init(NULL); + return 0; +} + +device_initcall(plat_dev_init); diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 61af6b6ab13d..dc91bde10d62 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -12,6 +12,8 @@ # Author: Wu Zhangjin <wuzhangjin@gmail.com> # +include $(srctree)/arch/mips/Kbuild.platforms + # set the default size of the mallocing area for decompressing BOOT_HEAP_SIZE := 0x400000 @@ -30,9 +32,10 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ targets := head.o decompress.o string.o dbg.o uart-16550.o uart-alchemy.o # decompressor objects (linked with vmlinuz) -vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/dbg.o +vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o ifdef CONFIG_DEBUG_ZBOOT +vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/dbg.o vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o endif @@ -66,8 +69,8 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE # Calculate the load address of the compressed kernel image hostprogs-y := calc_vmlinuz_load_addr -ifeq ($(CONFIG_MACH_JZ4740),y) -VMLINUZ_LOAD_ADDRESS := 0x80600000 +ifneq ($(zload-y),) +VMLINUZ_LOAD_ADDRESS := $(zload-y) else VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS)) diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index 31903cf9709d..54831069a206 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -28,8 +28,13 @@ unsigned long free_mem_end_ptr; extern unsigned char __image_begin, __image_end; /* debug interfaces */ +#ifdef CONFIG_DEBUG_ZBOOT extern void puts(const char *s); extern void puthex(unsigned long long val); +#else +#define puts(s) do {} while (0) +#define puthex(val) do {} while (0) +#endif void error(char *x) { diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile index 4f49fa477f14..5d95e4bd709a 100644 --- a/arch/mips/boot/dts/Makefile +++ b/arch/mips/boot/dts/Makefile @@ -1,21 +1,12 @@ -dtb-$(CONFIG_BCM3384) += bcm93384wvg.dtb -dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb -dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb -dtb-$(CONFIG_DT_XLP_EVP) += xlp_evp.dtb -dtb-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb -dtb-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb -dtb-$(CONFIG_DT_XLP_GVP) += xlp_gvp.dtb -dtb-$(CONFIG_DTB_RT2880_EVAL) += rt2880_eval.dtb -dtb-$(CONFIG_DTB_RT305X_EVAL) += rt3052_eval.dtb -dtb-$(CONFIG_DTB_RT3883_EVAL) += rt3883_eval.dtb -dtb-$(CONFIG_DTB_MT7620A_EVAL) += mt7620a_eval.dtb -dtb-$(CONFIG_MIPS_SEAD3) += sead3.dtb - -obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) - -targets += dtbs -targets += $(dtb-y) - -dtbs: $(addprefix $(obj)/, $(dtb-y)) - -clean-files += *.dtb *.dtb.S +dts-dirs += brcm +dts-dirs += cavium-octeon +dts-dirs += lantiq +dts-dirs += mti +dts-dirs += netlogic +dts-dirs += ralink + +obj-y := $(addsuffix /, $(dts-dirs)) + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/bcm3384.dtsi b/arch/mips/boot/dts/bcm3384.dtsi deleted file mode 100644 index 21b074a99c94..000000000000 --- a/arch/mips/boot/dts/bcm3384.dtsi +++ /dev/null @@ -1,109 +0,0 @@ -/ { - #address-cells = <1>; - #size-cells = <1>; - compatible = "brcm,bcm3384", "brcm,bcm33843"; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - /* On BMIPS5000 this is 1/8th of the CPU core clock */ - mips-hpt-frequency = <100000000>; - - cpu@0 { - compatible = "brcm,bmips5000"; - device_type = "cpu"; - reg = <0>; - }; - - cpu@1 { - compatible = "brcm,bmips5000"; - device_type = "cpu"; - reg = <1>; - }; - }; - - clocks { - #address-cells = <1>; - #size-cells = <0>; - - periph_clk: periph_clk@0 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <54000000>; - }; - }; - - aliases { - uart0 = &uart0; - }; - - cpu_intc: cpu_intc@0 { - #address-cells = <0>; - compatible = "mti,cpu-interrupt-controller"; - - interrupt-controller; - #interrupt-cells = <1>; - }; - - periph_intc: periph_intc@14e00038 { - compatible = "brcm,bcm3384-intc"; - reg = <0x14e00038 0x8 0x14e00340 0x8>; - - interrupt-controller; - #interrupt-cells = <1>; - - interrupt-parent = <&cpu_intc>; - interrupts = <4>; - }; - - zmips_intc: zmips_intc@104b0060 { - compatible = "brcm,bcm3384-intc"; - reg = <0x104b0060 0x8>; - - interrupt-controller; - #interrupt-cells = <1>; - - interrupt-parent = <&periph_intc>; - interrupts = <29>; - }; - - iop_intc: iop_intc@14e00058 { - compatible = "brcm,bcm3384-intc"; - reg = <0x14e00058 0x8>; - - interrupt-controller; - #interrupt-cells = <1>; - - interrupt-parent = <&cpu_intc>; - interrupts = <6>; - }; - - uart0: serial@14e00520 { - compatible = "brcm,bcm6345-uart"; - reg = <0x14e00520 0x18>; - interrupt-parent = <&periph_intc>; - interrupts = <2>; - clocks = <&periph_clk>; - status = "disabled"; - }; - - ehci0: usb@15400300 { - compatible = "brcm,bcm3384-ehci", "generic-ehci"; - reg = <0x15400300 0x100>; - big-endian; - interrupt-parent = <&periph_intc>; - interrupts = <41>; - status = "disabled"; - }; - - ohci0: usb@15400400 { - compatible = "brcm,bcm3384-ohci", "generic-ohci"; - reg = <0x15400400 0x100>; - big-endian; - no-big-frame-no; - interrupt-parent = <&periph_intc>; - interrupts = <40>; - status = "disabled"; - }; -}; diff --git a/arch/mips/boot/dts/brcm/Makefile b/arch/mips/boot/dts/brcm/Makefile new file mode 100644 index 000000000000..1c8353bfe003 --- /dev/null +++ b/arch/mips/boot/dts/brcm/Makefile @@ -0,0 +1,19 @@ +dtb-$(CONFIG_DT_BCM93384WVG) += bcm93384wvg.dtb +dtb-$(CONFIG_DT_BCM93384WVG_VIPER) += bcm93384wvg_viper.dtb +dtb-$(CONFIG_DT_BCM96368MVWG) += bcm96368mvwg.dtb +dtb-$(CONFIG_DT_BCM9EJTAGPRB) += bcm9ejtagprb.dtb +dtb-$(CONFIG_DT_BCM97125CBMB) += bcm97125cbmb.dtb +dtb-$(CONFIG_DT_BCM97346DBSMB) += bcm97346dbsmb.dtb +dtb-$(CONFIG_DT_BCM97358SVMB) += bcm97358svmb.dtb +dtb-$(CONFIG_DT_BCM97360SVMB) += bcm97360svmb.dtb +dtb-$(CONFIG_DT_BCM97362SVMB) += bcm97362svmb.dtb +dtb-$(CONFIG_DT_BCM97420C) += bcm97420c.dtb +dtb-$(CONFIG_DT_BCM97425SVMB) += bcm97425svmb.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/brcm/bcm3384_viper.dtsi b/arch/mips/boot/dts/brcm/bcm3384_viper.dtsi new file mode 100644 index 000000000000..aa406b43c65f --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm3384_viper.dtsi @@ -0,0 +1,108 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm3384-viper", "brcm,bcm33843-viper"; + + memory@0 { + device_type = "memory"; + + /* Typical ranges. The bootloader should fill these in. */ + reg = <0x06000000 0x02000000>, + <0x0e000000 0x02000000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + /* 1/2 of the CPU core clock (standard MIPS behavior) */ + mips-hpt-frequency = <300000000>; + + cpu@0 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <0>; + }; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + periph_clk: periph_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <54000000>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + ubus { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "brcm,ubus", "simple-bus"; + ranges; + /* No dma-ranges on Viper. */ + + periph_intc: periph_intc@14e00048 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x14e00048 0x4 0x14e0004c 0x4>, + <0x14e00350 0x4 0x14e00354 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <4>; + }; + + cmips_intc: cmips_intc@151f8048 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x151f8048 0x4 0x151f804c 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <30>; + brcm,int-map-mask = <0xffffffff>; + }; + + uart0: serial@14e00520 { + compatible = "brcm,bcm6345-uart"; + reg = <0x14e00520 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <2>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + ehci0: usb@15400300 { + compatible = "brcm,bcm3384-ehci", "generic-ehci"; + reg = <0x15400300 0x100>; + big-endian; + interrupt-parent = <&periph_intc>; + interrupts = <41>; + status = "disabled"; + }; + + ohci0: usb@15400400 { + compatible = "brcm,bcm3384-ohci", "generic-ohci"; + reg = <0x15400400 0x100>; + big-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <40>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm3384_zephyr.dtsi b/arch/mips/boot/dts/brcm/bcm3384_zephyr.dtsi new file mode 100644 index 000000000000..a7bd8564e9f6 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm3384_zephyr.dtsi @@ -0,0 +1,126 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm3384", "brcm,bcm33843"; + + memory@0 { + device_type = "memory"; + + /* Typical range. The bootloader should fill this in. */ + reg = <0x0 0x08000000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + /* On BMIPS5000 this is 1/8th of the CPU core clock */ + mips-hpt-frequency = <100000000>; + + cpu@0 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <1>; + }; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + periph_clk: periph_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <54000000>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + ubus { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "brcm,ubus", "simple-bus"; + ranges; + dma-ranges = <0x00000000 0x08000000 0x08000000>, + <0x08000000 0x00000000 0x08000000>; + + periph_intc: periph_intc@14e00038 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x14e00038 0x4 0x14e0003c 0x4>, + <0x14e00340 0x4 0x14e00344 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <4>; + }; + + zmips_intc: zmips_intc@104b0060 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x104b0060 0x4 0x104b0064 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <29>; + brcm,int-map-mask = <0xffffffff>; + }; + + iop_intc: iop_intc@14e00058 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x14e00058 0x4 0x14e0005c 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <6>; + brcm,int-map-mask = <0xffffffff>; + }; + + uart0: serial@14e00520 { + compatible = "brcm,bcm6345-uart"; + reg = <0x14e00520 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <2>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + ehci0: usb@15400300 { + compatible = "brcm,bcm3384-ehci", "generic-ehci"; + reg = <0x15400300 0x100>; + big-endian; + interrupt-parent = <&periph_intc>; + interrupts = <41>; + status = "disabled"; + }; + + ohci0: usb@15400400 { + compatible = "brcm,bcm3384-ohci", "generic-ohci"; + reg = <0x15400400 0x100>; + big-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <40>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi new file mode 100644 index 000000000000..41891c1e58bd --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi @@ -0,0 +1,86 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm6328"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <160000000>; + + cpu@0 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <1>; + }; + }; + + clocks { + periph_clk: periph_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + ubus { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges; + + periph_intc: periph_intc@10000020 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x10000024 0x4 0x1000002c 0x4>, + <0x10000020 0x4 0x10000028 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + }; + + uart0: serial@10000100 { + compatible = "brcm,bcm6345-uart"; + reg = <0x10000100 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <28>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + timer: timer@10000040 { + compatible = "syscon"; + reg = <0x10000040 0x2c>; + little-endian; + }; + + reboot { + compatible = "syscon-reboot"; + regmap = <&timer>; + offset = <0x28>; + mask = <0x1>; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi new file mode 100644 index 000000000000..45152bc22117 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi @@ -0,0 +1,93 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm6368"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <200000000>; + + cpu@0 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips4350"; + device_type = "cpu"; + reg = <1>; + }; + + }; + + clocks { + periph_clk: periph_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + ubus { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges; + + periph_intc: periph_intc@10000020 { + compatible = "brcm,bcm3380-l2-intc"; + reg = <0x10000024 0x4 0x1000002c 0x4>, + <0x10000020 0x4 0x10000028 0x4>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + }; + + uart0: serial@10000100 { + compatible = "brcm,bcm6345-uart"; + reg = <0x10000100 0x18>; + interrupt-parent = <&periph_intc>; + interrupts = <2>; + clocks = <&periph_clk>; + status = "disabled"; + }; + + ehci0: usb@10001500 { + compatible = "brcm,bcm6368-ehci", "generic-ehci"; + reg = <0x10001500 0x100>; + big-endian; + interrupt-parent = <&periph_intc>; + interrupts = <7>; + status = "disabled"; + }; + + ohci0: usb@10001600 { + compatible = "brcm,bcm6368-ohci", "generic-ohci"; + reg = <0x10001600 0x100>; + big-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <5>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7125.dtsi b/arch/mips/boot/dts/brcm/bcm7125.dtsi new file mode 100644 index 000000000000..1a7efa883c5e --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7125.dtsi @@ -0,0 +1,139 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7125"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <202500000>; + + cpu@0 { + compatible = "brcm,bmips4380"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips4380"; + device_type = "cpu"; + reg = <1>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@441400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x441400 0x30>, <0x441600 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@401800 { + compatible = "brcm,l2-intc"; + reg = <0x401800 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <23>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x2f7>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "pci_0", + "bsp_0", "rdc_0", "rptd_0", + "avd_0", "jtag_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406780 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406780 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <18>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; + reg = <0x404000 0x60c>; + little-endian; + }; + + reboot { + compatible = "brcm,bcm7038-reboot"; + syscon = <&sun_top_ctrl 0x8 0x14>; + }; + + uart0: serial@406b00 { + compatible = "ns16550a"; + reg = <0x406b00 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <21>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + ehci0: usb@488300 { + compatible = "brcm,bcm7125-ehci", "generic-ehci"; + reg = <0x488300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <60>; + status = "disabled"; + }; + + ohci0: usb@488400 { + compatible = "brcm,bcm7125-ohci", "generic-ohci"; + reg = <0x488400 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi new file mode 100644 index 000000000000..1f30728a3177 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -0,0 +1,224 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7346"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <163125000>; + + cpu@0 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <1>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@411400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x411400 0x30>, <0x411600 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <51>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x673>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "bsp_0", + "rdc_0", "raaga_0", + "jtag_0", "svd_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406780 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406780 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <59>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406900 { + compatible = "ns16550a"; + reg = <0x406900 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <64>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@430000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v2"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x430000 0x4c8c>; + interrupts = <24>, <25>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v2"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7346-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <68>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7346-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <70>; + status = "disabled"; + }; + + ehci1: usb@480500 { + compatible = "brcm,bcm7346-ehci", "generic-ehci"; + reg = <0x480500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <69>; + status = "disabled"; + }; + + ohci1: usb@480600 { + compatible = "brcm,bcm7346-ohci", "generic-ohci"; + reg = <0x480600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <71>; + status = "disabled"; + }; + + ehci2: usb@490300 { + compatible = "brcm,bcm7346-ehci", "generic-ehci"; + reg = <0x490300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <73>; + status = "disabled"; + }; + + ohci2: usb@490400 { + compatible = "brcm,bcm7346-ohci", "generic-ohci"; + reg = <0x490400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <75>; + status = "disabled"; + }; + + ehci3: usb@490500 { + compatible = "brcm,bcm7346-ehci", "generic-ehci"; + reg = <0x490500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <74>; + status = "disabled"; + }; + + ohci3: usb@490600 { + compatible = "brcm,bcm7346-ohci", "generic-ohci"; + reg = <0x490600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <76>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi new file mode 100644 index 000000000000..2c2aa9368f76 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -0,0 +1,161 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7358"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <375000000>; + + cpu@0 { + compatible = "brcm,bmips3300"; + device_type = "cpu"; + reg = <0>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@411400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x411400 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <48>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x2f3>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "bsp_0", + "rdc_0", "raaga_0", + "avd_0", "jtag_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406600 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406600 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <56>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406800 { + compatible = "ns16550a"; + reg = <0x406800 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@430000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v2"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x430000 0x4c8c>; + interrupts = <24>, <25>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v2"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7358-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7358-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi new file mode 100644 index 000000000000..f23b0aed276f --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -0,0 +1,161 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7360"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <375000000>; + + cpu@0 { + compatible = "brcm,bmips3300"; + device_type = "cpu"; + reg = <0>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@411400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x411400 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <48>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x2f3>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "bsp_0", + "rdc_0", "raaga_0", + "avd_0", "jtag_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406600 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406600 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <56>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406800 { + compatible = "ns16550a"; + reg = <0x406800 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@430000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v2"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x430000 0x4c8c>; + interrupts = <24>, <25>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v2"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7360-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7360-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi new file mode 100644 index 000000000000..da99db665bbc --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -0,0 +1,167 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7362"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <375000000>; + + cpu@0 { + compatible = "brcm,bmips4380"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips4380"; + device_type = "cpu"; + reg = <1>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@411400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x411400 0x30>, <0x411600 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <48>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x2f3>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "bsp_0", + "rdc_0", "raaga_0", + "avd_0", "jtag_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406600 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406600 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <56>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406800 { + compatible = "ns16550a"; + reg = <0x406800 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@430000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v2"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x430000 0x4c8c>; + interrupts = <24>, <25>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v2"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7362-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7362-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7420.dtsi b/arch/mips/boot/dts/brcm/bcm7420.dtsi new file mode 100644 index 000000000000..5f55d0a50a28 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7420.dtsi @@ -0,0 +1,184 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7420"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <93750000>; + + cpu@0 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <1>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@441400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x441400 0x30>, <0x441600 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@401800 { + compatible = "brcm,l2-intc"; + reg = <0x401800 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <23>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x3ff>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "pci_0", + "pcie_0", "bsp_0", "rdc_0", + "rptd_0", "avd_0", "avd_1", + "jtag_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406780 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406780 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <18>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; + reg = <0x404000 0x60c>; + little-endian; + }; + + reboot { + compatible = "brcm,bcm7038-reboot"; + syscon = <&sun_top_ctrl 0x8 0x14>; + }; + + uart0: serial@406b00 { + compatible = "ns16550a"; + reg = <0x406b00 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <21>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@468000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v1"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x468000 0x3c8c>; + interrupts = <69>, <79>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v1"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,65nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@488300 { + compatible = "brcm,bcm7420-ehci", "generic-ehci"; + reg = <0x488300 0x100>; + interrupt-parent = <&periph_intc>; + interrupts = <60>; + status = "disabled"; + }; + + ohci0: usb@488400 { + compatible = "brcm,bcm7420-ohci", "generic-ohci"; + reg = <0x488400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + status = "disabled"; + }; + + ehci1: usb@488500 { + compatible = "brcm,bcm7420-ehci", "generic-ehci"; + reg = <0x488500 0x100>; + interrupt-parent = <&periph_intc>; + interrupts = <55>; + status = "disabled"; + }; + + ohci1: usb@488600 { + compatible = "brcm,bcm7420-ohci", "generic-ohci"; + reg = <0x488600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <62>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi new file mode 100644 index 000000000000..5b660b617ead --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -0,0 +1,225 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "brcm,bcm7425"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + mips-hpt-frequency = <163125000>; + + cpu@0 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <0>; + }; + + cpu@1 { + compatible = "brcm,bmips5000"; + device_type = "cpu"; + reg = <1>; + }; + }; + + aliases { + uart0 = &uart0; + }; + + cpu_intc: cpu_intc { + #address-cells = <0>; + compatible = "mti,cpu-interrupt-controller"; + + interrupt-controller; + #interrupt-cells = <1>; + }; + + clocks { + uart_clk: uart_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <81000000>; + }; + }; + + rdb { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "simple-bus"; + ranges = <0 0x10000000 0x01000000>; + + periph_intc: periph_intc@41a400 { + compatible = "brcm,bcm7038-l1-intc"; + reg = <0x41a400 0x30>, <0x41a600 0x30>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>, <3>; + }; + + sun_l2_intc: sun_l2_intc@403000 { + compatible = "brcm,l2-intc"; + reg = <0x403000 0x30>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&periph_intc>; + interrupts = <47>; + }; + + gisb-arb@400000 { + compatible = "brcm,bcm7400-gisb-arb"; + reg = <0x400000 0xdc>; + native-endian; + interrupt-parent = <&sun_l2_intc>; + interrupts = <0>, <2>; + brcm,gisb-arb-master-mask = <0x177b>; + brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "pcie_0", + "bsp_0", "rdc_0", + "raaga_0", "avd_1", + "jtag_0", "svd_0", + "vice_0"; + }; + + upg_irq0_intc: upg_irq0_intc@406780 { + compatible = "brcm,bcm7120-l2-intc"; + reg = <0x406780 0x8>; + + brcm,int-map-mask = <0x44>; + brcm,int-fwd-mask = <0x70000>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&periph_intc>; + interrupts = <55>; + }; + + sun_top_ctrl: syscon@404000 { + compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; + reg = <0x404000 0x51c>; + little-endian; + }; + + reboot { + compatible = "brcm,brcmstb-reboot"; + syscon = <&sun_top_ctrl 0x304 0x308>; + }; + + uart0: serial@406b00 { + compatible = "ns16550a"; + reg = <0x406b00 0x20>; + reg-io-width = <0x4>; + reg-shift = <0x2>; + interrupt-parent = <&periph_intc>; + interrupts = <61>; + clocks = <&uart_clk>; + status = "disabled"; + }; + + enet0: ethernet@b80000 { + phy-mode = "internal"; + phy-handle = <&phy1>; + mac-address = [ 00 10 18 36 23 1a ]; + compatible = "brcm,genet-v3"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0xb80000 0x11c88>; + interrupts = <17>, <18>; + interrupt-parent = <&periph_intc>; + status = "disabled"; + + mdio@e14 { + compatible = "brcm,genet-mdio-v3"; + #address-cells = <0x1>; + #size-cells = <0x0>; + reg = <0xe14 0x8>; + + phy1: ethernet-phy@1 { + max-speed = <100>; + reg = <0x1>; + compatible = "brcm,40nm-ephy", + "ethernet-phy-ieee802.3-c22"; + }; + }; + }; + + ehci0: usb@480300 { + compatible = "brcm,bcm7425-ehci", "generic-ehci"; + reg = <0x480300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <65>; + status = "disabled"; + }; + + ohci0: usb@480400 { + compatible = "brcm,bcm7425-ohci", "generic-ohci"; + reg = <0x480400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <67>; + status = "disabled"; + }; + + ehci1: usb@480500 { + compatible = "brcm,bcm7425-ehci", "generic-ehci"; + reg = <0x480500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <66>; + status = "disabled"; + }; + + ohci1: usb@480600 { + compatible = "brcm,bcm7425-ohci", "generic-ohci"; + reg = <0x480600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <68>; + status = "disabled"; + }; + + ehci2: usb@490300 { + compatible = "brcm,bcm7425-ehci", "generic-ehci"; + reg = <0x490300 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <70>; + status = "disabled"; + }; + + ohci2: usb@490400 { + compatible = "brcm,bcm7425-ohci", "generic-ohci"; + reg = <0x490400 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <72>; + status = "disabled"; + }; + + ehci3: usb@490500 { + compatible = "brcm,bcm7425-ehci", "generic-ehci"; + reg = <0x490500 0x100>; + native-endian; + interrupt-parent = <&periph_intc>; + interrupts = <71>; + status = "disabled"; + }; + + ohci3: usb@490600 { + compatible = "brcm,bcm7425-ohci", "generic-ohci"; + reg = <0x490600 0x100>; + native-endian; + no-big-frame-no; + interrupt-parent = <&periph_intc>; + interrupts = <73>; + status = "disabled"; + }; + }; +}; diff --git a/arch/mips/boot/dts/bcm93384wvg.dts b/arch/mips/boot/dts/brcm/bcm93384wvg.dts index 831741179212..d1e44a17d41a 100644 --- a/arch/mips/boot/dts/bcm93384wvg.dts +++ b/arch/mips/boot/dts/brcm/bcm93384wvg.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ "bcm3384.dtsi" +/include/ "bcm3384_zephyr.dtsi" / { compatible = "brcm,bcm93384wvg", "brcm,bcm3384"; @@ -10,13 +10,6 @@ bootargs = "console=ttyS0,115200"; stdout-path = &uart0; }; - - memory@0 { - device_type = "memory"; - reg = <0x0 0x04000000>; - dma-xor-mask = <0x08000000>; - dma-xor-limit = <0x0fffffff>; - }; }; &uart0 { diff --git a/arch/mips/boot/dts/brcm/bcm93384wvg_viper.dts b/arch/mips/boot/dts/brcm/bcm93384wvg_viper.dts new file mode 100644 index 000000000000..1ecb2696aca8 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm93384wvg_viper.dts @@ -0,0 +1,25 @@ +/dts-v1/; + +/include/ "bcm3384_viper.dtsi" + +/ { + compatible = "brcm,bcm93384wvg-viper", "brcm,bcm3384-viper"; + model = "Broadcom BCM93384WVG-viper"; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm96368mvwg.dts b/arch/mips/boot/dts/brcm/bcm96368mvwg.dts new file mode 100644 index 000000000000..0e890c28fe5c --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm96368mvwg.dts @@ -0,0 +1,31 @@ +/dts-v1/; + +/include/ "bcm6368.dtsi" + +/ { + compatible = "brcm,bcm96368mvwg", "brcm,bcm6368"; + model = "Broadcom BCM96368MVWG"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x04000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +/* FIXME: need to set up USB_CTRL registers first */ +&ehci0 { + status = "disabled"; +}; + +&ohci0 { + status = "disabled"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97125cbmb.dts b/arch/mips/boot/dts/brcm/bcm97125cbmb.dts new file mode 100644 index 000000000000..e046b1109eab --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97125cbmb.dts @@ -0,0 +1,31 @@ +/dts-v1/; + +/include/ "bcm7125.dtsi" + +/ { + compatible = "brcm,bcm97125cbmb", "brcm,bcm7125"; + model = "Broadcom BCM97125CBMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +/* FIXME: USB is wonky; disable it for now */ +&ehci0 { + status = "disabled"; +}; + +&ohci0 { + status = "disabled"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts new file mode 100644 index 000000000000..70f196d89d26 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts @@ -0,0 +1,58 @@ +/dts-v1/; + +/include/ "bcm7346.dtsi" + +/ { + compatible = "brcm,bcm97346dbsmb", "brcm,bcm7346"; + model = "Broadcom BCM97346DBSMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, <0x20000000 0x30000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97358svmb.dts b/arch/mips/boot/dts/brcm/bcm97358svmb.dts new file mode 100644 index 000000000000..d18e6d947739 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97358svmb.dts @@ -0,0 +1,34 @@ +/dts-v1/; + +/include/ "bcm7358.dtsi" + +/ { + compatible = "brcm,bcm97358svmb", "brcm,bcm7358"; + model = "Broadcom BCM97358SVMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/arch/mips/boot/dts/brcm/bcm97360svmb.dts new file mode 100644 index 000000000000..4fe515500102 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97360svmb.dts @@ -0,0 +1,34 @@ +/dts-v1/; + +/include/ "bcm7360.dtsi" + +/ { + compatible = "brcm,bcm97360svmb", "brcm,bcm7360"; + model = "Broadcom BCM97360SVMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97362svmb.dts b/arch/mips/boot/dts/brcm/bcm97362svmb.dts new file mode 100644 index 000000000000..b7b88e5dc9e7 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97362svmb.dts @@ -0,0 +1,34 @@ +/dts-v1/; + +/include/ "bcm7362.dtsi" + +/ { + compatible = "brcm,bcm97362svmb", "brcm,bcm7362"; + model = "Broadcom BCM97362SVMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, <0x20000000 0x30000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97420c.dts b/arch/mips/boot/dts/brcm/bcm97420c.dts new file mode 100644 index 000000000000..67fe1f3a3891 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97420c.dts @@ -0,0 +1,45 @@ +/dts-v1/; + +/include/ "bcm7420.dtsi" + +/ { + compatible = "brcm,bcm97420c", "brcm,bcm7420"; + model = "Broadcom BCM97420C"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, + <0x20000000 0x30000000>, + <0x60000000 0x10000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +/* FIXME: MAC driver comes up but cannot attach to PHY */ +&enet0 { + status = "disabled"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm97425svmb.dts b/arch/mips/boot/dts/brcm/bcm97425svmb.dts new file mode 100644 index 000000000000..689c68a4f9c8 --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm97425svmb.dts @@ -0,0 +1,60 @@ +/dts-v1/; + +/include/ "bcm7425.dtsi" + +/ { + compatible = "brcm,bcm97425svmb", "brcm,bcm7425"; + model = "Broadcom BCM97425SVMB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, + <0x20000000 0x30000000>, + <0x90000000 0x40000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; + +&enet0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/brcm/bcm9ejtagprb.dts b/arch/mips/boot/dts/brcm/bcm9ejtagprb.dts new file mode 100644 index 000000000000..1da4608680aa --- /dev/null +++ b/arch/mips/boot/dts/brcm/bcm9ejtagprb.dts @@ -0,0 +1,22 @@ +/dts-v1/; + +/include/ "bcm6328.dtsi" + +/ { + compatible = "brcm,bcm9ejtagprb", "brcm,bcm6328"; + model = "Broadcom BCM9EJTAGPRB"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/mips/boot/dts/cavium-octeon/Makefile b/arch/mips/boot/dts/cavium-octeon/Makefile new file mode 100644 index 000000000000..5b99c40a058f --- /dev/null +++ b/arch/mips/boot/dts/cavium-octeon/Makefile @@ -0,0 +1,9 @@ +dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/octeon_3xxx.dts b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts index fa33115bde33..9c48e0586ba7 100644 --- a/arch/mips/boot/dts/octeon_3xxx.dts +++ b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts @@ -587,4 +587,16 @@ usbn = &usbn; led0 = &led0; }; + + dsr1000n-leds { + compatible = "gpio-leds"; + usb1 { + label = "usb1"; + gpios = <&gpio 9 1>; /* Active low */ + }; + usb2 { + label = "usb2"; + gpios = <&gpio 10 1>; /* Active low */ + }; + }; }; diff --git a/arch/mips/boot/dts/octeon_68xx.dts b/arch/mips/boot/dts/cavium-octeon/octeon_68xx.dts index 79b46fcb0a11..79b46fcb0a11 100644 --- a/arch/mips/boot/dts/octeon_68xx.dts +++ b/arch/mips/boot/dts/cavium-octeon/octeon_68xx.dts diff --git a/arch/mips/boot/dts/lantiq/Makefile b/arch/mips/boot/dts/lantiq/Makefile new file mode 100644 index 000000000000..0906c62141b9 --- /dev/null +++ b/arch/mips/boot/dts/lantiq/Makefile @@ -0,0 +1,9 @@ +dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi index d4c59e003708..d4c59e003708 100644 --- a/arch/mips/boot/dts/danube.dtsi +++ b/arch/mips/boot/dts/lantiq/danube.dtsi diff --git a/arch/mips/boot/dts/easy50712.dts b/arch/mips/boot/dts/lantiq/easy50712.dts index 143b8a37b5e4..143b8a37b5e4 100644 --- a/arch/mips/boot/dts/easy50712.dts +++ b/arch/mips/boot/dts/lantiq/easy50712.dts diff --git a/arch/mips/boot/dts/mti/Makefile b/arch/mips/boot/dts/mti/Makefile new file mode 100644 index 000000000000..ef1f3dbed033 --- /dev/null +++ b/arch/mips/boot/dts/mti/Makefile @@ -0,0 +1,9 @@ +dtb-$(CONFIG_MIPS_SEAD3) += sead3.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/sead3.dts b/arch/mips/boot/dts/mti/sead3.dts index e4b317d414f1..e4b317d414f1 100644 --- a/arch/mips/boot/dts/sead3.dts +++ b/arch/mips/boot/dts/mti/sead3.dts diff --git a/arch/mips/boot/dts/netlogic/Makefile b/arch/mips/boot/dts/netlogic/Makefile new file mode 100644 index 000000000000..9868057140b5 --- /dev/null +++ b/arch/mips/boot/dts/netlogic/Makefile @@ -0,0 +1,13 @@ +dtb-$(CONFIG_DT_XLP_EVP) += xlp_evp.dtb +dtb-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb +dtb-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb +dtb-$(CONFIG_DT_XLP_GVP) += xlp_gvp.dtb +dtb-$(CONFIG_DT_XLP_RVP) += xlp_rvp.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/xlp_evp.dts b/arch/mips/boot/dts/netlogic/xlp_evp.dts index 89ad04808c02..89ad04808c02 100644 --- a/arch/mips/boot/dts/xlp_evp.dts +++ b/arch/mips/boot/dts/netlogic/xlp_evp.dts diff --git a/arch/mips/boot/dts/xlp_fvp.dts b/arch/mips/boot/dts/netlogic/xlp_fvp.dts index 63e62b7bd758..63e62b7bd758 100644 --- a/arch/mips/boot/dts/xlp_fvp.dts +++ b/arch/mips/boot/dts/netlogic/xlp_fvp.dts diff --git a/arch/mips/boot/dts/xlp_gvp.dts b/arch/mips/boot/dts/netlogic/xlp_gvp.dts index bb4ecd1d47fc..bb4ecd1d47fc 100644 --- a/arch/mips/boot/dts/xlp_gvp.dts +++ b/arch/mips/boot/dts/netlogic/xlp_gvp.dts diff --git a/arch/mips/boot/dts/netlogic/xlp_rvp.dts b/arch/mips/boot/dts/netlogic/xlp_rvp.dts new file mode 100644 index 000000000000..7188aed2ea2e --- /dev/null +++ b/arch/mips/boot/dts/netlogic/xlp_rvp.dts @@ -0,0 +1,77 @@ +/* + * XLP5XX Device Tree Source for RVP boards + */ + +/dts-v1/; +/ { + model = "netlogic,XLP-RVP"; + compatible = "netlogic,xlp"; + #address-cells = <2>; + #size-cells = <2>; + + soc { + #address-cells = <2>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG + 1 0 0 0x16000000 0x02000000>; // GBU chipselects + + serial0: serial@30000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x112100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <125000000>; + interrupt-parent = <&pic>; + interrupts = <17>; + }; + pic: pic@110000 { + compatible = "netlogic,xlp-pic"; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0 0x110000 0x200>; + interrupt-controller; + }; + + nor_flash@1,0 { + compatible = "cfi-flash"; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <2>; + reg = <1 0 0x1000000>; + + partition@0 { + label = "x-loader"; + reg = <0x0 0x100000>; /* 1M */ + read-only; + }; + + partition@100000 { + label = "u-boot"; + reg = <0x100000 0x100000>; /* 1M */ + }; + + partition@200000 { + label = "kernel"; + reg = <0x200000 0x500000>; /* 5M */ + }; + + partition@700000 { + label = "rootfs"; + reg = <0x700000 0x800000>; /* 8M */ + }; + + partition@f00000 { + label = "env"; + reg = <0xf00000 0x100000>; /* 1M */ + read-only; + }; + }; + + }; + + chosen { + bootargs = "console=ttyS0,115200 rdinit=/sbin/init"; + }; +}; diff --git a/arch/mips/boot/dts/xlp_svp.dts b/arch/mips/boot/dts/netlogic/xlp_svp.dts index 1ebd00edaacc..1ebd00edaacc 100644 --- a/arch/mips/boot/dts/xlp_svp.dts +++ b/arch/mips/boot/dts/netlogic/xlp_svp.dts diff --git a/arch/mips/boot/dts/ralink/Makefile b/arch/mips/boot/dts/ralink/Makefile new file mode 100644 index 000000000000..2a7225954bf6 --- /dev/null +++ b/arch/mips/boot/dts/ralink/Makefile @@ -0,0 +1,12 @@ +dtb-$(CONFIG_DTB_RT2880_EVAL) += rt2880_eval.dtb +dtb-$(CONFIG_DTB_RT305X_EVAL) += rt3052_eval.dtb +dtb-$(CONFIG_DTB_RT3883_EVAL) += rt3883_eval.dtb +dtb-$(CONFIG_DTB_MT7620A_EVAL) += mt7620a_eval.dtb + +obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) + +# Force kbuild to make empty built-in.o if necessary +obj- += dummy.o + +always := $(dtb-y) +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/boot/dts/mt7620a.dtsi b/arch/mips/boot/dts/ralink/mt7620a.dtsi index 08bf24fefe9f..08bf24fefe9f 100644 --- a/arch/mips/boot/dts/mt7620a.dtsi +++ b/arch/mips/boot/dts/ralink/mt7620a.dtsi diff --git a/arch/mips/boot/dts/mt7620a_eval.dts b/arch/mips/boot/dts/ralink/mt7620a_eval.dts index 709f58132f5c..709f58132f5c 100644 --- a/arch/mips/boot/dts/mt7620a_eval.dts +++ b/arch/mips/boot/dts/ralink/mt7620a_eval.dts diff --git a/arch/mips/boot/dts/rt2880.dtsi b/arch/mips/boot/dts/ralink/rt2880.dtsi index 182afde2f2e1..182afde2f2e1 100644 --- a/arch/mips/boot/dts/rt2880.dtsi +++ b/arch/mips/boot/dts/ralink/rt2880.dtsi diff --git a/arch/mips/boot/dts/rt2880_eval.dts b/arch/mips/boot/dts/ralink/rt2880_eval.dts index 0a685db093d4..0a685db093d4 100644 --- a/arch/mips/boot/dts/rt2880_eval.dts +++ b/arch/mips/boot/dts/ralink/rt2880_eval.dts diff --git a/arch/mips/boot/dts/rt3050.dtsi b/arch/mips/boot/dts/ralink/rt3050.dtsi index e3203d414fee..e3203d414fee 100644 --- a/arch/mips/boot/dts/rt3050.dtsi +++ b/arch/mips/boot/dts/ralink/rt3050.dtsi diff --git a/arch/mips/boot/dts/rt3052_eval.dts b/arch/mips/boot/dts/ralink/rt3052_eval.dts index ec9e9a035541..ec9e9a035541 100644 --- a/arch/mips/boot/dts/rt3052_eval.dts +++ b/arch/mips/boot/dts/ralink/rt3052_eval.dts diff --git a/arch/mips/boot/dts/rt3883.dtsi b/arch/mips/boot/dts/ralink/rt3883.dtsi index 3b131dd0d5ac..3b131dd0d5ac 100644 --- a/arch/mips/boot/dts/rt3883.dtsi +++ b/arch/mips/boot/dts/ralink/rt3883.dtsi diff --git a/arch/mips/boot/dts/rt3883_eval.dts b/arch/mips/boot/dts/ralink/rt3883_eval.dts index e8df21a5d10d..e8df21a5d10d 100644 --- a/arch/mips/boot/dts/rt3883_eval.dts +++ b/arch/mips/boot/dts/ralink/rt3883_eval.dts diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile index a74f76d85a2f..f7aa9d5d3b87 100644 --- a/arch/mips/cavium-octeon/crypto/Makefile +++ b/arch/mips/cavium-octeon/crypto/Makefile @@ -4,4 +4,7 @@ obj-y += octeon-crypto.o -obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o +obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o +obj-$(CONFIG_CRYPTO_SHA1_OCTEON) += octeon-sha1.o +obj-$(CONFIG_CRYPTO_SHA256_OCTEON) += octeon-sha256.o +obj-$(CONFIG_CRYPTO_SHA512_OCTEON) += octeon-sha512.o diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.c b/arch/mips/cavium-octeon/crypto/octeon-crypto.c index 7c82ff463b65..f66bd1adc7ff 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.c +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.c @@ -17,7 +17,7 @@ * crypto operations in calls to octeon_crypto_enable/disable in order to make * sure the state of COP2 isn't corrupted if userspace is also performing * hardware crypto operations. Allocate the state parameter on the stack. - * Preemption must be disabled to prevent context switches. + * Returns with preemption disabled. * * @state: Pointer to state structure to store current COP2 state in. * @@ -28,6 +28,7 @@ unsigned long octeon_crypto_enable(struct octeon_cop2_state *state) int status; unsigned long flags; + preempt_disable(); local_irq_save(flags); status = read_c0_status(); write_c0_status(status | ST0_CU2); @@ -62,5 +63,6 @@ void octeon_crypto_disable(struct octeon_cop2_state *state, else write_c0_status(read_c0_status() & ~ST0_CU2); local_irq_restore(flags); + preempt_enable(); } EXPORT_SYMBOL_GPL(octeon_crypto_disable); diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h index e2a4aece9c24..7315cc307397 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.h +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -5,7 +5,8 @@ * * Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. * - * MD5 instruction definitions added by Aaro Koskinen <aaro.koskinen@iki.fi>. + * MD5/SHA1/SHA256/SHA512 instruction definitions added by + * Aaro Koskinen <aaro.koskinen@iki.fi>. * */ #ifndef __LINUX_OCTEON_CRYPTO_H @@ -21,22 +22,22 @@ extern void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long flags); /* - * Macros needed to implement MD5: + * Macros needed to implement MD5/SHA1/SHA256: */ /* - * The index can be 0-1. + * The index can be 0-1 (MD5) or 0-2 (SHA1), 0-3 (SHA256). */ #define write_octeon_64bit_hash_dword(value, index) \ do { \ __asm__ __volatile__ ( \ "dmtc2 %[rt],0x0048+" STR(index) \ : \ - : [rt] "d" (value)); \ + : [rt] "d" (cpu_to_be64(value))); \ } while (0) /* - * The index can be 0-1. + * The index can be 0-1 (MD5) or 0-2 (SHA1), 0-3 (SHA256). */ #define read_octeon_64bit_hash_dword(index) \ ({ \ @@ -47,7 +48,7 @@ do { \ : [rt] "=d" (__value) \ : ); \ \ - __value; \ + be64_to_cpu(__value); \ }) /* @@ -58,7 +59,7 @@ do { \ __asm__ __volatile__ ( \ "dmtc2 %[rt],0x0040+" STR(index) \ : \ - : [rt] "d" (value)); \ + : [rt] "d" (cpu_to_be64(value))); \ } while (0) /* @@ -69,6 +70,154 @@ do { \ __asm__ __volatile__ ( \ "dmtc2 %[rt],0x4047" \ : \ + : [rt] "d" (cpu_to_be64(value))); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_sha1_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x4057" \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_sha256_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x404f" \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * Macros needed to implement SHA512: + */ + +/* + * The index can be 0-7. + */ +#define write_octeon_64bit_hash_sha512(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0250+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The index can be 0-7. + */ +#define read_octeon_64bit_hash_sha512(index) \ +({ \ + u64 __value; \ + \ + __asm__ __volatile__ ( \ + "dmfc2 %[rt],0x0250+" STR(index) \ + : [rt] "=d" (__value) \ + : ); \ + \ + __value; \ +}) + +/* + * The index can be 0-14. + */ +#define write_octeon_64bit_block_sha512(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0240+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block word (64-bit). + */ +#define octeon_sha512_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x424f" \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_sha1_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x4057" \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_sha256_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x404f" \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * Macros needed to implement SHA512: + */ + +/* + * The index can be 0-7. + */ +#define write_octeon_64bit_hash_sha512(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0250+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The index can be 0-7. + */ +#define read_octeon_64bit_hash_sha512(index) \ +({ \ + u64 __value; \ + \ + __asm__ __volatile__ ( \ + "dmfc2 %[rt],0x0250+" STR(index) \ + : [rt] "=d" (__value) \ + : ); \ + \ + __value; \ +}) + +/* + * The index can be 0-14. + */ +#define write_octeon_64bit_block_sha512(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0240+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block word (64-bit). + */ +#define octeon_sha512_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x424f" \ + : \ : [rt] "d" (value)); \ } while (0) diff --git a/arch/mips/cavium-octeon/crypto/octeon-md5.c b/arch/mips/cavium-octeon/crypto/octeon-md5.c index b909881ba6c1..12dccdb38286 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-md5.c +++ b/arch/mips/cavium-octeon/crypto/octeon-md5.c @@ -97,8 +97,6 @@ static int octeon_md5_update(struct shash_desc *desc, const u8 *data, memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, avail); - local_bh_disable(); - preempt_disable(); flags = octeon_crypto_enable(&state); octeon_md5_store_hash(mctx); @@ -114,8 +112,6 @@ static int octeon_md5_update(struct shash_desc *desc, const u8 *data, octeon_md5_read_hash(mctx); octeon_crypto_disable(&state, flags); - preempt_enable(); - local_bh_enable(); memcpy(mctx->block, data, len); @@ -133,8 +129,6 @@ static int octeon_md5_final(struct shash_desc *desc, u8 *out) *p++ = 0x80; - local_bh_disable(); - preempt_disable(); flags = octeon_crypto_enable(&state); octeon_md5_store_hash(mctx); @@ -152,8 +146,6 @@ static int octeon_md5_final(struct shash_desc *desc, u8 *out) octeon_md5_read_hash(mctx); octeon_crypto_disable(&state, flags); - preempt_enable(); - local_bh_enable(); memcpy(out, mctx->hash, sizeof(mctx->hash)); memset(mctx, 0, sizeof(*mctx)); diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha1.c b/arch/mips/cavium-octeon/crypto/octeon-sha1.c new file mode 100644 index 000000000000..2b74b5b67cae --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-sha1.c @@ -0,0 +1,241 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>. + * + * Based on crypto/sha1_generic.c, which is: + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include <linux/mm.h> +#include <crypto/sha.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <asm/byteorder.h> +#include <asm/octeon/octeon.h> +#include <crypto/internal/hash.h> + +#include "octeon-crypto.h" + +/* + * We pass everything as 64-bit. OCTEON can handle misaligned data. + */ + +static void octeon_sha1_store_hash(struct sha1_state *sctx) +{ + u64 *hash = (u64 *)sctx->state; + union { + u32 word[2]; + u64 dword; + } hash_tail = { { sctx->state[4], } }; + + write_octeon_64bit_hash_dword(hash[0], 0); + write_octeon_64bit_hash_dword(hash[1], 1); + write_octeon_64bit_hash_dword(hash_tail.dword, 2); + memzero_explicit(&hash_tail.word[0], sizeof(hash_tail.word[0])); +} + +static void octeon_sha1_read_hash(struct sha1_state *sctx) +{ + u64 *hash = (u64 *)sctx->state; + union { + u32 word[2]; + u64 dword; + } hash_tail; + + hash[0] = read_octeon_64bit_hash_dword(0); + hash[1] = read_octeon_64bit_hash_dword(1); + hash_tail.dword = read_octeon_64bit_hash_dword(2); + sctx->state[4] = hash_tail.word[0]; + memzero_explicit(&hash_tail.dword, sizeof(hash_tail.dword)); +} + +static void octeon_sha1_transform(const void *_block) +{ + const u64 *block = _block; + + write_octeon_64bit_block_dword(block[0], 0); + write_octeon_64bit_block_dword(block[1], 1); + write_octeon_64bit_block_dword(block[2], 2); + write_octeon_64bit_block_dword(block[3], 3); + write_octeon_64bit_block_dword(block[4], 4); + write_octeon_64bit_block_dword(block[5], 5); + write_octeon_64bit_block_dword(block[6], 6); + octeon_sha1_start(block[7]); +} + +static int octeon_sha1_init(struct shash_desc *desc) +{ + struct sha1_state *sctx = shash_desc_ctx(desc); + + sctx->state[0] = SHA1_H0; + sctx->state[1] = SHA1_H1; + sctx->state[2] = SHA1_H2; + sctx->state[3] = SHA1_H3; + sctx->state[4] = SHA1_H4; + sctx->count = 0; + + return 0; +} + +static void __octeon_sha1_update(struct sha1_state *sctx, const u8 *data, + unsigned int len) +{ + unsigned int partial; + unsigned int done; + const u8 *src; + + partial = sctx->count % SHA1_BLOCK_SIZE; + sctx->count += len; + done = 0; + src = data; + + if ((partial + len) >= SHA1_BLOCK_SIZE) { + if (partial) { + done = -partial; + memcpy(sctx->buffer + partial, data, + done + SHA1_BLOCK_SIZE); + src = sctx->buffer; + } + + do { + octeon_sha1_transform(src); + done += SHA1_BLOCK_SIZE; + src = data + done; + } while (done + SHA1_BLOCK_SIZE <= len); + + partial = 0; + } + memcpy(sctx->buffer + partial, src, len - done); +} + +static int octeon_sha1_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct sha1_state *sctx = shash_desc_ctx(desc); + struct octeon_cop2_state state; + unsigned long flags; + + /* + * Small updates never reach the crypto engine, so the generic sha1 is + * faster because of the heavyweight octeon_crypto_enable() / + * octeon_crypto_disable(). + */ + if ((sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE) + return crypto_sha1_update(desc, data, len); + + flags = octeon_crypto_enable(&state); + octeon_sha1_store_hash(sctx); + + __octeon_sha1_update(sctx, data, len); + + octeon_sha1_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + return 0; +} + +static int octeon_sha1_final(struct shash_desc *desc, u8 *out) +{ + struct sha1_state *sctx = shash_desc_ctx(desc); + static const u8 padding[64] = { 0x80, }; + struct octeon_cop2_state state; + __be32 *dst = (__be32 *)out; + unsigned int pad_len; + unsigned long flags; + unsigned int index; + __be64 bits; + int i; + + /* Save number of bits. */ + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64. */ + index = sctx->count & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64+56) - index); + + flags = octeon_crypto_enable(&state); + octeon_sha1_store_hash(sctx); + + __octeon_sha1_update(sctx, padding, pad_len); + + /* Append length (before padding). */ + __octeon_sha1_update(sctx, (const u8 *)&bits, sizeof(bits)); + + octeon_sha1_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + /* Store state in digest */ + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(sctx->state[i]); + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(*sctx)); + + return 0; +} + +static int octeon_sha1_export(struct shash_desc *desc, void *out) +{ + struct sha1_state *sctx = shash_desc_ctx(desc); + + memcpy(out, sctx, sizeof(*sctx)); + return 0; +} + +static int octeon_sha1_import(struct shash_desc *desc, const void *in) +{ + struct sha1_state *sctx = shash_desc_ctx(desc); + + memcpy(sctx, in, sizeof(*sctx)); + return 0; +} + +static struct shash_alg octeon_sha1_alg = { + .digestsize = SHA1_DIGEST_SIZE, + .init = octeon_sha1_init, + .update = octeon_sha1_update, + .final = octeon_sha1_final, + .export = octeon_sha1_export, + .import = octeon_sha1_import, + .descsize = sizeof(struct sha1_state), + .statesize = sizeof(struct sha1_state), + .base = { + .cra_name = "sha1", + .cra_driver_name= "octeon-sha1", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + +static int __init octeon_sha1_mod_init(void) +{ + if (!octeon_has_crypto()) + return -ENOTSUPP; + return crypto_register_shash(&octeon_sha1_alg); +} + +static void __exit octeon_sha1_mod_fini(void) +{ + crypto_unregister_shash(&octeon_sha1_alg); +} + +module_init(octeon_sha1_mod_init); +module_exit(octeon_sha1_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (OCTEON)"); +MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha256.c b/arch/mips/cavium-octeon/crypto/octeon-sha256.c new file mode 100644 index 000000000000..97e96fead08a --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-sha256.c @@ -0,0 +1,280 @@ +/* + * Cryptographic API. + * + * SHA-224 and SHA-256 Secure Hash Algorithm. + * + * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>. + * + * Based on crypto/sha256_generic.c, which is: + * + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.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. + */ + +#include <linux/mm.h> +#include <crypto/sha.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <asm/byteorder.h> +#include <asm/octeon/octeon.h> +#include <crypto/internal/hash.h> + +#include "octeon-crypto.h" + +/* + * We pass everything as 64-bit. OCTEON can handle misaligned data. + */ + +static void octeon_sha256_store_hash(struct sha256_state *sctx) +{ + u64 *hash = (u64 *)sctx->state; + + write_octeon_64bit_hash_dword(hash[0], 0); + write_octeon_64bit_hash_dword(hash[1], 1); + write_octeon_64bit_hash_dword(hash[2], 2); + write_octeon_64bit_hash_dword(hash[3], 3); +} + +static void octeon_sha256_read_hash(struct sha256_state *sctx) +{ + u64 *hash = (u64 *)sctx->state; + + hash[0] = read_octeon_64bit_hash_dword(0); + hash[1] = read_octeon_64bit_hash_dword(1); + hash[2] = read_octeon_64bit_hash_dword(2); + hash[3] = read_octeon_64bit_hash_dword(3); +} + +static void octeon_sha256_transform(const void *_block) +{ + const u64 *block = _block; + + write_octeon_64bit_block_dword(block[0], 0); + write_octeon_64bit_block_dword(block[1], 1); + write_octeon_64bit_block_dword(block[2], 2); + write_octeon_64bit_block_dword(block[3], 3); + write_octeon_64bit_block_dword(block[4], 4); + write_octeon_64bit_block_dword(block[5], 5); + write_octeon_64bit_block_dword(block[6], 6); + octeon_sha256_start(block[7]); +} + +static int octeon_sha224_init(struct shash_desc *desc) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + + sctx->state[0] = SHA224_H0; + sctx->state[1] = SHA224_H1; + sctx->state[2] = SHA224_H2; + sctx->state[3] = SHA224_H3; + sctx->state[4] = SHA224_H4; + sctx->state[5] = SHA224_H5; + sctx->state[6] = SHA224_H6; + sctx->state[7] = SHA224_H7; + sctx->count = 0; + + return 0; +} + +static int octeon_sha256_init(struct shash_desc *desc) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + + sctx->state[0] = SHA256_H0; + sctx->state[1] = SHA256_H1; + sctx->state[2] = SHA256_H2; + sctx->state[3] = SHA256_H3; + sctx->state[4] = SHA256_H4; + sctx->state[5] = SHA256_H5; + sctx->state[6] = SHA256_H6; + sctx->state[7] = SHA256_H7; + sctx->count = 0; + + return 0; +} + +static void __octeon_sha256_update(struct sha256_state *sctx, const u8 *data, + unsigned int len) +{ + unsigned int partial; + unsigned int done; + const u8 *src; + + partial = sctx->count % SHA256_BLOCK_SIZE; + sctx->count += len; + done = 0; + src = data; + + if ((partial + len) >= SHA256_BLOCK_SIZE) { + if (partial) { + done = -partial; + memcpy(sctx->buf + partial, data, + done + SHA256_BLOCK_SIZE); + src = sctx->buf; + } + + do { + octeon_sha256_transform(src); + done += SHA256_BLOCK_SIZE; + src = data + done; + } while (done + SHA256_BLOCK_SIZE <= len); + + partial = 0; + } + memcpy(sctx->buf + partial, src, len - done); +} + +static int octeon_sha256_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + struct octeon_cop2_state state; + unsigned long flags; + + /* + * Small updates never reach the crypto engine, so the generic sha256 is + * faster because of the heavyweight octeon_crypto_enable() / + * octeon_crypto_disable(). + */ + if ((sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE) + return crypto_sha256_update(desc, data, len); + + flags = octeon_crypto_enable(&state); + octeon_sha256_store_hash(sctx); + + __octeon_sha256_update(sctx, data, len); + + octeon_sha256_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + return 0; +} + +static int octeon_sha256_final(struct shash_desc *desc, u8 *out) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + static const u8 padding[64] = { 0x80, }; + struct octeon_cop2_state state; + __be32 *dst = (__be32 *)out; + unsigned int pad_len; + unsigned long flags; + unsigned int index; + __be64 bits; + int i; + + /* Save number of bits. */ + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64. */ + index = sctx->count & 0x3f; + pad_len = (index < 56) ? (56 - index) : ((64+56) - index); + + flags = octeon_crypto_enable(&state); + octeon_sha256_store_hash(sctx); + + __octeon_sha256_update(sctx, padding, pad_len); + + /* Append length (before padding). */ + __octeon_sha256_update(sctx, (const u8 *)&bits, sizeof(bits)); + + octeon_sha256_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + /* Store state in digest */ + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be32(sctx->state[i]); + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(*sctx)); + + return 0; +} + +static int octeon_sha224_final(struct shash_desc *desc, u8 *hash) +{ + u8 D[SHA256_DIGEST_SIZE]; + + octeon_sha256_final(desc, D); + + memcpy(hash, D, SHA224_DIGEST_SIZE); + memzero_explicit(D, SHA256_DIGEST_SIZE); + + return 0; +} + +static int octeon_sha256_export(struct shash_desc *desc, void *out) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + + memcpy(out, sctx, sizeof(*sctx)); + return 0; +} + +static int octeon_sha256_import(struct shash_desc *desc, const void *in) +{ + struct sha256_state *sctx = shash_desc_ctx(desc); + + memcpy(sctx, in, sizeof(*sctx)); + return 0; +} + +static struct shash_alg octeon_sha256_algs[2] = { { + .digestsize = SHA256_DIGEST_SIZE, + .init = octeon_sha256_init, + .update = octeon_sha256_update, + .final = octeon_sha256_final, + .export = octeon_sha256_export, + .import = octeon_sha256_import, + .descsize = sizeof(struct sha256_state), + .statesize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha256", + .cra_driver_name= "octeon-sha256", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}, { + .digestsize = SHA224_DIGEST_SIZE, + .init = octeon_sha224_init, + .update = octeon_sha256_update, + .final = octeon_sha224_final, + .descsize = sizeof(struct sha256_state), + .base = { + .cra_name = "sha224", + .cra_driver_name= "octeon-sha224", + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA224_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +} }; + +static int __init octeon_sha256_mod_init(void) +{ + if (!octeon_has_crypto()) + return -ENOTSUPP; + return crypto_register_shashes(octeon_sha256_algs, + ARRAY_SIZE(octeon_sha256_algs)); +} + +static void __exit octeon_sha256_mod_fini(void) +{ + crypto_unregister_shashes(octeon_sha256_algs, + ARRAY_SIZE(octeon_sha256_algs)); +} + +module_init(octeon_sha256_mod_init); +module_exit(octeon_sha256_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm (OCTEON)"); +MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha512.c b/arch/mips/cavium-octeon/crypto/octeon-sha512.c new file mode 100644 index 000000000000..d5fb3c6f22ae --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-sha512.c @@ -0,0 +1,277 @@ +/* + * Cryptographic API. + * + * SHA-512 and SHA-384 Secure Hash Algorithm. + * + * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>. + * + * Based on crypto/sha512_generic.c, which is: + * + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + */ + +#include <linux/mm.h> +#include <crypto/sha.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <asm/byteorder.h> +#include <asm/octeon/octeon.h> +#include <crypto/internal/hash.h> + +#include "octeon-crypto.h" + +/* + * We pass everything as 64-bit. OCTEON can handle misaligned data. + */ + +static void octeon_sha512_store_hash(struct sha512_state *sctx) +{ + write_octeon_64bit_hash_sha512(sctx->state[0], 0); + write_octeon_64bit_hash_sha512(sctx->state[1], 1); + write_octeon_64bit_hash_sha512(sctx->state[2], 2); + write_octeon_64bit_hash_sha512(sctx->state[3], 3); + write_octeon_64bit_hash_sha512(sctx->state[4], 4); + write_octeon_64bit_hash_sha512(sctx->state[5], 5); + write_octeon_64bit_hash_sha512(sctx->state[6], 6); + write_octeon_64bit_hash_sha512(sctx->state[7], 7); +} + +static void octeon_sha512_read_hash(struct sha512_state *sctx) +{ + sctx->state[0] = read_octeon_64bit_hash_sha512(0); + sctx->state[1] = read_octeon_64bit_hash_sha512(1); + sctx->state[2] = read_octeon_64bit_hash_sha512(2); + sctx->state[3] = read_octeon_64bit_hash_sha512(3); + sctx->state[4] = read_octeon_64bit_hash_sha512(4); + sctx->state[5] = read_octeon_64bit_hash_sha512(5); + sctx->state[6] = read_octeon_64bit_hash_sha512(6); + sctx->state[7] = read_octeon_64bit_hash_sha512(7); +} + +static void octeon_sha512_transform(const void *_block) +{ + const u64 *block = _block; + + write_octeon_64bit_block_sha512(block[0], 0); + write_octeon_64bit_block_sha512(block[1], 1); + write_octeon_64bit_block_sha512(block[2], 2); + write_octeon_64bit_block_sha512(block[3], 3); + write_octeon_64bit_block_sha512(block[4], 4); + write_octeon_64bit_block_sha512(block[5], 5); + write_octeon_64bit_block_sha512(block[6], 6); + write_octeon_64bit_block_sha512(block[7], 7); + write_octeon_64bit_block_sha512(block[8], 8); + write_octeon_64bit_block_sha512(block[9], 9); + write_octeon_64bit_block_sha512(block[10], 10); + write_octeon_64bit_block_sha512(block[11], 11); + write_octeon_64bit_block_sha512(block[12], 12); + write_octeon_64bit_block_sha512(block[13], 13); + write_octeon_64bit_block_sha512(block[14], 14); + octeon_sha512_start(block[15]); +} + +static int octeon_sha512_init(struct shash_desc *desc) +{ + struct sha512_state *sctx = shash_desc_ctx(desc); + + sctx->state[0] = SHA512_H0; + sctx->state[1] = SHA512_H1; + sctx->state[2] = SHA512_H2; + sctx->state[3] = SHA512_H3; + sctx->state[4] = SHA512_H4; + sctx->state[5] = SHA512_H5; + sctx->state[6] = SHA512_H6; + sctx->state[7] = SHA512_H7; + sctx->count[0] = sctx->count[1] = 0; + + return 0; +} + +static int octeon_sha384_init(struct shash_desc *desc) +{ + struct sha512_state *sctx = shash_desc_ctx(desc); + + sctx->state[0] = SHA384_H0; + sctx->state[1] = SHA384_H1; + sctx->state[2] = SHA384_H2; + sctx->state[3] = SHA384_H3; + sctx->state[4] = SHA384_H4; + sctx->state[5] = SHA384_H5; + sctx->state[6] = SHA384_H6; + sctx->state[7] = SHA384_H7; + sctx->count[0] = sctx->count[1] = 0; + + return 0; +} + +static void __octeon_sha512_update(struct sha512_state *sctx, const u8 *data, + unsigned int len) +{ + unsigned int part_len; + unsigned int index; + unsigned int i; + + /* Compute number of bytes mod 128. */ + index = sctx->count[0] % SHA512_BLOCK_SIZE; + + /* Update number of bytes. */ + if ((sctx->count[0] += len) < len) + sctx->count[1]++; + + part_len = SHA512_BLOCK_SIZE - index; + + /* Transform as many times as possible. */ + if (len >= part_len) { + memcpy(&sctx->buf[index], data, part_len); + octeon_sha512_transform(sctx->buf); + + for (i = part_len; i + SHA512_BLOCK_SIZE <= len; + i += SHA512_BLOCK_SIZE) + octeon_sha512_transform(&data[i]); + + index = 0; + } else { + i = 0; + } + + /* Buffer remaining input. */ + memcpy(&sctx->buf[index], &data[i], len - i); +} + +static int octeon_sha512_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct sha512_state *sctx = shash_desc_ctx(desc); + struct octeon_cop2_state state; + unsigned long flags; + + /* + * Small updates never reach the crypto engine, so the generic sha512 is + * faster because of the heavyweight octeon_crypto_enable() / + * octeon_crypto_disable(). + */ + if ((sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE) + return crypto_sha512_update(desc, data, len); + + flags = octeon_crypto_enable(&state); + octeon_sha512_store_hash(sctx); + + __octeon_sha512_update(sctx, data, len); + + octeon_sha512_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + return 0; +} + +static int octeon_sha512_final(struct shash_desc *desc, u8 *hash) +{ + struct sha512_state *sctx = shash_desc_ctx(desc); + static u8 padding[128] = { 0x80, }; + struct octeon_cop2_state state; + __be64 *dst = (__be64 *)hash; + unsigned int pad_len; + unsigned long flags; + unsigned int index; + __be64 bits[2]; + int i; + + /* Save number of bits. */ + bits[1] = cpu_to_be64(sctx->count[0] << 3); + bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); + + /* Pad out to 112 mod 128. */ + index = sctx->count[0] & 0x7f; + pad_len = (index < 112) ? (112 - index) : ((128+112) - index); + + flags = octeon_crypto_enable(&state); + octeon_sha512_store_hash(sctx); + + __octeon_sha512_update(sctx, padding, pad_len); + + /* Append length (before padding). */ + __octeon_sha512_update(sctx, (const u8 *)bits, sizeof(bits)); + + octeon_sha512_read_hash(sctx); + octeon_crypto_disable(&state, flags); + + /* Store state in digest. */ + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be64(sctx->state[i]); + + /* Zeroize sensitive information. */ + memset(sctx, 0, sizeof(struct sha512_state)); + + return 0; +} + +static int octeon_sha384_final(struct shash_desc *desc, u8 *hash) +{ + u8 D[64]; + + octeon_sha512_final(desc, D); + + memcpy(hash, D, 48); + memzero_explicit(D, 64); + + return 0; +} + +static struct shash_alg octeon_sha512_algs[2] = { { + .digestsize = SHA512_DIGEST_SIZE, + .init = octeon_sha512_init, + .update = octeon_sha512_update, + .final = octeon_sha512_final, + .descsize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha512", + .cra_driver_name= "octeon-sha512", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}, { + .digestsize = SHA384_DIGEST_SIZE, + .init = octeon_sha384_init, + .update = octeon_sha512_update, + .final = octeon_sha384_final, + .descsize = sizeof(struct sha512_state), + .base = { + .cra_name = "sha384", + .cra_driver_name= "octeon-sha384", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +} }; + +static int __init octeon_sha512_mod_init(void) +{ + if (!octeon_has_crypto()) + return -ENOTSUPP; + return crypto_register_shashes(octeon_sha512_algs, + ARRAY_SIZE(octeon_sha512_algs)); +} + +static void __exit octeon_sha512_mod_fini(void) +{ + crypto_unregister_shashes(octeon_sha512_algs, + ARRAY_SIZE(octeon_sha512_algs)); +} + +module_init(octeon_sha512_mod_init); +module_exit(octeon_sha512_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms (OCTEON)"); +MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 7d8987818ccf..d8960d46417b 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -306,7 +306,7 @@ void __init plat_swiotlb_setup(void) swiotlbsize = 64 * (1<<20); } #endif -#ifdef CONFIG_USB_OCTEON_OHCI +#ifdef CONFIG_USB_OHCI_HCD_PLATFORM /* OCTEON II ohci is only 32-bit. */ if (OCTEON_IS_OCTEON2() && max_addr >= 0x100000000ul) swiotlbsize = 64 * (1<<20); diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c index 42e38c30b540..89b5273299ab 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c +++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c @@ -519,44 +519,89 @@ int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len) union __cvmx_l2c_tag { uint64_t u64; struct cvmx_l2c_tag_cn50xx { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:40; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:20; /* Phys mem addr (33..14) */ +#else + uint64_t addr:20; /* Phys mem addr (33..14) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:40; +#endif } cn50xx; struct cvmx_l2c_tag_cn30xx { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:41; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:19; /* Phys mem addr (33..15) */ +#else + uint64_t addr:19; /* Phys mem addr (33..15) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:41; +#endif } cn30xx; struct cvmx_l2c_tag_cn31xx { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:42; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:18; /* Phys mem addr (33..16) */ +#else + uint64_t addr:18; /* Phys mem addr (33..16) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:42; +#endif } cn31xx; struct cvmx_l2c_tag_cn38xx { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:43; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:17; /* Phys mem addr (33..17) */ +#else + uint64_t addr:17; /* Phys mem addr (33..17) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:43; +#endif } cn38xx; struct cvmx_l2c_tag_cn58xx { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:44; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:16; /* Phys mem addr (33..18) */ +#else + uint64_t addr:16; /* Phys mem addr (33..18) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:44; +#endif } cn58xx; struct cvmx_l2c_tag_cn58xx cn56xx; /* 2048 sets */ struct cvmx_l2c_tag_cn31xx cn52xx; /* 512 sets */ diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c index 237e5b1a72d8..a5e8f4a784af 100644 --- a/arch/mips/cavium-octeon/flash_setup.c +++ b/arch/mips/cavium-octeon/flash_setup.c @@ -8,9 +8,11 @@ * Copyright (C) 2007, 2008 Cavium Networks */ #include <linux/kernel.h> -#include <linux/export.h> +#include <linux/module.h> +#include <linux/semaphore.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> +#include <linux/of_platform.h> #include <linux/mtd/partitions.h> #include <asm/octeon/octeon.h> @@ -25,19 +27,62 @@ static const char *part_probe_types[] = { NULL }; +static map_word octeon_flash_map_read(struct map_info *map, unsigned long ofs) +{ + map_word r; + + down(&octeon_bootbus_sem); + r = inline_map_read(map, ofs); + up(&octeon_bootbus_sem); + + return r; +} + +static void octeon_flash_map_write(struct map_info *map, const map_word datum, + unsigned long ofs) +{ + down(&octeon_bootbus_sem); + inline_map_write(map, datum, ofs); + up(&octeon_bootbus_sem); +} + +static void octeon_flash_map_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + down(&octeon_bootbus_sem); + inline_map_copy_from(map, to, from, len); + up(&octeon_bootbus_sem); +} + +static void octeon_flash_map_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + down(&octeon_bootbus_sem); + inline_map_copy_to(map, to, from, len); + up(&octeon_bootbus_sem); +} + /** * Module/ driver initialization. * * Returns Zero on success */ -static int __init flash_init(void) +static int octeon_flash_probe(struct platform_device *pdev) { + union cvmx_mio_boot_reg_cfgx region_cfg; + u32 cs; + int r; + struct device_node *np = pdev->dev.of_node; + + r = of_property_read_u32(np, "reg", &cs); + if (r) + return r; + /* * Read the bootbus region 0 setup to determine the base * address of the flash. */ - union cvmx_mio_boot_reg_cfgx region_cfg; - region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(0)); + region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); if (region_cfg.s.en) { /* * The bootloader always takes the flash and sets its @@ -56,7 +101,11 @@ static int __init flash_init(void) flash_map.virt = ioremap(flash_map.phys, flash_map.size); pr_notice("Bootbus flash: Setting flash for %luMB flash at " "0x%08llx\n", flash_map.size >> 20, flash_map.phys); - simple_map_init(&flash_map); + WARN_ON(!map_bankwidth_supported(flash_map.bankwidth)); + flash_map.read = octeon_flash_map_read; + flash_map.write = octeon_flash_map_write; + flash_map.copy_from = octeon_flash_map_copy_from; + flash_map.copy_to = octeon_flash_map_copy_to; mymtd = do_map_probe("cfi_probe", &flash_map); if (mymtd) { mymtd->owner = THIS_MODULE; @@ -69,4 +118,26 @@ static int __init flash_init(void) return 0; } -late_initcall(flash_init); +static const struct of_device_id of_flash_match[] = { + { + .compatible = "cfi-flash", + }, + { }, +}; +MODULE_DEVICE_TABLE(of, of_flash_match); + +static struct platform_driver of_flash_driver = { + .driver = { + .name = "octeon-of-flash", + .of_match_table = of_flash_match, + }, + .probe = octeon_flash_probe, +}; + +static int octeon_flash_init(void) +{ + return platform_driver_register(&of_flash_driver); +} +late_initcall(octeon_flash_init); + +MODULE_LICENSE("GPL"); diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 12410a2788d8..d113c8ded6e2 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -325,8 +325,14 @@ static void __init octeon_ehci_hw_start(struct device *dev) /* Use 64-bit addressing. */ ehci_ctl.s.ehci_64b_addr_en = 1; ehci_ctl.s.l2c_addr_msb = 0; +#ifdef __BIG_ENDIAN ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ +#else + ehci_ctl.s.l2c_buff_emod = 0; /* not swapped. */ + ehci_ctl.s.l2c_desc_emod = 0; /* not swapped. */ + ehci_ctl.s.inv_reg_a2 = 1; +#endif cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64); octeon2_usb_clocks_stop(); @@ -381,8 +387,14 @@ static void __init octeon_ohci_hw_start(struct device *dev) ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); ohci_ctl.s.l2c_addr_msb = 0; +#ifdef __BIG_ENDIAN ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ +#else + ohci_ctl.s.l2c_buff_emod = 0; /* not swapped. */ + ohci_ctl.s.l2c_desc_emod = 0; /* not swapped. */ + ohci_ctl.s.inv_reg_a2 = 1; +#endif cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64); octeon2_usb_clocks_stop(); @@ -958,6 +970,13 @@ end_led: } } + if (octeon_bootinfo->board_type != CVMX_BOARD_TYPE_CUST_DSR1000N) { + int dsr1000n_leds = fdt_path_offset(initial_boot_params, + "/dsr1000n-leds"); + if (dsr1000n_leds >= 0) + fdt_nop_node(initial_boot_params, dsr1000n_leds); + } + return 0; } diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h index 7b066bbca86d..a6ce7c43e0ae 100644 --- a/arch/mips/cavium-octeon/octeon_boot.h +++ b/arch/mips/cavium-octeon/octeon_boot.h @@ -37,11 +37,13 @@ struct boot_init_vector { /* similar to bootloader's linux_app_boot_info but without global data */ struct linux_app_boot_info { +#ifdef __BIG_ENDIAN_BITFIELD uint32_t labi_signature; uint32_t start_core0_addr; uint32_t avail_coremask; uint32_t pci_console_active; uint32_t icache_prefetch_disable; + uint32_t padding; uint64_t InitTLBStart_addr; uint32_t start_app_addr; uint32_t cur_exception_base; @@ -49,6 +51,27 @@ struct linux_app_boot_info { uint32_t compact_flash_common_base_addr; uint32_t compact_flash_attribute_base_addr; uint32_t led_display_base_addr; +#else + uint32_t start_core0_addr; + uint32_t labi_signature; + + uint32_t pci_console_active; + uint32_t avail_coremask; + + uint32_t padding; + uint32_t icache_prefetch_disable; + + uint64_t InitTLBStart_addr; + + uint32_t cur_exception_base; + uint32_t start_app_addr; + + uint32_t compact_flash_common_base_addr; + uint32_t no_mark_private_data; + + uint32_t led_display_base_addr; + uint32_t compact_flash_attribute_base_addr; +#endif }; /* If not to copy a lot of bootloader's structures diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index a42110e7edbc..89a628455bc2 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -51,6 +51,9 @@ extern void pci_console_init(const char *arg); static unsigned long long MAX_MEMORY = 512ull << 20; +DEFINE_SEMAPHORE(octeon_bootbus_sem); +EXPORT_SYMBOL(octeon_bootbus_sem); + struct octeon_boot_descriptor *octeon_boot_desc_ptr; struct cvmx_bootinfo *octeon_bootinfo; @@ -413,7 +416,10 @@ static void octeon_restart(char *command) mb(); while (1) - cvmx_write_csr(CVMX_CIU_SOFT_RST, 1); + if (OCTEON_IS_OCTEON3()) + cvmx_write_csr(CVMX_RST_SOFT_RST, 1); + else + cvmx_write_csr(CVMX_CIU_SOFT_RST, 1); } @@ -1043,7 +1049,7 @@ int prom_putchar(char c) } EXPORT_SYMBOL(prom_putchar); -void prom_free_prom_memory(void) +void __init prom_free_prom_memory(void) { if (CAVIUM_OCTEON_DCACHE_PREFETCH_WAR) { /* Check for presence of Core-14449 fix. */ diff --git a/arch/mips/configs/bcm3384_defconfig b/arch/mips/configs/bmips_be_defconfig index 88711c28ff32..f5585c8f35ad 100644 --- a/arch/mips/configs/bcm3384_defconfig +++ b/arch/mips/configs/bmips_be_defconfig @@ -1,4 +1,4 @@ -CONFIG_BCM3384=y +CONFIG_BMIPS_GENERIC=y CONFIG_HIGHMEM=y CONFIG_SMP=y CONFIG_NR_CPUS=4 @@ -33,6 +33,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_BRCMSTB_GISB_ARB=y CONFIG_MTD=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y @@ -43,15 +44,19 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y +CONFIG_BCMGENET=y CONFIG_USB_USBNET=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -CONFIG_SERIAL_EARLYCON_FORCE=y CONFIG_SERIAL_BCM63XX=y CONFIG_SERIAL_BCM63XX_CONSOLE=y # CONFIG_HW_RANDOM is not set +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_BRCMSTB=y +CONFIG_POWER_RESET_SYSCON=y # CONFIG_HWMON is not set CONFIG_USB=y CONFIG_USB_EHCI_HCD=y @@ -75,4 +80,6 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_DEBUG_FS=y CONFIG_MAGIC_SYSRQ=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="earlycon" # CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/bmips_stb_defconfig b/arch/mips/configs/bmips_stb_defconfig new file mode 100644 index 000000000000..400a47ec1ef1 --- /dev/null +++ b/arch/mips/configs/bmips_stb_defconfig @@ -0,0 +1,88 @@ +CONFIG_BMIPS_GENERIC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_HIGHMEM=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +# CONFIG_SECCOMP is not set +CONFIG_MIPS_O32_FP64_SUPPORT=y +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_NO_HZ=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_GZIP is not set +CONFIG_EXPERT=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +CONFIG_MAC80211=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_BRCMSTB_GISB_ARB=y +CONFIG_MTD=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_BLK_DEV is not set +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +CONFIG_BCMGENET=y +CONFIG_USB_USBNET=y +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_BRCMSTB=y +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_HWMON is not set +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_STORAGE=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_FUSE_FS=y +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_CIFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="earlycon" +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 70ffe9b55829..fe48220157a9 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -105,7 +105,8 @@ CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set # CONFIG_RTC_INTF_SYSFS is not set # CONFIG_RTC_INTF_PROC is not set -CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_DS1685_FAMILY=y +CONFIG_RTC_DRV_DS1685=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig new file mode 100644 index 000000000000..c388bff09148 --- /dev/null +++ b/arch/mips/configs/maltaup_xpa_defconfig @@ -0,0 +1,439 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPS32_R5_FEATURES=y +CONFIG_CPU_MIPS32_R5_XPA=y +CONFIG_PAGE_SIZE_16KB=y +CONFIG_HZ_100=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_NAMESPACES=y +CONFIG_RELAY=y +CONFIG_EXPERT=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_PCI=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_SCTP=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_PHONET=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=m +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_OOPS=m +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_GLUEBI=m +CONFIG_BLK_DEV_FD=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_IDE=y +CONFIG_BLK_DEV_IDECD=y +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_FC_ATTRS=m +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_PCNET32=y +CONFIG_CHELSIO_T3=m +CONFIG_AX88796=m +CONFIG_NETXEN_NIC=m +CONFIG_TC35815=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PRISM54=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_LIBERTAS=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HWMON is not set +CONFIG_FB=y +CONFIG_FB_CIRRUS=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HID=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_RUBIN=y +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC16=m diff --git a/arch/mips/configs/pistachio_defconfig b/arch/mips/configs/pistachio_defconfig new file mode 100644 index 000000000000..f22e92ee7709 --- /dev/null +++ b/arch/mips/configs/pistachio_defconfig @@ -0,0 +1,336 @@ +CONFIG_MACH_PISTACHIO=y +CONFIG_MIPS_MT_SMP=y +CONFIG_MIPS_CPS=y +# CONFIG_COMPACTION is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_ZSMALLOC=y +CONFIG_NR_CPUS=4 +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="localhost" +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_CPU_IDLE=y +# CONFIG_MIPS_CPS_CPUIDLE is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_IPV6_SIT=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_BRIDGE_NETFILTER is not set +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_DSCP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_NAT_IPV4=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_MARK=y +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_MAC80211_DEBUG_MENU=y +CONFIG_MAC80211_VERBOSE_DEBUG=y +CONFIG_RFKILL=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DEBUG_DEVRES=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BLOCK=y +CONFIG_ZRAM=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_VERITY=y +CONFIG_NETDEVICES=y +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +# CONFIG_NET_VENDOR_VIA is not set +CONFIG_PPP=m +CONFIG_PPP_ASYNC=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_MCS7830=m +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_MAC80211_HWSIM=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_RT2X00=m +CONFIG_RT2800USB=m +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_HW_RANDOM=y +CONFIG_TCG_TPM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_IMG=y +CONFIG_I2C_STUB=m +CONFIG_SPI=y +CONFIG_SPI_BITBANG=m +CONFIG_SPI_IMG_SPFI=y +CONFIG_SPI_SPIDEV=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +CONFIG_IMGPDC_WDT=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +# CONFIG_RC_DECODERS is not set +CONFIG_RC_DEVICES=y +CONFIG_IR_IMG=y +CONFIG_IR_IMG_NEC=y +CONFIG_IR_IMG_JVC=y +CONFIG_IR_IMG_SONY=y +CONFIG_IR_IMG_SHARP=y +CONFIG_IR_IMG_SANYO=y +CONFIG_IR_IMG_RC5=y +CONFIG_IR_IMG_RC6=y +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_HRTIMER=m +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_DEFAULT_PERSIST is not set +CONFIG_USB_MON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_DWC2=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=16 +CONFIG_MMC_TEST=m +CONFIG_MMC_DW=y +CONFIG_MMC_DW_IDMAC=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_IMG_MDC_DMA=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +# CONFIG_ANDROID_TIMED_OUTPUT is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_MEMORY=y +CONFIG_IIO=y +CONFIG_CC10001_ADC=y +CONFIG_PWM=y +CONFIG_PWM_IMG=y +CONFIG_ANDROID=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_FUSE_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_VFAT_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_ECRYPT_FS=y +CONFIG_HFSPLUS_FS=m +CONFIG_UBIFS_FS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_LZO=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +CONFIG_LOCKUP_DETECTOR=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_FUNCTION_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=y +CONFIG_TEST_UDELAY=m +CONFIG_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_YAMA=y +CONFIG_SECURITY_YAMA_STACKED=y +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC_T10DIF=m +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +# CONFIG_XZ_DEC_X86 is not set diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S index 41a2fa1fa12e..8c6f508e59de 100644 --- a/arch/mips/dec/int-handler.S +++ b/arch/mips/dec/int-handler.S @@ -267,8 +267,13 @@ handle_it: #ifdef CONFIG_32BIT fpu: + lw t0,fpu_kstat_irq + nop + lw t1,(t0) + nop + addu t1,1 j handle_fpe_int - nop + sw t1,(t0) #endif spurious: diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 41bbffd9cc0e..a0b8943c8f11 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -12,13 +12,15 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/ioport.h> +#include <linux/irq.h> +#include <linux/irqnr.h> #include <linux/module.h> #include <linux/param.h> +#include <linux/percpu-defs.h> #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/types.h> #include <linux/pm.h> -#include <linux/irq.h> #include <asm/bootinfo.h> #include <asm/cpu.h> @@ -98,6 +100,7 @@ int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2] = { { { .i = ~0 }, { .p = asic_intr_unimplemented } }, }; int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU); +int *fpu_kstat_irq; static struct irqaction ioirq = { .handler = no_action, @@ -755,8 +758,15 @@ void __init arch_init_irq(void) dec_interrupt[DEC_IRQ_HALT] = -1; /* Register board interrupts: FPU and cascade. */ - if (dec_interrupt[DEC_IRQ_FPU] >= 0) - setup_irq(dec_interrupt[DEC_IRQ_FPU], &fpuirq); + if (dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) { + struct irq_desc *desc_fpu; + int irq_fpu; + + irq_fpu = dec_interrupt[DEC_IRQ_FPU]; + setup_irq(irq_fpu, &fpuirq); + desc_fpu = irq_to_desc(irq_fpu); + fpu_kstat_irq = this_cpu_ptr(desc_fpu->kstat_irqs); + } if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) setup_irq(dec_interrupt[DEC_IRQ_CASCADE], &ioirq); diff --git a/arch/mips/include/asm/asm-eva.h b/arch/mips/include/asm/asm-eva.h index e41c56e375b1..1e38f0e1ea3e 100644 --- a/arch/mips/include/asm/asm-eva.h +++ b/arch/mips/include/asm/asm-eva.h @@ -11,6 +11,36 @@ #define __ASM_ASM_EVA_H #ifndef __ASSEMBLY__ + +/* Kernel variants */ + +#define kernel_cache(op, base) "cache " op ", " base "\n" +#define kernel_ll(reg, addr) "ll " reg ", " addr "\n" +#define kernel_sc(reg, addr) "sc " reg ", " addr "\n" +#define kernel_lw(reg, addr) "lw " reg ", " addr "\n" +#define kernel_lwl(reg, addr) "lwl " reg ", " addr "\n" +#define kernel_lwr(reg, addr) "lwr " reg ", " addr "\n" +#define kernel_lh(reg, addr) "lh " reg ", " addr "\n" +#define kernel_lb(reg, addr) "lb " reg ", " addr "\n" +#define kernel_lbu(reg, addr) "lbu " reg ", " addr "\n" +#define kernel_sw(reg, addr) "sw " reg ", " addr "\n" +#define kernel_swl(reg, addr) "swl " reg ", " addr "\n" +#define kernel_swr(reg, addr) "swr " reg ", " addr "\n" +#define kernel_sh(reg, addr) "sh " reg ", " addr "\n" +#define kernel_sb(reg, addr) "sb " reg ", " addr "\n" + +#ifdef CONFIG_32BIT +/* + * No 'sd' or 'ld' instructions in 32-bit but the code will + * do the correct thing + */ +#define kernel_sd(reg, addr) user_sw(reg, addr) +#define kernel_ld(reg, addr) user_lw(reg, addr) +#else +#define kernel_sd(reg, addr) "sd " reg", " addr "\n" +#define kernel_ld(reg, addr) "ld " reg", " addr "\n" +#endif /* CONFIG_32BIT */ + #ifdef CONFIG_EVA #define __BUILD_EVA_INSN(insn, reg, addr) \ @@ -41,37 +71,60 @@ #else -#define user_cache(op, base) "cache " op ", " base "\n" -#define user_ll(reg, addr) "ll " reg ", " addr "\n" -#define user_sc(reg, addr) "sc " reg ", " addr "\n" -#define user_lw(reg, addr) "lw " reg ", " addr "\n" -#define user_lwl(reg, addr) "lwl " reg ", " addr "\n" -#define user_lwr(reg, addr) "lwr " reg ", " addr "\n" -#define user_lh(reg, addr) "lh " reg ", " addr "\n" -#define user_lb(reg, addr) "lb " reg ", " addr "\n" -#define user_lbu(reg, addr) "lbu " reg ", " addr "\n" -#define user_sw(reg, addr) "sw " reg ", " addr "\n" -#define user_swl(reg, addr) "swl " reg ", " addr "\n" -#define user_swr(reg, addr) "swr " reg ", " addr "\n" -#define user_sh(reg, addr) "sh " reg ", " addr "\n" -#define user_sb(reg, addr) "sb " reg ", " addr "\n" +#define user_cache(op, base) kernel_cache(op, base) +#define user_ll(reg, addr) kernel_ll(reg, addr) +#define user_sc(reg, addr) kernel_sc(reg, addr) +#define user_lw(reg, addr) kernel_lw(reg, addr) +#define user_lwl(reg, addr) kernel_lwl(reg, addr) +#define user_lwr(reg, addr) kernel_lwr(reg, addr) +#define user_lh(reg, addr) kernel_lh(reg, addr) +#define user_lb(reg, addr) kernel_lb(reg, addr) +#define user_lbu(reg, addr) kernel_lbu(reg, addr) +#define user_sw(reg, addr) kernel_sw(reg, addr) +#define user_swl(reg, addr) kernel_swl(reg, addr) +#define user_swr(reg, addr) kernel_swr(reg, addr) +#define user_sh(reg, addr) kernel_sh(reg, addr) +#define user_sb(reg, addr) kernel_sb(reg, addr) #ifdef CONFIG_32BIT -/* - * No 'sd' or 'ld' instructions in 32-bit but the code will - * do the correct thing - */ -#define user_sd(reg, addr) user_sw(reg, addr) -#define user_ld(reg, addr) user_lw(reg, addr) +#define user_sd(reg, addr) kernel_sw(reg, addr) +#define user_ld(reg, addr) kernel_lw(reg, addr) #else -#define user_sd(reg, addr) "sd " reg", " addr "\n" -#define user_ld(reg, addr) "ld " reg", " addr "\n" +#define user_sd(reg, addr) kernel_sd(reg, addr) +#define user_ld(reg, addr) kernel_ld(reg, addr) #endif /* CONFIG_32BIT */ #endif /* CONFIG_EVA */ #else /* __ASSEMBLY__ */ +#define kernel_cache(op, base) cache op, base +#define kernel_ll(reg, addr) ll reg, addr +#define kernel_sc(reg, addr) sc reg, addr +#define kernel_lw(reg, addr) lw reg, addr +#define kernel_lwl(reg, addr) lwl reg, addr +#define kernel_lwr(reg, addr) lwr reg, addr +#define kernel_lh(reg, addr) lh reg, addr +#define kernel_lb(reg, addr) lb reg, addr +#define kernel_lbu(reg, addr) lbu reg, addr +#define kernel_sw(reg, addr) sw reg, addr +#define kernel_swl(reg, addr) swl reg, addr +#define kernel_swr(reg, addr) swr reg, addr +#define kernel_sh(reg, addr) sh reg, addr +#define kernel_sb(reg, addr) sb reg, addr + +#ifdef CONFIG_32BIT +/* + * No 'sd' or 'ld' instructions in 32-bit but the code will + * do the correct thing + */ +#define kernel_sd(reg, addr) user_sw(reg, addr) +#define kernel_ld(reg, addr) user_lw(reg, addr) +#else +#define kernel_sd(reg, addr) sd reg, addr +#define kernel_ld(reg, addr) ld reg, addr +#endif /* CONFIG_32BIT */ + #ifdef CONFIG_EVA #define __BUILD_EVA_INSN(insn, reg, addr) \ @@ -101,31 +154,27 @@ #define user_sd(reg, addr) user_sw(reg, addr) #else -#define user_cache(op, base) cache op, base -#define user_ll(reg, addr) ll reg, addr -#define user_sc(reg, addr) sc reg, addr -#define user_lw(reg, addr) lw reg, addr -#define user_lwl(reg, addr) lwl reg, addr -#define user_lwr(reg, addr) lwr reg, addr -#define user_lh(reg, addr) lh reg, addr -#define user_lb(reg, addr) lb reg, addr -#define user_lbu(reg, addr) lbu reg, addr -#define user_sw(reg, addr) sw reg, addr -#define user_swl(reg, addr) swl reg, addr -#define user_swr(reg, addr) swr reg, addr -#define user_sh(reg, addr) sh reg, addr -#define user_sb(reg, addr) sb reg, addr +#define user_cache(op, base) kernel_cache(op, base) +#define user_ll(reg, addr) kernel_ll(reg, addr) +#define user_sc(reg, addr) kernel_sc(reg, addr) +#define user_lw(reg, addr) kernel_lw(reg, addr) +#define user_lwl(reg, addr) kernel_lwl(reg, addr) +#define user_lwr(reg, addr) kernel_lwr(reg, addr) +#define user_lh(reg, addr) kernel_lh(reg, addr) +#define user_lb(reg, addr) kernel_lb(reg, addr) +#define user_lbu(reg, addr) kernel_lbu(reg, addr) +#define user_sw(reg, addr) kernel_sw(reg, addr) +#define user_swl(reg, addr) kernel_swl(reg, addr) +#define user_swr(reg, addr) kernel_swr(reg, addr) +#define user_sh(reg, addr) kernel_sh(reg, addr) +#define user_sb(reg, addr) kernel_sb(reg, addr) #ifdef CONFIG_32BIT -/* - * No 'sd' or 'ld' instructions in 32-bit but the code will - * do the correct thing - */ -#define user_sd(reg, addr) user_sw(reg, addr) -#define user_ld(reg, addr) user_lw(reg, addr) +#define user_sd(reg, addr) kernel_sw(reg, addr) +#define user_ld(reg, addr) kernel_lw(reg, addr) #else -#define user_sd(reg, addr) sd reg, addr -#define user_ld(reg, addr) ld reg, addr +#define user_sd(reg, addr) kernel_sd(reg, addr) +#define user_ld(reg, addr) kernel_sd(reg, addr) #endif /* CONFIG_32BIT */ #endif /* CONFIG_EVA */ diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h index cdac7b3eeaf7..0ef39ad0f2d4 100644 --- a/arch/mips/include/asm/asmmacro-32.h +++ b/arch/mips/include/asm/asmmacro-32.h @@ -16,38 +16,22 @@ .set push SET_HARDFLOAT cfc1 \tmp, fcr31 - swc1 $f0, THREAD_FPR0_LS64(\thread) - swc1 $f1, THREAD_FPR1_LS64(\thread) - swc1 $f2, THREAD_FPR2_LS64(\thread) - swc1 $f3, THREAD_FPR3_LS64(\thread) - swc1 $f4, THREAD_FPR4_LS64(\thread) - swc1 $f5, THREAD_FPR5_LS64(\thread) - swc1 $f6, THREAD_FPR6_LS64(\thread) - swc1 $f7, THREAD_FPR7_LS64(\thread) - swc1 $f8, THREAD_FPR8_LS64(\thread) - swc1 $f9, THREAD_FPR9_LS64(\thread) - swc1 $f10, THREAD_FPR10_LS64(\thread) - swc1 $f11, THREAD_FPR11_LS64(\thread) - swc1 $f12, THREAD_FPR12_LS64(\thread) - swc1 $f13, THREAD_FPR13_LS64(\thread) - swc1 $f14, THREAD_FPR14_LS64(\thread) - swc1 $f15, THREAD_FPR15_LS64(\thread) - swc1 $f16, THREAD_FPR16_LS64(\thread) - swc1 $f17, THREAD_FPR17_LS64(\thread) - swc1 $f18, THREAD_FPR18_LS64(\thread) - swc1 $f19, THREAD_FPR19_LS64(\thread) - swc1 $f20, THREAD_FPR20_LS64(\thread) - swc1 $f21, THREAD_FPR21_LS64(\thread) - swc1 $f22, THREAD_FPR22_LS64(\thread) - swc1 $f23, THREAD_FPR23_LS64(\thread) - swc1 $f24, THREAD_FPR24_LS64(\thread) - swc1 $f25, THREAD_FPR25_LS64(\thread) - swc1 $f26, THREAD_FPR26_LS64(\thread) - swc1 $f27, THREAD_FPR27_LS64(\thread) - swc1 $f28, THREAD_FPR28_LS64(\thread) - swc1 $f29, THREAD_FPR29_LS64(\thread) - swc1 $f30, THREAD_FPR30_LS64(\thread) - swc1 $f31, THREAD_FPR31_LS64(\thread) + s.d $f0, THREAD_FPR0(\thread) + s.d $f2, THREAD_FPR2(\thread) + s.d $f4, THREAD_FPR4(\thread) + s.d $f6, THREAD_FPR6(\thread) + s.d $f8, THREAD_FPR8(\thread) + s.d $f10, THREAD_FPR10(\thread) + s.d $f12, THREAD_FPR12(\thread) + s.d $f14, THREAD_FPR14(\thread) + s.d $f16, THREAD_FPR16(\thread) + s.d $f18, THREAD_FPR18(\thread) + s.d $f20, THREAD_FPR20(\thread) + s.d $f22, THREAD_FPR22(\thread) + s.d $f24, THREAD_FPR24(\thread) + s.d $f26, THREAD_FPR26(\thread) + s.d $f28, THREAD_FPR28(\thread) + s.d $f30, THREAD_FPR30(\thread) sw \tmp, THREAD_FCR31(\thread) .set pop .endm @@ -56,38 +40,22 @@ .set push SET_HARDFLOAT lw \tmp, THREAD_FCR31(\thread) - lwc1 $f0, THREAD_FPR0_LS64(\thread) - lwc1 $f1, THREAD_FPR1_LS64(\thread) - lwc1 $f2, THREAD_FPR2_LS64(\thread) - lwc1 $f3, THREAD_FPR3_LS64(\thread) - lwc1 $f4, THREAD_FPR4_LS64(\thread) - lwc1 $f5, THREAD_FPR5_LS64(\thread) - lwc1 $f6, THREAD_FPR6_LS64(\thread) - lwc1 $f7, THREAD_FPR7_LS64(\thread) - lwc1 $f8, THREAD_FPR8_LS64(\thread) - lwc1 $f9, THREAD_FPR9_LS64(\thread) - lwc1 $f10, THREAD_FPR10_LS64(\thread) - lwc1 $f11, THREAD_FPR11_LS64(\thread) - lwc1 $f12, THREAD_FPR12_LS64(\thread) - lwc1 $f13, THREAD_FPR13_LS64(\thread) - lwc1 $f14, THREAD_FPR14_LS64(\thread) - lwc1 $f15, THREAD_FPR15_LS64(\thread) - lwc1 $f16, THREAD_FPR16_LS64(\thread) - lwc1 $f17, THREAD_FPR17_LS64(\thread) - lwc1 $f18, THREAD_FPR18_LS64(\thread) - lwc1 $f19, THREAD_FPR19_LS64(\thread) - lwc1 $f20, THREAD_FPR20_LS64(\thread) - lwc1 $f21, THREAD_FPR21_LS64(\thread) - lwc1 $f22, THREAD_FPR22_LS64(\thread) - lwc1 $f23, THREAD_FPR23_LS64(\thread) - lwc1 $f24, THREAD_FPR24_LS64(\thread) - lwc1 $f25, THREAD_FPR25_LS64(\thread) - lwc1 $f26, THREAD_FPR26_LS64(\thread) - lwc1 $f27, THREAD_FPR27_LS64(\thread) - lwc1 $f28, THREAD_FPR28_LS64(\thread) - lwc1 $f29, THREAD_FPR29_LS64(\thread) - lwc1 $f30, THREAD_FPR30_LS64(\thread) - lwc1 $f31, THREAD_FPR31_LS64(\thread) + l.d $f0, THREAD_FPR0(\thread) + l.d $f2, THREAD_FPR2(\thread) + l.d $f4, THREAD_FPR4(\thread) + l.d $f6, THREAD_FPR6(\thread) + l.d $f8, THREAD_FPR8(\thread) + l.d $f10, THREAD_FPR10(\thread) + l.d $f12, THREAD_FPR12(\thread) + l.d $f14, THREAD_FPR14(\thread) + l.d $f16, THREAD_FPR16(\thread) + l.d $f18, THREAD_FPR18(\thread) + l.d $f20, THREAD_FPR20(\thread) + l.d $f22, THREAD_FPR22(\thread) + l.d $f24, THREAD_FPR24(\thread) + l.d $f26, THREAD_FPR26(\thread) + l.d $f28, THREAD_FPR28(\thread) + l.d $f30, THREAD_FPR30(\thread) ctc1 \tmp, fcr31 .set pop .endm diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 0cae4595e985..6156ac8c4cfb 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -60,22 +60,22 @@ .set push SET_HARDFLOAT cfc1 \tmp, fcr31 - sdc1 $f0, THREAD_FPR0_LS64(\thread) - sdc1 $f2, THREAD_FPR2_LS64(\thread) - sdc1 $f4, THREAD_FPR4_LS64(\thread) - sdc1 $f6, THREAD_FPR6_LS64(\thread) - sdc1 $f8, THREAD_FPR8_LS64(\thread) - sdc1 $f10, THREAD_FPR10_LS64(\thread) - sdc1 $f12, THREAD_FPR12_LS64(\thread) - sdc1 $f14, THREAD_FPR14_LS64(\thread) - sdc1 $f16, THREAD_FPR16_LS64(\thread) - sdc1 $f18, THREAD_FPR18_LS64(\thread) - sdc1 $f20, THREAD_FPR20_LS64(\thread) - sdc1 $f22, THREAD_FPR22_LS64(\thread) - sdc1 $f24, THREAD_FPR24_LS64(\thread) - sdc1 $f26, THREAD_FPR26_LS64(\thread) - sdc1 $f28, THREAD_FPR28_LS64(\thread) - sdc1 $f30, THREAD_FPR30_LS64(\thread) + sdc1 $f0, THREAD_FPR0(\thread) + sdc1 $f2, THREAD_FPR2(\thread) + sdc1 $f4, THREAD_FPR4(\thread) + sdc1 $f6, THREAD_FPR6(\thread) + sdc1 $f8, THREAD_FPR8(\thread) + sdc1 $f10, THREAD_FPR10(\thread) + sdc1 $f12, THREAD_FPR12(\thread) + sdc1 $f14, THREAD_FPR14(\thread) + sdc1 $f16, THREAD_FPR16(\thread) + sdc1 $f18, THREAD_FPR18(\thread) + sdc1 $f20, THREAD_FPR20(\thread) + sdc1 $f22, THREAD_FPR22(\thread) + sdc1 $f24, THREAD_FPR24(\thread) + sdc1 $f26, THREAD_FPR26(\thread) + sdc1 $f28, THREAD_FPR28(\thread) + sdc1 $f30, THREAD_FPR30(\thread) sw \tmp, THREAD_FCR31(\thread) .set pop .endm @@ -84,22 +84,22 @@ .set push .set mips64r2 SET_HARDFLOAT - sdc1 $f1, THREAD_FPR1_LS64(\thread) - sdc1 $f3, THREAD_FPR3_LS64(\thread) - sdc1 $f5, THREAD_FPR5_LS64(\thread) - sdc1 $f7, THREAD_FPR7_LS64(\thread) - sdc1 $f9, THREAD_FPR9_LS64(\thread) - sdc1 $f11, THREAD_FPR11_LS64(\thread) - sdc1 $f13, THREAD_FPR13_LS64(\thread) - sdc1 $f15, THREAD_FPR15_LS64(\thread) - sdc1 $f17, THREAD_FPR17_LS64(\thread) - sdc1 $f19, THREAD_FPR19_LS64(\thread) - sdc1 $f21, THREAD_FPR21_LS64(\thread) - sdc1 $f23, THREAD_FPR23_LS64(\thread) - sdc1 $f25, THREAD_FPR25_LS64(\thread) - sdc1 $f27, THREAD_FPR27_LS64(\thread) - sdc1 $f29, THREAD_FPR29_LS64(\thread) - sdc1 $f31, THREAD_FPR31_LS64(\thread) + sdc1 $f1, THREAD_FPR1(\thread) + sdc1 $f3, THREAD_FPR3(\thread) + sdc1 $f5, THREAD_FPR5(\thread) + sdc1 $f7, THREAD_FPR7(\thread) + sdc1 $f9, THREAD_FPR9(\thread) + sdc1 $f11, THREAD_FPR11(\thread) + sdc1 $f13, THREAD_FPR13(\thread) + sdc1 $f15, THREAD_FPR15(\thread) + sdc1 $f17, THREAD_FPR17(\thread) + sdc1 $f19, THREAD_FPR19(\thread) + sdc1 $f21, THREAD_FPR21(\thread) + sdc1 $f23, THREAD_FPR23(\thread) + sdc1 $f25, THREAD_FPR25(\thread) + sdc1 $f27, THREAD_FPR27(\thread) + sdc1 $f29, THREAD_FPR29(\thread) + sdc1 $f31, THREAD_FPR31(\thread) .set pop .endm @@ -118,22 +118,22 @@ .set push SET_HARDFLOAT lw \tmp, THREAD_FCR31(\thread) - ldc1 $f0, THREAD_FPR0_LS64(\thread) - ldc1 $f2, THREAD_FPR2_LS64(\thread) - ldc1 $f4, THREAD_FPR4_LS64(\thread) - ldc1 $f6, THREAD_FPR6_LS64(\thread) - ldc1 $f8, THREAD_FPR8_LS64(\thread) - ldc1 $f10, THREAD_FPR10_LS64(\thread) - ldc1 $f12, THREAD_FPR12_LS64(\thread) - ldc1 $f14, THREAD_FPR14_LS64(\thread) - ldc1 $f16, THREAD_FPR16_LS64(\thread) - ldc1 $f18, THREAD_FPR18_LS64(\thread) - ldc1 $f20, THREAD_FPR20_LS64(\thread) - ldc1 $f22, THREAD_FPR22_LS64(\thread) - ldc1 $f24, THREAD_FPR24_LS64(\thread) - ldc1 $f26, THREAD_FPR26_LS64(\thread) - ldc1 $f28, THREAD_FPR28_LS64(\thread) - ldc1 $f30, THREAD_FPR30_LS64(\thread) + ldc1 $f0, THREAD_FPR0(\thread) + ldc1 $f2, THREAD_FPR2(\thread) + ldc1 $f4, THREAD_FPR4(\thread) + ldc1 $f6, THREAD_FPR6(\thread) + ldc1 $f8, THREAD_FPR8(\thread) + ldc1 $f10, THREAD_FPR10(\thread) + ldc1 $f12, THREAD_FPR12(\thread) + ldc1 $f14, THREAD_FPR14(\thread) + ldc1 $f16, THREAD_FPR16(\thread) + ldc1 $f18, THREAD_FPR18(\thread) + ldc1 $f20, THREAD_FPR20(\thread) + ldc1 $f22, THREAD_FPR22(\thread) + ldc1 $f24, THREAD_FPR24(\thread) + ldc1 $f26, THREAD_FPR26(\thread) + ldc1 $f28, THREAD_FPR28(\thread) + ldc1 $f30, THREAD_FPR30(\thread) ctc1 \tmp, fcr31 .endm @@ -141,22 +141,22 @@ .set push .set mips64r2 SET_HARDFLOAT - ldc1 $f1, THREAD_FPR1_LS64(\thread) - ldc1 $f3, THREAD_FPR3_LS64(\thread) - ldc1 $f5, THREAD_FPR5_LS64(\thread) - ldc1 $f7, THREAD_FPR7_LS64(\thread) - ldc1 $f9, THREAD_FPR9_LS64(\thread) - ldc1 $f11, THREAD_FPR11_LS64(\thread) - ldc1 $f13, THREAD_FPR13_LS64(\thread) - ldc1 $f15, THREAD_FPR15_LS64(\thread) - ldc1 $f17, THREAD_FPR17_LS64(\thread) - ldc1 $f19, THREAD_FPR19_LS64(\thread) - ldc1 $f21, THREAD_FPR21_LS64(\thread) - ldc1 $f23, THREAD_FPR23_LS64(\thread) - ldc1 $f25, THREAD_FPR25_LS64(\thread) - ldc1 $f27, THREAD_FPR27_LS64(\thread) - ldc1 $f29, THREAD_FPR29_LS64(\thread) - ldc1 $f31, THREAD_FPR31_LS64(\thread) + ldc1 $f1, THREAD_FPR1(\thread) + ldc1 $f3, THREAD_FPR3(\thread) + ldc1 $f5, THREAD_FPR5(\thread) + ldc1 $f7, THREAD_FPR7(\thread) + ldc1 $f9, THREAD_FPR9(\thread) + ldc1 $f11, THREAD_FPR11(\thread) + ldc1 $f13, THREAD_FPR13(\thread) + ldc1 $f15, THREAD_FPR15(\thread) + ldc1 $f17, THREAD_FPR17(\thread) + ldc1 $f19, THREAD_FPR19(\thread) + ldc1 $f21, THREAD_FPR21(\thread) + ldc1 $f23, THREAD_FPR23(\thread) + ldc1 $f25, THREAD_FPR25(\thread) + ldc1 $f27, THREAD_FPR27(\thread) + ldc1 $f29, THREAD_FPR29(\thread) + ldc1 $f31, THREAD_FPR31(\thread) .set pop .endm @@ -211,6 +211,22 @@ .endm #ifdef TOOLCHAIN_SUPPORTS_MSA + .macro _cfcmsa rd, cs + .set push + .set mips32r2 + .set msa + cfcmsa \rd, $\cs + .set pop + .endm + + .macro _ctcmsa cd, rs + .set push + .set mips32r2 + .set msa + ctcmsa $\cd, \rs + .set pop + .endm + .macro ld_d wd, off, base .set push .set mips32r2 @@ -227,35 +243,35 @@ .set pop .endm - .macro copy_u_w rd, ws, n + .macro copy_u_w ws, n .set push .set mips32r2 .set msa - copy_u.w \rd, $w\ws[\n] + copy_u.w $1, $w\ws[\n] .set pop .endm - .macro copy_u_d rd, ws, n + .macro copy_u_d ws, n .set push .set mips64r2 .set msa - copy_u.d \rd, $w\ws[\n] + copy_u.d $1, $w\ws[\n] .set pop .endm - .macro insert_w wd, n, rs + .macro insert_w wd, n .set push .set mips32r2 .set msa - insert.w $w\wd[\n], \rs + insert.w $w\wd[\n], $1 .set pop .endm - .macro insert_d wd, n, rs + .macro insert_d wd, n .set push .set mips64r2 .set msa - insert.d $w\wd[\n], \rs + insert.d $w\wd[\n], $1 .set pop .endm #else @@ -283,7 +299,7 @@ /* * Temporary until all toolchains in use include MSA support. */ - .macro cfcmsa rd, cs + .macro _cfcmsa rd, cs .set push .set noat SET_HARDFLOAT @@ -293,7 +309,7 @@ .set pop .endm - .macro ctcmsa cd, rs + .macro _ctcmsa cd, rs .set push .set noat SET_HARDFLOAT @@ -320,44 +336,36 @@ .set pop .endm - .macro copy_u_w rd, ws, n + .macro copy_u_w ws, n .set push .set noat SET_HARDFLOAT .insn .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11) - /* move triggers an assembler bug... */ - or \rd, $1, zero .set pop .endm - .macro copy_u_d rd, ws, n + .macro copy_u_d ws, n .set push .set noat SET_HARDFLOAT .insn .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11) - /* move triggers an assembler bug... */ - or \rd, $1, zero .set pop .endm - .macro insert_w wd, n, rs + .macro insert_w wd, n .set push .set noat SET_HARDFLOAT - /* move triggers an assembler bug... */ - or $1, \rs, zero .word INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6) .set pop .endm - .macro insert_d wd, n, rs + .macro insert_d wd, n .set push .set noat SET_HARDFLOAT - /* move triggers an assembler bug... */ - or $1, \rs, zero .word INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6) .set pop .endm @@ -399,7 +407,7 @@ .set push .set noat SET_HARDFLOAT - cfcmsa $1, MSA_CSR + _cfcmsa $1, MSA_CSR sw $1, THREAD_MSA_CSR(\thread) .set pop .endm @@ -409,7 +417,7 @@ .set noat SET_HARDFLOAT lw $1, THREAD_MSA_CSR(\thread) - ctcmsa MSA_CSR, $1 + _ctcmsa MSA_CSR, $1 .set pop ld_d 0, THREAD_FPR0, \thread ld_d 1, THREAD_FPR1, \thread @@ -452,9 +460,6 @@ insert_w \wd, 2 insert_w \wd, 3 #endif - .if 31-\wd - msa_init_upper (\wd+1) - .endif .endm .macro msa_init_all_upper @@ -463,6 +468,37 @@ SET_HARDFLOAT not $1, zero msa_init_upper 0 + msa_init_upper 1 + msa_init_upper 2 + msa_init_upper 3 + msa_init_upper 4 + msa_init_upper 5 + msa_init_upper 6 + msa_init_upper 7 + msa_init_upper 8 + msa_init_upper 9 + msa_init_upper 10 + msa_init_upper 11 + msa_init_upper 12 + msa_init_upper 13 + msa_init_upper 14 + msa_init_upper 15 + msa_init_upper 16 + msa_init_upper 17 + msa_init_upper 18 + msa_init_upper 19 + msa_init_upper 20 + msa_init_upper 21 + msa_init_upper 22 + msa_init_upper 23 + msa_init_upper 24 + msa_init_upper 25 + msa_init_upper 26 + msa_init_upper 27 + msa_init_upper 28 + msa_init_upper 29 + msa_init_upper 30 + msa_init_upper 31 .set pop .endm diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 9f935f6aa996..0cf29bd5dc5c 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -481,7 +481,7 @@ static inline unsigned long __fls(unsigned long word) { int num; - if (BITS_PER_LONG == 32 && + if (BITS_PER_LONG == 32 && !__builtin_constant_p(word) && __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { __asm__( " .set push \n" @@ -494,7 +494,7 @@ static inline unsigned long __fls(unsigned long word) return 31 - num; } - if (BITS_PER_LONG == 64 && + if (BITS_PER_LONG == 64 && !__builtin_constant_p(word) && __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) { __asm__( " .set push \n" @@ -559,7 +559,8 @@ static inline int fls(int x) { int r; - if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { + if (!__builtin_constant_p(x) && + __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) { __asm__( " .set push \n" " .set "MIPS_ISA_LEVEL" \n" diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index 30939b02e3ff..6d25ad33ec78 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -122,6 +122,22 @@ static inline void bmips_write_zscm_reg(unsigned int offset, unsigned long data) barrier(); } +static inline void bmips_post_dma_flush(struct device *dev) +{ + void __iomem *cbr = BMIPS_GET_CBR(); + u32 cfg; + + if (boot_cpu_type() != CPU_BMIPS3300 && + boot_cpu_type() != CPU_BMIPS4350 && + boot_cpu_type() != CPU_BMIPS4380) + return; + + /* Flush stale data out of the readahead cache */ + cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); + __raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG); + __raw_readl(cbr + BMIPS_RAC_CONFIG); +} + #endif /* !defined(__ASSEMBLY__) */ #endif /* _ASM_BMIPS_H */ diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index e08381a37f8b..723229f4cf27 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -29,6 +29,20 @@ * - flush_icache_all() flush the entire instruction cache * - flush_data_cache_page() flushes a page from the data cache */ + + /* + * This flag is used to indicate that the page pointed to by a pte + * is dirty and requires cleaning before returning it to the user. + */ +#define PG_dcache_dirty PG_arch_1 + +#define Page_dcache_dirty(page) \ + test_bit(PG_dcache_dirty, &(page)->flags) +#define SetPageDcacheDirty(page) \ + set_bit(PG_dcache_dirty, &(page)->flags) +#define ClearPageDcacheDirty(page) \ + clear_bit(PG_dcache_dirty, &(page)->flags) + extern void (*flush_cache_all)(void); extern void (*__flush_cache_all)(void); extern void (*flush_cache_mm)(struct mm_struct *mm); @@ -37,13 +51,15 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); extern void __flush_dcache_page(struct page *page); +extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page); #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 static inline void flush_dcache_page(struct page *page) { - if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) + if (cpu_has_dc_aliases) __flush_dcache_page(page); - + else if (!cpu_has_ic_fills_f_dc) + SetPageDcacheDirty(page); } #define flush_dcache_mmap_lock(mapping) do { } while (0) @@ -61,6 +77,11 @@ static inline void flush_anon_page(struct vm_area_struct *vma, static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page) { + if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) && + Page_dcache_dirty(page)) { + __flush_icache_page(vma, page); + ClearPageDcacheDirty(page); + } } extern void (*flush_icache_range)(unsigned long start, unsigned long end); @@ -95,19 +116,6 @@ extern void (*flush_icache_all)(void); extern void (*local_flush_data_cache_page)(void * addr); extern void (*flush_data_cache_page)(unsigned long addr); -/* - * This flag is used to indicate that the page pointed to by a pte - * is dirty and requires cleaning before returning it to the user. - */ -#define PG_dcache_dirty PG_arch_1 - -#define Page_dcache_dirty(page) \ - test_bit(PG_dcache_dirty, &(page)->flags) -#define SetPageDcacheDirty(page) \ - set_bit(PG_dcache_dirty, &(page)->flags) -#define ClearPageDcacheDirty(page) \ - clear_bit(PG_dcache_dirty, &(page)->flags) - /* Run kernel code uncached, useful for cache probing functions. */ unsigned long run_uncached(void *func); diff --git a/arch/mips/include/asm/cdmm.h b/arch/mips/include/asm/cdmm.h new file mode 100644 index 000000000000..16e22ce9719f --- /dev/null +++ b/arch/mips/include/asm/cdmm.h @@ -0,0 +1,98 @@ +/* + * 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 Imagination Technologies Ltd. + */ +#ifndef __ASM_CDMM_H +#define __ASM_CDMM_H + +#include <linux/device.h> +#include <linux/mod_devicetable.h> + +/** + * struct mips_cdmm_device - Represents a single device on a CDMM bus. + * @dev: Driver model device object. + * @cpu: CPU which can access this device. + * @res: MMIO resource. + * @type: Device type identifier. + * @rev: Device revision number. + */ +struct mips_cdmm_device { + struct device dev; + unsigned int cpu; + struct resource res; + unsigned int type; + unsigned int rev; +}; + +/** + * struct mips_cdmm_driver - Represents a driver for a CDMM device. + * @drv: Driver model driver object. + * @probe Callback for probing newly discovered devices. + * @remove: Callback to remove the device. + * @shutdown: Callback on system shutdown. + * @cpu_down: Callback when the parent CPU is going down. + * Any CPU pinned threads/timers should be disabled. + * @cpu_up: Callback when the parent CPU is coming back up again. + * CPU pinned threads/timers can be restarted. + * @id_table: Table for CDMM IDs to match against. + */ +struct mips_cdmm_driver { + struct device_driver drv; + int (*probe)(struct mips_cdmm_device *); + int (*remove)(struct mips_cdmm_device *); + void (*shutdown)(struct mips_cdmm_device *); + int (*cpu_down)(struct mips_cdmm_device *); + int (*cpu_up)(struct mips_cdmm_device *); + const struct mips_cdmm_device_id *id_table; +}; + +/** + * mips_cdmm_phys_base() - Choose a physical base address for CDMM region. + * + * Picking a suitable physical address at which to map the CDMM region is + * platform specific, so this weak function can be defined by platform code to + * pick a suitable value if none is configured by the bootloader. + * + * This address must be 32kB aligned, and the region occupies a maximum of 32kB + * of physical address space which must not be used for anything else. + * + * Returns: Physical base address for CDMM region, or 0 on failure. + */ +phys_addr_t __weak mips_cdmm_phys_base(void); + +extern struct bus_type mips_cdmm_bustype; +void __iomem *mips_cdmm_early_probe(unsigned int dev_type); + +#define to_mips_cdmm_device(d) container_of(d, struct mips_cdmm_device, dev) + +#define mips_cdmm_get_drvdata(d) dev_get_drvdata(&d->dev) +#define mips_cdmm_set_drvdata(d, p) dev_set_drvdata(&d->dev, p) + +int mips_cdmm_driver_register(struct mips_cdmm_driver *); +void mips_cdmm_driver_unregister(struct mips_cdmm_driver *); + +/* + * module_mips_cdmm_driver() - Helper macro for drivers that don't do + * anything special in module init/exit. This eliminates a lot of + * boilerplate. Each module may only use this macro once, and + * calling it replaces module_init() and module_exit() + */ +#define module_mips_cdmm_driver(__mips_cdmm_driver) \ + module_driver(__mips_cdmm_driver, mips_cdmm_driver_register, \ + mips_cdmm_driver_unregister) + +/* drivers/tty/mips_ejtag_fdc.c */ + +#ifdef CONFIG_MIPS_EJTAG_FDC_EARLYCON +int setup_early_fdc_console(void); +#else +static inline int setup_early_fdc_console(void) +{ + return -ENODEV; +} +#endif + +#endif /* __ASM_CDMM_H */ diff --git a/arch/mips/include/asm/cevt-r4k.h b/arch/mips/include/asm/cevt-r4k.h index 65f9bdd02f1f..f0edf6fcd002 100644 --- a/arch/mips/include/asm/cevt-r4k.h +++ b/arch/mips/include/asm/cevt-r4k.h @@ -27,23 +27,4 @@ irqreturn_t c0_compare_interrupt(int, void *); extern struct irqaction c0_compare_irqaction; extern int cp0_timer_irq_installed; -/* - * Possibly handle a performance counter interrupt. - * Return true if the timer interrupt should not be checked - */ - -static inline int handle_perf_irq(int r2) -{ - /* - * The performance counter overflow interrupt may be shared with the - * timer interrupt (cp0_perfcount_irq < 0). If it is and a - * performance counter has overflowed (perf_irq() == IRQ_HANDLED) - * and we can't reliably determine if a counter interrupt has also - * happened (!r2) then don't check for a timer interrupt. - */ - return (cp0_perfcount_irq < 0) && - perf_irq() == IRQ_HANDLED && - !r2; -} - #endif /* __ASM_CEVT_R4K_H */ diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index 5c585c5c1c3e..3ceacde5eb6e 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -218,6 +218,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, __u32 len, unsigned short proto, __wsum sum) { + __wsum tmp; + __asm__( " .set push # csum_ipv6_magic\n" " .set noreorder \n" @@ -270,9 +272,9 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, " addu %0, $1 # Add final carry\n" " .set pop" - : "=r" (sum), "=r" (proto) + : "=&r" (sum), "=&r" (tmp) : "r" (saddr), "r" (daddr), - "0" (htonl(len)), "1" (htonl(proto)), "r" (sum)); + "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)); return csum_fold(sum); } diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index d0a2a68ca600..412f945f1f5e 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h @@ -229,21 +229,22 @@ extern void __cmpxchg_called_with_bad_pointer(void); #define cmpxchg(ptr, old, new) __cmpxchg(ptr, old, new, smp_mb__before_llsc(), smp_llsc_mb()) #define cmpxchg_local(ptr, old, new) __cmpxchg(ptr, old, new, , ) -#define cmpxchg64(ptr, o, n) \ +#ifdef CONFIG_64BIT +#define cmpxchg64_local(ptr, o, n) \ ({ \ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg((ptr), (o), (n)); \ + cmpxchg_local((ptr), (o), (n)); \ }) -#ifdef CONFIG_64BIT -#define cmpxchg64_local(ptr, o, n) \ +#define cmpxchg64(ptr, o, n) \ ({ \ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg_local((ptr), (o), (n)); \ + cmpxchg((ptr), (o), (n)); \ }) #else #include <asm-generic/cmpxchg-local.h> #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) #endif #endif /* __ASM_CMPXCHG_H */ diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 0d8208de9a3f..5aeaf19c26b0 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -68,6 +68,7 @@ #ifndef cpu_has_octeon_cache #define cpu_has_octeon_cache 0 #endif +/* Don't override `cpu_has_fpu' to 1 or the "nofpu" option won't work. */ #ifndef cpu_has_fpu #define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) #define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU) @@ -139,6 +140,9 @@ # endif #endif +#ifndef cpu_has_xpa +#define cpu_has_xpa (cpu_data[0].options & MIPS_CPU_XPA) +#endif #ifndef cpu_has_vtag_icache #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) #endif @@ -220,8 +224,11 @@ #define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r) #define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r) -#define cpu_has_mips_4_5_r2_r6 (cpu_has_mips_4_5 | cpu_has_mips_r2 | \ - cpu_has_mips_r6) +#define cpu_has_mips_3_4_5_64_r2_r6 \ + (cpu_has_mips_3 | cpu_has_mips_4_5_64_r2_r6) +#define cpu_has_mips_4_5_64_r2_r6 \ + (cpu_has_mips_4_5 | cpu_has_mips64r1 | \ + cpu_has_mips_r2 | cpu_has_mips_r6) #define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6) #define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6) @@ -235,8 +242,39 @@ /* MIPSR2 and MIPSR6 have a lot of similarities */ #define cpu_has_mips_r2_r6 (cpu_has_mips_r2 | cpu_has_mips_r6) +/* + * cpu_has_mips_r2_exec_hazard - return if IHB is required on current processor + * + * Returns non-zero value if the current processor implementation requires + * an IHB instruction to deal with an instruction hazard as per MIPS R2 + * architecture specification, zero otherwise. + */ #ifndef cpu_has_mips_r2_exec_hazard -#define cpu_has_mips_r2_exec_hazard (cpu_has_mips_r2 | cpu_has_mips_r6) +#define cpu_has_mips_r2_exec_hazard \ +({ \ + int __res; \ + \ + switch (current_cpu_type()) { \ + case CPU_M14KC: \ + case CPU_74K: \ + case CPU_1074K: \ + case CPU_PROAPTIV: \ + case CPU_P5600: \ + case CPU_M5150: \ + case CPU_QEMU_GENERIC: \ + case CPU_CAVIUM_OCTEON: \ + case CPU_CAVIUM_OCTEON_PLUS: \ + case CPU_CAVIUM_OCTEON2: \ + case CPU_CAVIUM_OCTEON3: \ + __res = 0; \ + break; \ + \ + default: \ + __res = 1; \ + } \ + \ + __res; \ +}) #endif /* @@ -366,4 +404,8 @@ # define cpu_has_fre (cpu_data[0].options & MIPS_CPU_FRE) #endif +#ifndef cpu_has_cdmm +# define cpu_has_cdmm (cpu_data[0].options & MIPS_CPU_CDMM) +#endif + #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index c3f4f2d2e108..e7dc785a91ca 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -49,6 +49,8 @@ struct cpuinfo_mips { unsigned int udelay_val; unsigned int processor_id; unsigned int fpu_id; + unsigned int fpu_csr31; + unsigned int fpu_msk31; unsigned int msa_id; unsigned int cputype; int isa_level; diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 8245875f8b33..33f3cab9e689 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -157,6 +157,7 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: #endif #ifdef CONFIG_SYS_HAS_CPU_RM7000 case CPU_RM7000: diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 15687234d70a..e3adca1d0b99 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -67,7 +67,7 @@ #define PRID_IMP_R4300 0x0b00 #define PRID_IMP_VR41XX 0x0c00 #define PRID_IMP_R12000 0x0e00 -#define PRID_IMP_R14000 0x0f00 +#define PRID_IMP_R14000 0x0f00 /* R14K && R16K */ #define PRID_IMP_R8000 0x1000 #define PRID_IMP_PR4450 0x1200 #define PRID_IMP_R4600 0x2000 @@ -284,8 +284,8 @@ enum cpu_type_enum { CPU_R4000PC, CPU_R4000SC, CPU_R4000MC, CPU_R4200, CPU_R4300, CPU_R4310, CPU_R4400PC, CPU_R4400SC, CPU_R4400MC, CPU_R4600, CPU_R4640, CPU_R4650, CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000, - CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122, - CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000, + CPU_R12000, CPU_R14000, CPU_R16000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, + CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000, CPU_SR71000, CPU_TX49XX, /* @@ -377,6 +377,8 @@ enum cpu_type_enum { #define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ #define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ #define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */ +#define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */ +#define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index 06412aa9e3fb..fd1b4a150759 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h @@ -23,7 +23,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { if (!dev->dma_mask) - return 0; + return false; return addr + size <= *dev->dma_mask; } diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 535f196ffe02..a594d8ed9698 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -11,6 +11,9 @@ #include <linux/fs.h> #include <uapi/linux/elf.h> +#include <asm/cpu-info.h> +#include <asm/current.h> + /* ELF header e_flags defines. */ /* MIPS architecture level. */ #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ @@ -294,9 +297,14 @@ do { \ if (personality(current->personality) != PER_LINUX) \ set_personality(PER_LINUX); \ \ + clear_thread_flag(TIF_HYBRID_FPREGS); \ + set_thread_flag(TIF_32BIT_FPREGS); \ + \ mips_set_personality_fp(state); \ \ current->thread.abi = &mips_abi; \ + \ + current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31; \ } while (0) #endif /* CONFIG_32BIT */ @@ -319,6 +327,8 @@ do { \ do { \ set_thread_flag(TIF_32BIT_REGS); \ set_thread_flag(TIF_32BIT_ADDR); \ + clear_thread_flag(TIF_HYBRID_FPREGS); \ + set_thread_flag(TIF_32BIT_FPREGS); \ \ mips_set_personality_fp(state); \ \ @@ -356,6 +366,8 @@ do { \ else \ current->thread.abi = &mips_abi; \ \ + current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31; \ + \ p = personality(current->personality); \ if (p != PER_LINUX32 && p != PER_LINUX) \ set_personality(PER_LINUX); \ @@ -410,10 +422,6 @@ struct linux_binprm; extern int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp); -struct mm_struct; -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - struct arch_elf_state { int fp_abi; int interp_fp_abi; diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h index dd083e999b08..084780b355aa 100644 --- a/arch/mips/include/asm/fpu.h +++ b/arch/mips/include/asm/fpu.h @@ -30,7 +30,7 @@ struct sigcontext; struct sigcontext32; -extern void _init_fpu(void); +extern void _init_fpu(unsigned int); extern void _save_fp(struct task_struct *); extern void _restore_fp(struct task_struct *); @@ -48,6 +48,12 @@ enum fpu_mode { #define FPU_FR_MASK 0x1 }; +#define __disable_fpu() \ +do { \ + clear_c0_status(ST0_CU1); \ + disable_fpu_hazard(); \ +} while (0) + static inline int __enable_fpu(enum fpu_mode mode) { int fr; @@ -86,7 +92,12 @@ fr_common: enable_fpu_hazard(); /* check FR has the desired value */ - return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE; + if (!!(read_c0_status() & ST0_FR) == !!fr) + return 0; + + /* unsupported FR value */ + __disable_fpu(); + return SIGFPE; default: BUG(); @@ -95,12 +106,6 @@ fr_common: return SIGFPE; } -#define __disable_fpu() \ -do { \ - clear_c0_status(ST0_CU1); \ - disable_fpu_hazard(); \ -} while (0) - #define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) static inline int __is_fpu_owner(void) @@ -170,6 +175,7 @@ static inline void lose_fpu(int save) } disable_msa(); clear_thread_flag(TIF_USEDMSA); + __disable_fpu(); } else if (is_fpu_owner()) { if (save) _save_fp(current); @@ -182,6 +188,7 @@ static inline void lose_fpu(int save) static inline int init_fpu(void) { + unsigned int fcr31 = current->thread.fpu.fcr31; int ret = 0; if (cpu_has_fpu) { @@ -192,7 +199,7 @@ static inline int init_fpu(void) return ret; if (!cpu_has_fre) { - _init_fpu(); + _init_fpu(fcr31); return 0; } @@ -206,7 +213,7 @@ static inline int init_fpu(void) config5 = clear_c0_config5(MIPS_CONF5_FRE); enable_fpu_hazard(); - _init_fpu(); + _init_fpu(fcr31); /* Restore FRE */ write_c0_config5(config5); diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 3ee347713307..2f021cdfba4f 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -44,6 +44,7 @@ struct mips_fpu_emulator_stats { unsigned long ieee754_overflow; unsigned long ieee754_zerodiv; unsigned long ieee754_invalidop; + unsigned long ds_emul; }; DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); @@ -65,7 +66,8 @@ extern int do_dsemulret(struct pt_regs *xcp); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr); -int process_fpemu_return(int sig, void __user *fault_addr); +int process_fpemu_return(int sig, void __user *fault_addr, + unsigned long fcr31); int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, unsigned long *contpc); @@ -86,8 +88,6 @@ static inline void fpu_emulator_init_fpu(void) struct task_struct *t = current; int i; - t->thread.fpu.fcr31 = 0; - for (i = 0; i < 32; i++) set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); } diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 5a4e1bb8fb1b..f0db99f8defe 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -47,6 +47,9 @@ extern void free_irqno(unsigned int irq); extern int cp0_compare_irq; extern int cp0_compare_irq_shift; extern int cp0_perfcount_irq; +extern int cp0_fdc_irq; + +extern int __weak get_c0_fdc_int(void); void arch_trigger_all_cpu_backtrace(bool); #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h index fdbff44e5482..608aa57799c8 100644 --- a/arch/mips/include/asm/jump_label.h +++ b/arch/mips/include/asm/jump_label.h @@ -8,9 +8,9 @@ #ifndef _ASM_MIPS_JUMP_LABEL_H #define _ASM_MIPS_JUMP_LABEL_H -#include <linux/types.h> +#ifndef __ASSEMBLY__ -#ifdef __KERNEL__ +#include <linux/types.h> #define JUMP_LABEL_NOP_SIZE 4 @@ -39,8 +39,6 @@ l_yes: return true; } -#endif /* __KERNEL__ */ - #ifdef CONFIG_64BIT typedef u64 jump_label_t; #else @@ -53,4 +51,5 @@ struct jump_entry { jump_label_t key; }; +#endif /* __ASSEMBLY__ */ #endif /* _ASM_MIPS_JUMP_LABEL_H */ diff --git a/arch/mips/include/asm/kdebug.h b/arch/mips/include/asm/kdebug.h index 6a9af5fcb5d7..cba22ab7ad4d 100644 --- a/arch/mips/include/asm/kdebug.h +++ b/arch/mips/include/asm/kdebug.h @@ -10,7 +10,8 @@ enum die_val { DIE_RI, DIE_PAGE_FAULT, DIE_BREAK, - DIE_SSTEPBP + DIE_SSTEPBP, + DIE_MSAFP }; #endif /* _ASM_MIPS_KDEBUG_H */ diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index ac4fc716062b..4c25823563fe 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -21,10 +21,10 @@ /* MIPS KVM register ids */ #define MIPS_CP0_32(_R, _S) \ - (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S))) + (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) #define MIPS_CP0_64(_R, _S) \ - (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S))) + (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) #define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0) #define KVM_REG_MIPS_CP0_ENTRYLO0 MIPS_CP0_64(2, 0) @@ -42,11 +42,14 @@ #define KVM_REG_MIPS_CP0_STATUS MIPS_CP0_32(12, 0) #define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0) #define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0) +#define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0) #define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1) #define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0) #define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1) #define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2) #define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3) +#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4) +#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5) #define KVM_REG_MIPS_CP0_CONFIG7 MIPS_CP0_32(16, 7) #define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0) #define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0) @@ -119,6 +122,10 @@ struct kvm_vcpu_stat { u32 syscall_exits; u32 resvd_inst_exits; u32 break_inst_exits; + u32 trap_inst_exits; + u32 msa_fpe_exits; + u32 fpe_exits; + u32 msa_disabled_exits; u32 flush_dcache_exits; u32 halt_successful_poll; u32 halt_wakeup; @@ -138,6 +145,10 @@ enum kvm_mips_exit_types { SYSCALL_EXITS, RESVD_INST_EXITS, BREAK_INST_EXITS, + TRAP_INST_EXITS, + MSA_FPE_EXITS, + FPE_EXITS, + MSA_DISABLED_EXITS, FLUSH_DCACHE_EXITS, MAX_KVM_MIPS_EXIT_TYPES }; @@ -206,6 +217,8 @@ struct mips_coproc { #define MIPS_CP0_CONFIG1_SEL 1 #define MIPS_CP0_CONFIG2_SEL 2 #define MIPS_CP0_CONFIG3_SEL 3 +#define MIPS_CP0_CONFIG4_SEL 4 +#define MIPS_CP0_CONFIG5_SEL 5 /* Config0 register bits */ #define CP0C0_M 31 @@ -262,31 +275,6 @@ struct mips_coproc { #define CP0C3_SM 1 #define CP0C3_TL 0 -/* Have config1, Cacheable, noncoherent, write-back, write allocate*/ -#define MIPS_CONFIG0 \ - ((1 << CP0C0_M) | (0x3 << CP0C0_K0)) - -/* Have config2, no coprocessor2 attached, no MDMX support attached, - no performance counters, watch registers present, - no code compression, EJTAG present, no FPU, no watch registers */ -#define MIPS_CONFIG1 \ -((1 << CP0C1_M) | \ - (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ - (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \ - (0 << CP0C1_FP)) - -/* Have config3, no tertiary/secondary caches implemented */ -#define MIPS_CONFIG2 \ -((1 << CP0C2_M)) - -/* No config4, no DSP ASE, no large physaddr (PABITS), - no external interrupt controller, no vectored interrupts, - no 1kb pages, no SmartMIPS ASE, no trace logic */ -#define MIPS_CONFIG3 \ -((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ - (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ - (0 << CP0C3_SM) | (0 << CP0C3_TL)) - /* MMU types, the first four entries have the same layout as the CP0C0_MT field. */ enum mips_mmu_types { @@ -321,7 +309,9 @@ enum mips_mmu_types { */ #define T_TRAP 13 /* Trap instruction */ #define T_VCEI 14 /* Virtual coherency exception */ +#define T_MSAFPE 14 /* MSA floating point exception */ #define T_FPE 15 /* Floating point exception */ +#define T_MSADIS 21 /* MSA disabled exception */ #define T_WATCH 23 /* Watch address reference */ #define T_VCED 31 /* Virtual coherency data */ @@ -374,6 +364,9 @@ struct kvm_mips_tlb { long tlb_lo1; }; +#define KVM_MIPS_FPU_FPU 0x1 +#define KVM_MIPS_FPU_MSA 0x2 + #define KVM_MIPS_GUEST_TLB_SIZE 64 struct kvm_vcpu_arch { void *host_ebase, *guest_ebase; @@ -395,6 +388,8 @@ struct kvm_vcpu_arch { /* FPU State */ struct mips_fpu_struct fpu; + /* Which FPU state is loaded (KVM_MIPS_FPU_*) */ + unsigned int fpu_inuse; /* COP0 State */ struct mips_coproc *cop0; @@ -441,6 +436,9 @@ struct kvm_vcpu_arch { /* WAIT executed */ int wait; + + u8 fpu_enabled; + u8 msa_enabled; }; @@ -482,11 +480,15 @@ struct kvm_vcpu_arch { #define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1]) #define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2]) #define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3]) +#define kvm_read_c0_guest_config4(cop0) (cop0->reg[MIPS_CP0_CONFIG][4]) +#define kvm_read_c0_guest_config5(cop0) (cop0->reg[MIPS_CP0_CONFIG][5]) #define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7]) #define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val)) #define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val)) #define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val)) #define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val)) +#define kvm_write_c0_guest_config4(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][4] = (val)) +#define kvm_write_c0_guest_config5(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][5] = (val)) #define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val)) #define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0]) #define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val)) @@ -567,6 +569,31 @@ static inline void _kvm_atomic_change_c0_guest_reg(unsigned long *reg, kvm_set_c0_guest_ebase(cop0, ((val) & (change))); \ } +/* Helpers */ + +static inline bool kvm_mips_guest_can_have_fpu(struct kvm_vcpu_arch *vcpu) +{ + return (!__builtin_constant_p(cpu_has_fpu) || cpu_has_fpu) && + vcpu->fpu_enabled; +} + +static inline bool kvm_mips_guest_has_fpu(struct kvm_vcpu_arch *vcpu) +{ + return kvm_mips_guest_can_have_fpu(vcpu) && + kvm_read_c0_guest_config1(vcpu->cop0) & MIPS_CONF1_FP; +} + +static inline bool kvm_mips_guest_can_have_msa(struct kvm_vcpu_arch *vcpu) +{ + return (!__builtin_constant_p(cpu_has_msa) || cpu_has_msa) && + vcpu->msa_enabled; +} + +static inline bool kvm_mips_guest_has_msa(struct kvm_vcpu_arch *vcpu) +{ + return kvm_mips_guest_can_have_msa(vcpu) && + kvm_read_c0_guest_config3(vcpu->cop0) & MIPS_CONF3_MSA; +} struct kvm_mips_callbacks { int (*handle_cop_unusable)(struct kvm_vcpu *vcpu); @@ -578,6 +605,10 @@ struct kvm_mips_callbacks { int (*handle_syscall)(struct kvm_vcpu *vcpu); int (*handle_res_inst)(struct kvm_vcpu *vcpu); int (*handle_break)(struct kvm_vcpu *vcpu); + int (*handle_trap)(struct kvm_vcpu *vcpu); + int (*handle_msa_fpe)(struct kvm_vcpu *vcpu); + int (*handle_fpe)(struct kvm_vcpu *vcpu); + int (*handle_msa_disabled)(struct kvm_vcpu *vcpu); int (*vm_init)(struct kvm *kvm); int (*vcpu_init)(struct kvm_vcpu *vcpu); int (*vcpu_setup)(struct kvm_vcpu *vcpu); @@ -596,6 +627,8 @@ struct kvm_mips_callbacks { const struct kvm_one_reg *reg, s64 *v); int (*set_one_reg)(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, s64 v); + int (*vcpu_get_regs)(struct kvm_vcpu *vcpu); + int (*vcpu_set_regs)(struct kvm_vcpu *vcpu); }; extern struct kvm_mips_callbacks *kvm_mips_callbacks; int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks); @@ -606,6 +639,19 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu); /* Trampoline ASM routine to start running in "Guest" context */ extern int __kvm_mips_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu); +/* FPU/MSA context management */ +void __kvm_save_fpu(struct kvm_vcpu_arch *vcpu); +void __kvm_restore_fpu(struct kvm_vcpu_arch *vcpu); +void __kvm_restore_fcsr(struct kvm_vcpu_arch *vcpu); +void __kvm_save_msa(struct kvm_vcpu_arch *vcpu); +void __kvm_restore_msa(struct kvm_vcpu_arch *vcpu); +void __kvm_restore_msa_upper(struct kvm_vcpu_arch *vcpu); +void __kvm_restore_msacsr(struct kvm_vcpu_arch *vcpu); +void kvm_own_fpu(struct kvm_vcpu *vcpu); +void kvm_own_msa(struct kvm_vcpu *vcpu); +void kvm_drop_fpu(struct kvm_vcpu *vcpu); +void kvm_lose_fpu(struct kvm_vcpu *vcpu); + /* TLB handling */ uint32_t kvm_get_kernel_asid(struct kvm_vcpu *vcpu); @@ -711,6 +757,26 @@ extern enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause, struct kvm_run *run, struct kvm_vcpu *vcpu); +extern enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_msafpe_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_msadis_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run); @@ -749,6 +815,11 @@ enum emulation_result kvm_mips_emulate_load(uint32_t inst, struct kvm_run *run, struct kvm_vcpu *vcpu); +unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu); +unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu); +unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu); +unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu); + /* Dynamic binary translation */ extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu); diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h deleted file mode 100644 index 99071e50faab..000000000000 --- a/arch/mips/include/asm/mach-ar7/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_AR7_WAR_H -#define __ASM_MIPS_MACH_AR7_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_AR7_WAR_H */ diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h index d8009c93a465..d5defdde32db 100644 --- a/arch/mips/include/asm/mach-ath25/dma-coherence.h +++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h @@ -59,16 +59,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask) return 1; } -static inline void plat_extra_sync_for_device(struct device *dev) -{ -} - -static inline int plat_dma_mapping_error(struct device *dev, - dma_addr_t dma_addr) -{ - return 0; -} - static inline int plat_device_is_coherent(struct device *dev) { #ifdef CONFIG_DMA_COHERENT @@ -79,4 +69,8 @@ static inline int plat_device_is_coherent(struct device *dev) #endif } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + #endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/include/asm/mach-ath25/war.h deleted file mode 100644 index e3a5250ebd67..000000000000 --- a/arch/mips/include/asm/mach-ath25/war.h +++ /dev/null @@ -1,25 +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) 2008 Felix Fietkau <nbd@openwrt.org> - */ -#ifndef __ASM_MACH_ATH25_WAR_H -#define __ASM_MACH_ATH25_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define RM9000_CDEX_SMP_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MACH_ATH25_WAR_H */ diff --git a/arch/mips/include/asm/mach-ath79/war.h b/arch/mips/include/asm/mach-ath79/war.h deleted file mode 100644 index 0bb30905fd5b..000000000000 --- a/arch/mips/include/asm/mach-ath79/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MACH_ATH79_WAR_H -#define __ASM_MACH_ATH79_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MACH_ATH79_WAR_H */ diff --git a/arch/mips/include/asm/mach-au1x00/war.h b/arch/mips/include/asm/mach-au1x00/war.h deleted file mode 100644 index 72e260d24e59..000000000000 --- a/arch/mips/include/asm/mach-au1x00/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_AU1X00_WAR_H -#define __ASM_MIPS_MACH_AU1X00_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_AU1X00_WAR_H */ diff --git a/arch/mips/include/asm/mach-bcm3384/war.h b/arch/mips/include/asm/mach-bcm3384/war.h deleted file mode 100644 index 59d7599059b0..000000000000 --- a/arch/mips/include/asm/mach-bcm3384/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_BCM3384_WAR_H -#define __ASM_MIPS_MACH_BCM3384_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_BCM3384_WAR_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index 7527c1d33d02..8ed77f618940 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -22,6 +22,7 @@ #include <linux/ssb/ssb.h> #include <linux/bcma/bcma.h> #include <linux/bcma/bcma_soc.h> +#include <linux/bcm47xx_nvram.h> enum bcm47xx_bus_type { #ifdef CONFIG_BCM47XX_SSB diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h index 1f5643b89a91..c41d1dce1062 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h @@ -67,6 +67,7 @@ enum bcm47xx_board { BCM47XX_BOARD_LINKSYS_WRT150NV11, BCM47XX_BOARD_LINKSYS_WRT160NV1, BCM47XX_BOARD_LINKSYS_WRT160NV3, + BCM47XX_BOARD_LINKSYS_WRT300N_V1, BCM47XX_BOARD_LINKSYS_WRT300NV11, BCM47XX_BOARD_LINKSYS_WRT310NV1, BCM47XX_BOARD_LINKSYS_WRT310NV2, @@ -74,6 +75,7 @@ enum bcm47xx_board { BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, + BCM47XX_BOARD_LINKSYS_WRT600N_V11, BCM47XX_BOARD_LINKSYS_WRT610NV1, BCM47XX_BOARD_LINKSYS_WRT610NV2, BCM47XX_BOARD_LINKSYS_WRTSL54GS, @@ -86,9 +88,11 @@ enum bcm47xx_board { BCM47XX_BOARD_NETGEAR_WGR614V8, BCM47XX_BOARD_NETGEAR_WGR614V9, + BCM47XX_BOARD_NETGEAR_WGR614_V10, BCM47XX_BOARD_NETGEAR_WNDR3300, BCM47XX_BOARD_NETGEAR_WNDR3400V1, BCM47XX_BOARD_NETGEAR_WNDR3400V2, + BCM47XX_BOARD_NETGEAR_WNDR3400_V3, BCM47XX_BOARD_NETGEAR_WNDR3400VCNA, BCM47XX_BOARD_NETGEAR_WNDR3700V3, BCM47XX_BOARD_NETGEAR_WNDR4000, diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h deleted file mode 100644 index ee59ffe99922..000000000000 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2005, Broadcom Corporation - * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __BCM47XX_NVRAM_H -#define __BCM47XX_NVRAM_H - -#include <linux/types.h> -#include <linux/kernel.h> - -int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); -int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); -int bcm47xx_nvram_gpio_pin(const char *name); - -#endif /* __BCM47XX_NVRAM_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/war.h b/arch/mips/include/asm/mach-bcm47xx/war.h deleted file mode 100644 index a3d2f448b10e..000000000000 --- a/arch/mips/include/asm/mach-bcm47xx/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_BCM47XX_WAR_H -#define __ASM_MIPS_MACH_BCM47XX_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_BCM47XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 4794067cb5a7..5035f09c5427 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -1259,20 +1259,6 @@ #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18) /************************************************************************* - * _REG relative to RSET_RNG - *************************************************************************/ - -#define RNG_CTRL 0x00 -#define RNG_EN (1 << 0) - -#define RNG_STAT 0x04 -#define RNG_AVAIL_MASK (0xff000000) - -#define RNG_DATA 0x08 -#define RNG_THRES 0x0c -#define RNG_MASK 0x10 - -/************************************************************************* * _REG relative to RSET_SPI *************************************************************************/ diff --git a/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h b/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h new file mode 100644 index 000000000000..11d3b572b1b3 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h @@ -0,0 +1,10 @@ +#ifndef __ASM_MACH_BCM63XX_DMA_COHERENCE_H +#define __ASM_MACH_BCM63XX_DMA_COHERENCE_H + +#include <asm/bmips.h> + +#define plat_post_dma_flush bmips_post_dma_flush + +#include <asm/mach-generic/dma-coherence.h> + +#endif /* __ASM_MACH_BCM63XX_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/war.h b/arch/mips/include/asm/mach-bcm63xx/war.h deleted file mode 100644 index 05ee8671bef1..000000000000 --- a/arch/mips/include/asm/mach-bcm63xx/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_BCM63XX_WAR_H -#define __ASM_MIPS_MACH_BCM63XX_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_BCM63XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-bcm3384/dma-coherence.h b/arch/mips/include/asm/mach-bmips/dma-coherence.h index a3be8e50e1f0..d29781f02285 100644 --- a/arch/mips/include/asm/mach-bcm3384/dma-coherence.h +++ b/arch/mips/include/asm/mach-bmips/dma-coherence.h @@ -12,8 +12,12 @@ * GNU General Public License for more details. */ -#ifndef __ASM_MACH_BCM3384_DMA_COHERENCE_H -#define __ASM_MACH_BCM3384_DMA_COHERENCE_H +#ifndef __ASM_MACH_BMIPS_DMA_COHERENCE_H +#define __ASM_MACH_BMIPS_DMA_COHERENCE_H + +#include <asm/bmips.h> +#include <asm/cpu-type.h> +#include <asm/cpu.h> struct device; @@ -45,4 +49,6 @@ static inline int plat_device_is_coherent(struct device *dev) return 0; } -#endif /* __ASM_MACH_BCM3384_DMA_COHERENCE_H */ +#define plat_post_dma_flush bmips_post_dma_flush + +#endif /* __ASM_MACH_BMIPS_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-bmips/spaces.h b/arch/mips/include/asm/mach-bmips/spaces.h new file mode 100644 index 000000000000..1b05bddc8ec5 --- /dev/null +++ b/arch/mips/include/asm/mach-bmips/spaces.h @@ -0,0 +1,18 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_BMIPS_SPACES_H +#define _ASM_BMIPS_SPACES_H + +/* Avoid collisions with system base register (SBR) region on BMIPS3300 */ +#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_BMIPS_SPACES_H */ diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index fa1f3cfbae8d..d68e685cde60 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -50,7 +50,6 @@ #define cpu_has_mips32r2 0 #define cpu_has_mips64r1 0 #define cpu_has_mips64r2 1 -#define cpu_has_mips_r2_exec_hazard 0 #define cpu_has_dsp 0 #define cpu_has_dsp2 0 #define cpu_has_mipsmt 0 diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h index f9f448650505..460042ee5d6f 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h +++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h @@ -57,6 +57,10 @@ static inline int plat_device_is_coherent(struct device *dev) return 1; } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr); phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr); diff --git a/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h b/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h new file mode 100644 index 000000000000..374eefafb320 --- /dev/null +++ b/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h @@ -0,0 +1,74 @@ +/* + * 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) 2003, 2004 Ralf Baechle + */ +#ifndef __ASM_MACH_GENERIC_MANGLE_PORT_H +#define __ASM_MACH_GENERIC_MANGLE_PORT_H + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + +# define __swizzle_addr_b(port) (port) +# define __swizzle_addr_w(port) (port) +# define __swizzle_addr_l(port) (port) +# define __swizzle_addr_q(port) (port) + +#else /* __LITTLE_ENDIAN */ + +static inline bool __should_swizzle_addr(unsigned long p) +{ + /* boot bus? */ + return ((p >> 40) & 0xff) == 0; +} + +# define __swizzle_addr_b(port) \ + (__should_swizzle_addr(port) ? (port) ^ 7 : (port)) +# define __swizzle_addr_w(port) \ + (__should_swizzle_addr(port) ? (port) ^ 6 : (port)) +# define __swizzle_addr_l(port) \ + (__should_swizzle_addr(port) ? (port) ^ 4 : (port)) +# define __swizzle_addr_q(port) (port) + +#endif /* __BIG_ENDIAN */ + +/* + * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware; + * less sane hardware forces software to fiddle with this... + * + * Regardless, if the host bus endianness mismatches that of PCI/ISA, then + * you can't have the numerical value of data and byte addresses within + * multibyte quantities both preserved at the same time. Hence two + * variations of functions: non-prefixed ones that preserve the value + * and prefixed ones that preserve byte addresses. The latters are + * typically used for moving raw data between a peripheral and memory (cf. + * string I/O functions), hence the "__mem_" prefix. + */ +#if defined(CONFIG_SWAP_IO_SPACE) + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) le16_to_cpu(x) +# define __mem_ioswabw(a, x) (x) +# define ioswabl(a, x) le32_to_cpu(x) +# define __mem_ioswabl(a, x) (x) +# define ioswabq(a, x) le64_to_cpu(x) +# define __mem_ioswabq(a, x) (x) + +#else + +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) (x) +# define __mem_ioswabw(a, x) cpu_to_le16(x) +# define ioswabl(a, x) (x) +# define __mem_ioswabl(a, x) cpu_to_le32(x) +# define ioswabq(a, x) (x) +# define __mem_ioswabq(a, x) cpu_to_le32(x) + +#endif + +#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */ diff --git a/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h index 71d4bface1dc..30c5cd9fd973 100644 --- a/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h @@ -14,7 +14,6 @@ #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 #define cpu_has_tx39_cache 0 -#define cpu_has_fpu 1 #define cpu_has_32fpr 1 #define cpu_has_counter 1 #define cpu_has_watch 0 diff --git a/arch/mips/include/asm/mach-cobalt/war.h b/arch/mips/include/asm/mach-cobalt/war.h deleted file mode 100644 index 34ae4046541e..000000000000 --- a/arch/mips/include/asm/mach-cobalt/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_COBALT_WAR_H -#define __ASM_MIPS_MACH_COBALT_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_COBALT_WAR_H */ diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h index acce27fd2bb8..bdf045fb00c8 100644 --- a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h @@ -15,7 +15,6 @@ /* Generic ones first. */ #define cpu_has_tlb 1 #define cpu_has_tx39_cache 0 -#define cpu_has_fpu 1 #define cpu_has_divec 0 #define cpu_has_prefetch 0 #define cpu_has_mcheck 0 diff --git a/arch/mips/include/asm/mach-dec/war.h b/arch/mips/include/asm/mach-dec/war.h deleted file mode 100644 index d29996feb3e7..000000000000 --- a/arch/mips/include/asm/mach-dec/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_DEC_WAR_H -#define __ASM_MIPS_MACH_DEC_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_DEC_WAR_H */ diff --git a/arch/mips/include/asm/mach-emma2rh/war.h b/arch/mips/include/asm/mach-emma2rh/war.h deleted file mode 100644 index 79ae82da3ec7..000000000000 --- a/arch/mips/include/asm/mach-emma2rh/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_EMMA2RH_WAR_H -#define __ASM_MIPS_MACH_EMMA2RH_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_EMMA2RH_WAR_H */ diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h index 7629c35986f7..0f8a354fd468 100644 --- a/arch/mips/include/asm/mach-generic/dma-coherence.h +++ b/arch/mips/include/asm/mach-generic/dma-coherence.h @@ -52,6 +52,12 @@ static inline int plat_device_is_coherent(struct device *dev) return coherentio; } +#ifndef plat_post_dma_flush +static inline void plat_post_dma_flush(struct device *dev) +{ +} +#endif + #ifdef CONFIG_SWIOTLB static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-generic/war.h index c074b5dc1f82..a1bc2e71f983 100644 --- a/arch/mips/include/asm/mach-ralink/war.h +++ b/arch/mips/include/asm/mach-generic/war.h @@ -5,8 +5,8 @@ * * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> */ -#ifndef __ASM_MACH_RALINK_WAR_H -#define __ASM_MACH_RALINK_WAR_H +#ifndef __ASM_MACH_GENERIC_WAR_H +#define __ASM_MACH_GENERIC_WAR_H #define R4600_V1_INDEX_ICACHEOP_WAR 0 #define R4600_V1_HIT_CACHEOP_WAR 0 @@ -21,4 +21,4 @@ #define R10000_LLSC_WAR 0 #define MIPS34K_MISSED_ITLB_WAR 0 -#endif /* __ASM_MACH_RALINK_WAR_H */ +#endif /* __ASM_MACH_GENERIC_WAR_H */ diff --git a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h index 1dfe47453ea4..9b19b72dba56 100644 --- a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h @@ -16,7 +16,6 @@ #define cpu_has_tlb 1 #define cpu_has_4kex 1 #define cpu_has_4k_cache 1 -#define cpu_has_fpu 1 #define cpu_has_32fpr 1 #define cpu_has_counter 1 #define cpu_has_mips16 0 diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h index 4ffddfdb5062..1daa64412569 100644 --- a/arch/mips/include/asm/mach-ip27/dma-coherence.h +++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h @@ -58,6 +58,10 @@ static inline int plat_dma_supported(struct device *dev, u64 mask) return 1; } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + static inline int plat_device_is_coherent(struct device *dev) { return 1; /* IP27 non-cohernet mode is unsupported */ diff --git a/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h index 2e1ec6cfedd5..241409b78ff1 100644 --- a/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h @@ -26,7 +26,6 @@ /* Settings which are common for all ip32 CPUs */ #define cpu_has_tlb 1 #define cpu_has_4kex 1 -#define cpu_has_fpu 1 #define cpu_has_32fpr 1 #define cpu_has_counter 1 #define cpu_has_mips16 0 diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h index 104cfbc3ed63..0a0b0e2ced60 100644 --- a/arch/mips/include/asm/mach-ip32/dma-coherence.h +++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h @@ -80,6 +80,10 @@ static inline int plat_dma_supported(struct device *dev, u64 mask) return 1; } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + static inline int plat_device_is_coherent(struct device *dev) { return 0; /* IP32 is non-cohernet */ diff --git a/arch/mips/include/asm/mach-ip32/mc146818rtc.h b/arch/mips/include/asm/mach-ip32/mc146818rtc.h deleted file mode 100644 index 6b6bab43d5c1..000000000000 --- a/arch/mips/include/asm/mach-ip32/mc146818rtc.h +++ /dev/null @@ -1,36 +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) 1998, 2001, 03 by Ralf Baechle - * Copyright (C) 2000 Harald Koerfgen - * - * RTC routines for IP32 style attached Dallas chip. - */ -#ifndef __ASM_MACH_IP32_MC146818RTC_H -#define __ASM_MACH_IP32_MC146818RTC_H - -#include <asm/ip32/mace.h> - -#define RTC_PORT(x) (0x70 + (x)) - -static unsigned char CMOS_READ(unsigned long addr) -{ - return mace->isa.rtc[addr << 8]; -} - -static inline void CMOS_WRITE(unsigned char data, unsigned long addr) -{ - mace->isa.rtc[addr << 8] = data; -} - -/* - * FIXME: Do it right. For now just assume that no one lives in 20th century - * and no O2 user in 22th century ;-) - */ -#define mc146818_decode_year(year) ((year) + 2000) - -#define RTC_ALWAYS_BCD 0 - -#endif /* __ASM_MACH_IP32_MC146818RTC_H */ diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h index 949003ef97b3..dc347c25c343 100644 --- a/arch/mips/include/asm/mach-jazz/dma-coherence.h +++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h @@ -48,6 +48,10 @@ static inline int plat_dma_supported(struct device *dev, u64 mask) return 1; } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + static inline int plat_device_is_coherent(struct device *dev) { return 0; diff --git a/arch/mips/include/asm/mach-jazz/war.h b/arch/mips/include/asm/mach-jazz/war.h deleted file mode 100644 index 5b18b9a3d0ec..000000000000 --- a/arch/mips/include/asm/mach-jazz/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_JAZZ_WAR_H -#define __ASM_MIPS_MACH_JAZZ_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_JAZZ_WAR_H */ diff --git a/arch/mips/include/asm/mach-jz4740/war.h b/arch/mips/include/asm/mach-jz4740/war.h deleted file mode 100644 index 9b511d323838..000000000000 --- a/arch/mips/include/asm/mach-jz4740/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_JZ4740_WAR_H -#define __ASM_MIPS_MACH_JZ4740_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_JZ4740_WAR_H */ diff --git a/arch/mips/include/asm/mach-lantiq/war.h b/arch/mips/include/asm/mach-lantiq/war.h deleted file mode 100644 index 358ca979c1bd..000000000000 --- a/arch/mips/include/asm/mach-lantiq/war.h +++ /dev/null @@ -1,23 +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. - * - */ -#ifndef __ASM_MIPS_MACH_LANTIQ_WAR_H -#define __ASM_MIPS_MACH_LANTIQ_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif diff --git a/arch/mips/include/asm/mach-lasat/war.h b/arch/mips/include/asm/mach-lasat/war.h deleted file mode 100644 index 741ae724adc6..000000000000 --- a/arch/mips/include/asm/mach-lasat/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_LASAT_WAR_H -#define __ASM_MIPS_MACH_LASAT_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_LASAT_WAR_H */ diff --git a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h index 6d69332f21ec..acc376897e46 100644 --- a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h @@ -34,7 +34,6 @@ #define cpu_has_dsp 0 #define cpu_has_dsp2 0 #define cpu_has_ejtag 0 -#define cpu_has_fpu 1 #define cpu_has_ic_fills_f_dc 0 #define cpu_has_inclusive_pcaches 1 #define cpu_has_llsc 1 diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h index a90534161bd2..4bf4e19f72e8 100644 --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h @@ -78,4 +78,8 @@ static inline int plat_device_is_coherent(struct device *dev) #endif /* CONFIG_DMA_NONCOHERENT */ } +static inline void plat_post_dma_flush(struct device *dev) +{ +} + #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 5459ac09679f..9783103fd6f6 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -255,6 +255,10 @@ static inline void do_perfcnt_IRQ(void) extern u64 loongson_chipcfg[MAX_PACKAGES]; #define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id])) +/* Chip Temperature registor of each physical cpu package, PRid >= Loongson-3A */ +extern u64 loongson_chiptemp[MAX_PACKAGES]; +#define LOONGSON_CHIPTEMP(id) (*(volatile u32 *)(loongson_chiptemp[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])) diff --git a/arch/mips/include/asm/mach-loongson/war.h b/arch/mips/include/asm/mach-loongson/war.h deleted file mode 100644 index f2570df66bb5..000000000000 --- a/arch/mips/include/asm/mach-loongson/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MACH_LOONGSON_WAR_H -#define __ASM_MACH_LOONGSON_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MACH_LEMOTE_WAR_H */ diff --git a/arch/mips/include/asm/mach-loongson1/war.h b/arch/mips/include/asm/mach-loongson1/war.h deleted file mode 100644 index 8fb50d008131..000000000000 --- a/arch/mips/include/asm/mach-loongson1/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MACH_LOONGSON1_WAR_H -#define __ASM_MACH_LOONGSON1_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MACH_LOONGSON1_WAR_H */ diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h index 9ed8dacdc37c..8bdf47e29145 100644 --- a/arch/mips/include/asm/mach-netlogic/multi-node.h +++ b/arch/mips/include/asm/mach-netlogic/multi-node.h @@ -48,15 +48,6 @@ #endif #define NLM_THREADS_PER_CORE 4 -#ifdef CONFIG_CPU_XLR -#define nlm_cores_per_node() 8 -#else -extern unsigned int xlp_cores_per_node; -#define nlm_cores_per_node() xlp_cores_per_node -#endif - -#define nlm_threads_per_node() (nlm_cores_per_node() * NLM_THREADS_PER_CORE) -#define nlm_cpuid_to_node(c) ((c) / nlm_threads_per_node()) struct nlm_soc_info { unsigned long coremask; /* cores enabled on the soc */ diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h deleted file mode 100644 index 0eb43c832b25..000000000000 --- a/arch/mips/include/asm/mach-netlogic/topology.h +++ /dev/null @@ -1,15 +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) 2013 Broadcom Corporation - */ -#ifndef _ASM_MACH_NETLOGIC_TOPOLOGY_H -#define _ASM_MACH_NETLOGIC_TOPOLOGY_H - -#include <asm/mach-netlogic/multi-node.h> - -#include <asm-generic/topology.h> - -#endif /* _ASM_MACH_NETLOGIC_TOPOLOGY_H */ diff --git a/arch/mips/include/asm/mach-netlogic/war.h b/arch/mips/include/asm/mach-netlogic/war.h deleted file mode 100644 index 2c7216840e18..000000000000 --- a/arch/mips/include/asm/mach-netlogic/war.h +++ /dev/null @@ -1,25 +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) 2011 Netlogic Microsystems. - * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_NLM_WAR_H -#define __ASM_MIPS_MACH_NLM_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_NLM_WAR_H */ diff --git a/arch/mips/include/asm/mach-paravirt/war.h b/arch/mips/include/asm/mach-paravirt/war.h deleted file mode 100644 index 36d3afb98451..000000000000 --- a/arch/mips/include/asm/mach-paravirt/war.h +++ /dev/null @@ -1,25 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - * Copyright (C) 2013 Cavium Networks <support@caviumnetworks.com> - */ -#ifndef __ASM_MIPS_MACH_PARAVIRT_WAR_H -#define __ASM_MIPS_MACH_PARAVIRT_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_PARAVIRT_WAR_H */ diff --git a/arch/mips/include/asm/mach-pistachio/gpio.h b/arch/mips/include/asm/mach-pistachio/gpio.h new file mode 100644 index 000000000000..6c1649c27b8d --- /dev/null +++ b/arch/mips/include/asm/mach-pistachio/gpio.h @@ -0,0 +1,21 @@ +/* + * Pistachio IRQ setup + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_PISTACHIO_GPIO_H +#define __ASM_MACH_PISTACHIO_GPIO_H + +#include <asm-generic/gpio.h> + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +#endif /* __ASM_MACH_PISTACHIO_GPIO_H */ diff --git a/arch/mips/include/asm/mach-pistachio/irq.h b/arch/mips/include/asm/mach-pistachio/irq.h new file mode 100644 index 000000000000..b94a09a54221 --- /dev/null +++ b/arch/mips/include/asm/mach-pistachio/irq.h @@ -0,0 +1,18 @@ +/* + * Pistachio IRQ setup + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_PISTACHIO_IRQ_H +#define __ASM_MACH_PISTACHIO_IRQ_H + +#define NR_IRQS 256 + +#include_next <irq.h> + +#endif /* __ASM_MACH_PISTACHIO_IRQ_H */ diff --git a/arch/mips/include/asm/mach-pnx833x/war.h b/arch/mips/include/asm/mach-pnx833x/war.h deleted file mode 100644 index e410df4e1b3a..000000000000 --- a/arch/mips/include/asm/mach-pnx833x/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_PNX833X_WAR_H -#define __ASM_MIPS_MACH_PNX833X_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_PNX833X_WAR_H */ diff --git a/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h index f095c529c48c..98cf40417c5d 100644 --- a/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h @@ -15,7 +15,6 @@ #define cpu_has_tlb 1 #define cpu_has_4kex 1 #define cpu_has_4k_cache 1 -#define cpu_has_fpu 1 #define cpu_has_32fpr 1 #define cpu_has_counter 1 #define cpu_has_watch 0 diff --git a/arch/mips/include/asm/mach-tx39xx/war.h b/arch/mips/include/asm/mach-tx39xx/war.h deleted file mode 100644 index 6a52e6534776..000000000000 --- a/arch/mips/include/asm/mach-tx39xx/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_TX39XX_WAR_H -#define __ASM_MIPS_MACH_TX39XX_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_TX39XX_WAR_H */ diff --git a/arch/mips/include/asm/mach-vr41xx/war.h b/arch/mips/include/asm/mach-vr41xx/war.h deleted file mode 100644 index ffe31e736009..000000000000 --- a/arch/mips/include/asm/mach-vr41xx/war.h +++ /dev/null @@ -1,24 +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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> - */ -#ifndef __ASM_MIPS_MACH_VR41XX_WAR_H -#define __ASM_MIPS_MACH_VR41XX_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_VR41XX_WAR_H */ diff --git a/arch/mips/include/asm/mips-boards/sead3-addr.h b/arch/mips/include/asm/mips-boards/sead3-addr.h new file mode 100644 index 000000000000..c0db57802f7c --- /dev/null +++ b/arch/mips/include/asm/mips-boards/sead3-addr.h @@ -0,0 +1,83 @@ +/* + * 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) 2015 Imagination Technologies, Inc. + * written by Ralf Baechle <ralf@linux-mips.org> + */ +#ifndef __ASM_MIPS_BOARDS_SEAD3_ADDR_H +#define __ASM_MIPS_BOARDS_SEAD3_ADDR_H + +/* + * Target #0 Register Decode + */ +#define SEAD3_SD_SPDCNF 0xbb000040 +#define SEAD3_SD_SPADDR 0xbb000048 +#define SEAD3_SD_DATA 0xbb000050 + +/* + * Target #1 Register Decode + */ +#define SEAD3_CFG 0xbb100110 +#define SEAD3_GIC_BASE_ADDRESS 0xbb1c0000 +#define SEAD3_SHARED_SECTION 0xbb1c0000 +#define SEAD3_VPE_LOCAL_SECTION 0xbb1c8000 +#define SEAD3_VPE_OTHER_SECTION 0xbb1cc000 +#define SEAD3_USER_MODE_VISIBLE_SECTION 0xbb1d0000 + +/* + * Target #3 Register Decode + */ +#define SEAD3_USB_HS_BASE 0xbb200000 +#define SEAD3_USB_HS_IDENTIFICATION_REGS 0xbb200000 +#define SEAD3_USB_HS_CAPABILITY_REGS 0xbb200100 +#define SEAD3_USB_HS_OPERATIONAL_REGS 0xbb200140 +#define SEAD3_RESERVED 0xbe800000 + +/* + * Target #3 Register Decode + */ +#define SEAD3_SRAM 0xbe000000 +#define SEAD3_OPTIONAL_SRAM 0xbe400000 +#define SEAD3_FPGA 0xbf000000 + +#define SEAD3_PI_PIC32_USB_STATUS 0xbf000060 +#define SEAD3_PI_PIC32_USB_STATUS_IO_RDY (1 << 0) +#define SEAD3_PI_PIC32_USB_STATUS_SPL_INT (1 << 1) +#define SEAD3_PI_PIC32_USB_STATUS_GPIOA_INT (1 << 2) +#define SEAD3_PI_PIC32_USB_STATUS_GPIOB_INT (1 << 3) + +#define SEAD3_PI_SOFT_ENDIAN 0xbf000070 + +#define SEAD3_CPLD_P_SWITCH 0xbf000200 +#define SEAD3_CPLD_F_SWITCH 0xbf000208 +#define SEAD3_CPLD_P_LED 0xbf000210 +#define SEAD3_CPLD_F_LED 0xbf000218 +#define SEAD3_NEWSC_LIVE 0xbf000220 +#define SEAD3_NEWSC_REG 0xbf000228 +#define SEAD3_NEWSC_CTRL 0xbf000230 + +#define SEAD3_LCD_CONTROL 0xbf000400 +#define SEAD3_LCD_DATA 0xbf000408 +#define SEAD3_CPLD_LCD_STATUS 0xbf000410 +#define SEAD3_CPLD_LCD_DATA 0xbf000418 + +#define SEAD3_CPLD_PI_DEVRST 0xbf000480 +#define SEAD3_CPLD_PI_DEVRST_IC32_RST (1 << 0) +#define SEAD3_RESERVED_0 0xbf000500 + +#define SEAD3_PIC32_REGISTERS 0xbf000600 +#define SEAD3_RESERVED_1 0xbf000700 +#define SEAD3_UART_CH_0 0xbf000800 +#define SEAD3_UART_CH_1 0xbf000900 +#define SEAD3_RESERVED_2 0xbf000a00 +#define SEAD3_ETHERNET 0xbf010000 +#define SEAD3_RESERVED_3 0xbf020000 +#define SEAD3_USER_EXPANSION 0xbf400000 +#define SEAD3_RESERVED_4 0xbf800000 +#define SEAD3_BOOT_FLASH_EXTENSION 0xbfa00000 +#define SEAD3_BOOT_FLASH 0xbfc00000 +#define SEAD3_REVISION_REGISTER 0xbfc00010 + +#endif /* __ASM_MIPS_BOARDS_SEAD3_ADDR_H */ diff --git a/arch/mips/include/asm/mips-r2-to-r6-emul.h b/arch/mips/include/asm/mips-r2-to-r6-emul.h index 60570f2c3ba2..4b89f28047f7 100644 --- a/arch/mips/include/asm/mips-r2-to-r6-emul.h +++ b/arch/mips/include/asm/mips-r2-to-r6-emul.h @@ -84,11 +84,16 @@ extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR static int mipsr2_emulation; -static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; }; +static inline int mipsr2_decoder(struct pt_regs *regs, u32 inst, + unsigned long *fcr31) +{ + return 0; +}; #else /* MIPS R2 Emulator ON/OFF */ extern int mipsr2_emulation; -extern int mipsr2_decoder(struct pt_regs *regs, u32 inst); +extern int mipsr2_decoder(struct pt_regs *regs, u32 inst, + unsigned long *fcr31); #endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */ #define NO_R6EMU (cpu_has_mips_r6 && !mipsr2_emulation) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index fef004434096..764e2756b54d 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -111,70 +111,6 @@ */ #define CP0_TX39_CACHE $7 -/* - * Coprocessor 1 (FPU) register names - */ -#define CP1_REVISION $0 -#define CP1_STATUS $31 - -/* - * FPU Status Register Values - */ -/* - * Status Register Values - */ - -#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ -#define FPU_CSR_COND 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ -#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ -#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ -#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ -#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ -#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ -#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ - -/* - * Bits 18 - 20 of the FPU Status Register will be read as 0, - * and should be written as zero. - */ -#define FPU_CSR_RSVD 0x001c0000 - -/* - * X the exception cause indicator - * E the exception enable - * S the sticky/flag bit -*/ -#define FPU_CSR_ALL_X 0x0003f000 -#define FPU_CSR_UNI_X 0x00020000 -#define FPU_CSR_INV_X 0x00010000 -#define FPU_CSR_DIV_X 0x00008000 -#define FPU_CSR_OVF_X 0x00004000 -#define FPU_CSR_UDF_X 0x00002000 -#define FPU_CSR_INE_X 0x00001000 - -#define FPU_CSR_ALL_E 0x00000f80 -#define FPU_CSR_INV_E 0x00000800 -#define FPU_CSR_DIV_E 0x00000400 -#define FPU_CSR_OVF_E 0x00000200 -#define FPU_CSR_UDF_E 0x00000100 -#define FPU_CSR_INE_E 0x00000080 - -#define FPU_CSR_ALL_S 0x0000007c -#define FPU_CSR_INV_S 0x00000040 -#define FPU_CSR_DIV_S 0x00000020 -#define FPU_CSR_OVF_S 0x00000010 -#define FPU_CSR_UDF_S 0x00000008 -#define FPU_CSR_INE_S 0x00000004 - -/* Bits 0 and 1 of FPU Status Register specify the rounding mode */ -#define FPU_CSR_RM 0x00000003 -#define FPU_CSR_RN 0x0 /* nearest */ -#define FPU_CSR_RZ 0x1 /* towards zero */ -#define FPU_CSR_RU 0x2 /* towards +Infinity */ -#define FPU_CSR_RD 0x3 /* towards -Infinity */ - /* * Values for PageMask register @@ -341,39 +277,6 @@ #define ST0_MX 0x01000000 /* - * Bitfields in the TX39 family CP0 Configuration Register 3 - */ -#define TX39_CONF_ICS_SHIFT 19 -#define TX39_CONF_ICS_MASK 0x00380000 -#define TX39_CONF_ICS_1KB 0x00000000 -#define TX39_CONF_ICS_2KB 0x00080000 -#define TX39_CONF_ICS_4KB 0x00100000 -#define TX39_CONF_ICS_8KB 0x00180000 -#define TX39_CONF_ICS_16KB 0x00200000 - -#define TX39_CONF_DCS_SHIFT 16 -#define TX39_CONF_DCS_MASK 0x00070000 -#define TX39_CONF_DCS_1KB 0x00000000 -#define TX39_CONF_DCS_2KB 0x00010000 -#define TX39_CONF_DCS_4KB 0x00020000 -#define TX39_CONF_DCS_8KB 0x00030000 -#define TX39_CONF_DCS_16KB 0x00040000 - -#define TX39_CONF_CWFON 0x00004000 -#define TX39_CONF_WBON 0x00002000 -#define TX39_CONF_RF_SHIFT 10 -#define TX39_CONF_RF_MASK 0x00000c00 -#define TX39_CONF_DOZE 0x00000200 -#define TX39_CONF_HALT 0x00000100 -#define TX39_CONF_LOCK 0x00000080 -#define TX39_CONF_ICE 0x00000020 -#define TX39_CONF_DCE 0x00000010 -#define TX39_CONF_IRSIZE_SHIFT 2 -#define TX39_CONF_IRSIZE_MASK 0x0000000c -#define TX39_CONF_DRSIZE_SHIFT 0 -#define TX39_CONF_DRSIZE_MASK 0x00000003 - -/* * Status register bits available in all MIPS CPUs. */ #define ST0_IM 0x0000ff00 @@ -425,9 +328,9 @@ /* * Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2) - * - * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. */ +#define INTCTLB_IPFDC 23 +#define INTCTLF_IPFDC (_ULCAST_(7) << INTCTLB_IPFDC) #define INTCTLB_IPPCI 26 #define INTCTLF_IPPCI (_ULCAST_(7) << INTCTLB_IPPCI) #define INTCTLB_IPTI 29 @@ -438,10 +341,10 @@ * * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. */ -#define CAUSEB_EXCCODE 2 -#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) -#define CAUSEB_IP 8 -#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) #define CAUSEB_IP0 8 #define CAUSEF_IP0 (_ULCAST_(1) << 8) #define CAUSEB_IP1 9 @@ -458,16 +361,18 @@ #define CAUSEF_IP6 (_ULCAST_(1) << 14) #define CAUSEB_IP7 15 #define CAUSEF_IP7 (_ULCAST_(1) << 15) -#define CAUSEB_IV 23 -#define CAUSEF_IV (_ULCAST_(1) << 23) -#define CAUSEB_PCI 26 -#define CAUSEF_PCI (_ULCAST_(1) << 26) -#define CAUSEB_CE 28 -#define CAUSEF_CE (_ULCAST_(3) << 28) -#define CAUSEB_TI 30 -#define CAUSEF_TI (_ULCAST_(1) << 30) -#define CAUSEB_BD 31 -#define CAUSEF_BD (_ULCAST_(1) << 31) +#define CAUSEB_FDCI 21 +#define CAUSEF_FDCI (_ULCAST_(1) << 21) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_PCI 26 +#define CAUSEF_PCI (_ULCAST_(1) << 26) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_TI 30 +#define CAUSEF_TI (_ULCAST_(1) << 30) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) /* * Bits in the coprocessor 0 config register. @@ -689,18 +594,6 @@ #define MIPS_CMGCRF_BASE (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1)) /* - * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. - */ -#define MIPS_FPIR_S (_ULCAST_(1) << 16) -#define MIPS_FPIR_D (_ULCAST_(1) << 17) -#define MIPS_FPIR_PS (_ULCAST_(1) << 18) -#define MIPS_FPIR_3D (_ULCAST_(1) << 19) -#define MIPS_FPIR_W (_ULCAST_(1) << 20) -#define MIPS_FPIR_L (_ULCAST_(1) << 21) -#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) -#define MIPS_FPIR_FREP (_ULCAST_(1) << 29) - -/* * Bits in the MIPS32 Memory Segmentation registers. */ #define MIPS_SEGCFG_PA_SHIFT 9 @@ -751,6 +644,172 @@ #define MIPS_PWCTL_PSN_SHIFT 0 #define MIPS_PWCTL_PSN_MASK 0x0000003f +/* CDMMBase register bit definitions */ +#define MIPS_CDMMBASE_SIZE_SHIFT 0 +#define MIPS_CDMMBASE_SIZE (_ULCAST_(511) << MIPS_CDMMBASE_SIZE_SHIFT) +#define MIPS_CDMMBASE_CI (_ULCAST_(1) << 9) +#define MIPS_CDMMBASE_EN (_ULCAST_(1) << 10) +#define MIPS_CDMMBASE_ADDR_SHIFT 11 +#define MIPS_CDMMBASE_ADDR_START 15 + +/* + * Bitfields in the TX39 family CP0 Configuration Register 3 + */ +#define TX39_CONF_ICS_SHIFT 19 +#define TX39_CONF_ICS_MASK 0x00380000 +#define TX39_CONF_ICS_1KB 0x00000000 +#define TX39_CONF_ICS_2KB 0x00080000 +#define TX39_CONF_ICS_4KB 0x00100000 +#define TX39_CONF_ICS_8KB 0x00180000 +#define TX39_CONF_ICS_16KB 0x00200000 + +#define TX39_CONF_DCS_SHIFT 16 +#define TX39_CONF_DCS_MASK 0x00070000 +#define TX39_CONF_DCS_1KB 0x00000000 +#define TX39_CONF_DCS_2KB 0x00010000 +#define TX39_CONF_DCS_4KB 0x00020000 +#define TX39_CONF_DCS_8KB 0x00030000 +#define TX39_CONF_DCS_16KB 0x00040000 + +#define TX39_CONF_CWFON 0x00004000 +#define TX39_CONF_WBON 0x00002000 +#define TX39_CONF_RF_SHIFT 10 +#define TX39_CONF_RF_MASK 0x00000c00 +#define TX39_CONF_DOZE 0x00000200 +#define TX39_CONF_HALT 0x00000100 +#define TX39_CONF_LOCK 0x00000080 +#define TX39_CONF_ICE 0x00000020 +#define TX39_CONF_DCE 0x00000010 +#define TX39_CONF_IRSIZE_SHIFT 2 +#define TX39_CONF_IRSIZE_MASK 0x0000000c +#define TX39_CONF_DRSIZE_SHIFT 0 +#define TX39_CONF_DRSIZE_MASK 0x00000003 + + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_UFR $1 +#define CP1_UNFR $4 +#define CP1_FCCR $25 +#define CP1_FEXR $26 +#define CP1_FENR $28 +#define CP1_STATUS $31 + + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. + */ +#define MIPS_FPIR_S (_ULCAST_(1) << 16) +#define MIPS_FPIR_D (_ULCAST_(1) << 17) +#define MIPS_FPIR_PS (_ULCAST_(1) << 18) +#define MIPS_FPIR_3D (_ULCAST_(1) << 19) +#define MIPS_FPIR_W (_ULCAST_(1) << 20) +#define MIPS_FPIR_L (_ULCAST_(1) << 21) +#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) +#define MIPS_FPIR_HAS2008 (_ULCAST_(1) << 23) +#define MIPS_FPIR_UFRP (_ULCAST_(1) << 28) +#define MIPS_FPIR_FREP (_ULCAST_(1) << 29) + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) condition codes register. + */ +#define MIPS_FCCR_CONDX_S 0 +#define MIPS_FCCR_CONDX (_ULCAST_(255) << MIPS_FCCR_CONDX_S) +#define MIPS_FCCR_COND0_S 0 +#define MIPS_FCCR_COND0 (_ULCAST_(1) << MIPS_FCCR_COND0_S) +#define MIPS_FCCR_COND1_S 1 +#define MIPS_FCCR_COND1 (_ULCAST_(1) << MIPS_FCCR_COND1_S) +#define MIPS_FCCR_COND2_S 2 +#define MIPS_FCCR_COND2 (_ULCAST_(1) << MIPS_FCCR_COND2_S) +#define MIPS_FCCR_COND3_S 3 +#define MIPS_FCCR_COND3 (_ULCAST_(1) << MIPS_FCCR_COND3_S) +#define MIPS_FCCR_COND4_S 4 +#define MIPS_FCCR_COND4 (_ULCAST_(1) << MIPS_FCCR_COND4_S) +#define MIPS_FCCR_COND5_S 5 +#define MIPS_FCCR_COND5 (_ULCAST_(1) << MIPS_FCCR_COND5_S) +#define MIPS_FCCR_COND6_S 6 +#define MIPS_FCCR_COND6 (_ULCAST_(1) << MIPS_FCCR_COND6_S) +#define MIPS_FCCR_COND7_S 7 +#define MIPS_FCCR_COND7 (_ULCAST_(1) << MIPS_FCCR_COND7_S) + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) enables register. + */ +#define MIPS_FENR_FS_S 2 +#define MIPS_FENR_FS (_ULCAST_(1) << MIPS_FENR_FS_S) + +/* + * FPU Status Register Values + */ +#define FPU_CSR_COND_S 23 /* $fcc0 */ +#define FPU_CSR_COND (_ULCAST_(1) << FPU_CSR_COND_S) + +#define FPU_CSR_FS_S 24 /* flush denormalised results to 0 */ +#define FPU_CSR_FS (_ULCAST_(1) << FPU_CSR_FS_S) + +#define FPU_CSR_CONDX_S 25 /* $fcc[7:1] */ +#define FPU_CSR_CONDX (_ULCAST_(127) << FPU_CSR_CONDX_S) +#define FPU_CSR_COND1_S 25 /* $fcc1 */ +#define FPU_CSR_COND1 (_ULCAST_(1) << FPU_CSR_COND1_S) +#define FPU_CSR_COND2_S 26 /* $fcc2 */ +#define FPU_CSR_COND2 (_ULCAST_(1) << FPU_CSR_COND2_S) +#define FPU_CSR_COND3_S 27 /* $fcc3 */ +#define FPU_CSR_COND3 (_ULCAST_(1) << FPU_CSR_COND3_S) +#define FPU_CSR_COND4_S 28 /* $fcc4 */ +#define FPU_CSR_COND4 (_ULCAST_(1) << FPU_CSR_COND4_S) +#define FPU_CSR_COND5_S 29 /* $fcc5 */ +#define FPU_CSR_COND5 (_ULCAST_(1) << FPU_CSR_COND5_S) +#define FPU_CSR_COND6_S 30 /* $fcc6 */ +#define FPU_CSR_COND6 (_ULCAST_(1) << FPU_CSR_COND6_S) +#define FPU_CSR_COND7_S 31 /* $fcc7 */ +#define FPU_CSR_COND7 (_ULCAST_(1) << FPU_CSR_COND7_S) + +/* + * Bits 22:20 of the FPU Status Register will be read as 0, + * and should be written as zero. + */ +#define FPU_CSR_RSVD (_ULCAST_(7) << 20) + +#define FPU_CSR_ABS2008 (_ULCAST_(1) << 19) +#define FPU_CSR_NAN2008 (_ULCAST_(1) << 18) + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* Bits 0 and 1 of FPU Status Register specify the rounding mode */ +#define FPU_CSR_RM 0x00000003 +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + + #ifndef __ASSEMBLY__ /* @@ -1282,6 +1341,9 @@ do { \ #define read_c0_ebase() __read_32bit_c0_register($15, 1) #define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) +#define read_c0_cdmmbase() __read_ulong_c0_register($15, 2) +#define write_c0_cdmmbase(val) __write_ulong_c0_register($15, 2, val) + /* MIPSR3 */ #define read_c0_segctl0() __read_32bit_c0_register($5, 2) #define write_c0_segctl0(val) __write_32bit_c0_register($5, 2, val) diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index c281f03eb312..2a4c128277e4 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -111,6 +111,25 @@ static inline int nlm_irq_to_xirq(int node, int irq) return node * NR_IRQS / NLM_NR_NODES + irq; } -extern int nlm_cpu_ready[]; +#ifdef CONFIG_CPU_XLR +#define nlm_cores_per_node() 8 +#else +static inline int nlm_cores_per_node(void) +{ + return ((read_c0_prid() & PRID_IMP_MASK) + == PRID_IMP_NETLOGIC_XLP9XX) ? 32 : 8; +} #endif +static inline int nlm_threads_per_node(void) +{ + return nlm_cores_per_node() * NLM_THREADS_PER_CORE; +} + +static inline int nlm_hwtid_to_node(int hwtid) +{ + return hwtid / nlm_threads_per_node(); +} + +extern int nlm_cpu_ready[]; +#endif /* __ASSEMBLY__ */ #endif /* _NETLOGIC_COMMON_H_ */ diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index 06f1f75bfa9b..788baf399e69 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -157,7 +157,13 @@ static inline int nlm_nodeid(void) static inline unsigned int nlm_core_id(void) { - return (read_c0_ebase() & 0x1c) >> 2; + uint32_t prid = read_c0_prid() & PRID_IMP_MASK; + + if ((prid == PRID_IMP_NETLOGIC_XLP9XX) || + (prid == PRID_IMP_NETLOGIC_XLP5XX)) + return (read_c0_ebase() & 0x7c) >> 2; + else + return (read_c0_ebase() & 0x1c) >> 2; } static inline unsigned int nlm_thread_id(void) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h index 6d2e58a9a542..a06b59292153 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h @@ -46,6 +46,8 @@ #define CPU_BLOCKID_FPU 9 #define CPU_BLOCKID_MAP 10 +#define IFU_BRUB_RESERVE 0x007 + #define ICU_DEFEATURE 0x100 #define LSU_DEFEATURE 0x304 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h index bc7bddf25be9..6bcf3952e556 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h @@ -177,6 +177,9 @@ #define SYS_9XX_CLK_DEV_DIV 0x18d #define SYS_9XX_CLK_DEV_CHG 0x18f +#define SYS_9XX_CLK_DEV_SEL_REG 0x1a4 +#define SYS_9XX_CLK_DEV_DIV_REG 0x1a6 + /* Registers changed on 9XX */ #define SYS_9XX_POWER_ON_RESET_CFG 0x00 #define SYS_9XX_CHIP_RESET 0x01 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index a862b93223cc..feb6ed807ec6 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -52,6 +52,7 @@ #define PIC_2XX_XHCI_2_IRQ 25 #define PIC_9XX_XHCI_0_IRQ 23 #define PIC_9XX_XHCI_1_IRQ 24 +#define PIC_9XX_XHCI_2_IRQ 25 #define PIC_MMC_IRQ 29 #define PIC_I2C_0_IRQ 30 @@ -89,7 +90,7 @@ void xlp_wakeup_secondary_cpus(void); void xlp_mmu_init(void); void nlm_hal_init(void); -int xlp_get_dram_map(int n, uint64_t *dram_map); +int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries); struct pci_dev; int xlp_socdev_to_node(const struct pci_dev *dev); diff --git a/arch/mips/include/asm/octeon/cvmx-address.h b/arch/mips/include/asm/octeon/cvmx-address.h index e2d874e681f6..e4444f8c4a61 100644 --- a/arch/mips/include/asm/octeon/cvmx-address.h +++ b/arch/mips/include/asm/octeon/cvmx-address.h @@ -104,6 +104,7 @@ typedef enum { typedef union { uint64_t u64; +#ifdef __BIG_ENDIAN_BITFIELD /* mapped or unmapped virtual address */ struct { uint64_t R:2; @@ -202,6 +203,72 @@ typedef union { uint64_t didspace:24; uint64_t unused:40; } sfilldidspace; +#else + struct { + uint64_t offset:62; + uint64_t R:2; + } sva; + + struct { + uint64_t offset:31; + uint64_t zeroes:33; + } suseg; + + struct { + uint64_t offset:29; + uint64_t sp:2; + uint64_t ones:33; + } sxkseg; + + struct { + uint64_t pa:49; + uint64_t mbz:10; + uint64_t cca:3; + uint64_t R:2; + } sxkphys; + + struct { + uint64_t offset:36; + uint64_t unaddr:4; + uint64_t did:8; + uint64_t is_io:1; + uint64_t mbz:15; + } sphys; + + struct { + uint64_t offset:36; + uint64_t unaddr:4; + uint64_t zeroes:24; + } smem; + + struct { + uint64_t offset:36; + uint64_t unaddr:4; + uint64_t did:8; + uint64_t is_io:1; + uint64_t mbz:13; + uint64_t mem_region:2; + } sio; + + struct { + uint64_t addr:13; + cvmx_add_win_dec_t csrdec:2; + uint64_t ones:49; + } sscr; + + struct { + uint64_t addr:7; + uint64_t type:3; + uint64_t unused2:3; + uint64_t csrdec:2; + uint64_t ones:49; + } sdma; + + struct { + uint64_t unused:40; + uint64_t didspace:24; + } sfilldidspace; +#endif } cvmx_addr_t; diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index 2298199a287e..c373d95b5e2c 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -53,6 +53,7 @@ * to 0. */ struct cvmx_bootinfo { +#ifdef __BIG_ENDIAN_BITFIELD uint32_t major_version; uint32_t minor_version; @@ -123,6 +124,60 @@ struct cvmx_bootinfo { */ uint64_t fdt_addr; #endif +#else /* __BIG_ENDIAN */ + /* + * Little-Endian: When the CPU mode is switched to + * little-endian, the view of the structure has some of the + * fields swapped. + */ + uint32_t minor_version; + uint32_t major_version; + + uint64_t stack_top; + uint64_t heap_base; + uint64_t heap_end; + uint64_t desc_vaddr; + + uint32_t stack_size; + uint32_t exception_base_addr; + + uint32_t core_mask; + uint32_t flags; + + uint32_t phy_mem_desc_addr; + uint32_t dram_size; + + uint32_t eclock_hz; + uint32_t debugger_flags_base_addr; + + uint32_t reserved0; + uint32_t dclock_hz; + + uint8_t reserved3; + uint8_t reserved2; + uint16_t reserved1; + uint8_t board_rev_minor; + uint8_t board_rev_major; + uint16_t board_type; + + char board_serial_number[CVMX_BOOTINFO_OCTEON_SERIAL_LEN]; + uint8_t mac_addr_base[6]; + uint8_t mac_addr_count; + uint8_t pad[5]; + +#if (CVMX_BOOTINFO_MIN_VER >= 1) + uint64_t compact_flash_common_base_addr; + uint64_t compact_flash_attribute_base_addr; + uint64_t led_display_base_addr; +#endif +#if (CVMX_BOOTINFO_MIN_VER >= 2) + uint32_t config_flags; + uint32_t dfa_ref_clock_hz; +#endif +#if (CVMX_BOOTINFO_MIN_VER >= 3) + uint64_t fdt_addr; +#endif +#endif }; #define CVMX_BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h index 352f1dc2508b..374562507d0b 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootmem.h +++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h @@ -95,6 +95,7 @@ struct cvmx_bootmem_named_block_desc { * positions for backwards compatibility. */ struct cvmx_bootmem_desc { +#if defined(__BIG_ENDIAN_BITFIELD) || defined(CVMX_BUILD_FOR_LINUX_HOST) /* spinlock to control access to list */ uint32_t lock; /* flags for indicating various conditions */ @@ -120,7 +121,20 @@ struct cvmx_bootmem_desc { uint32_t named_block_name_len; /* address of named memory block descriptors */ uint64_t named_block_array_addr; +#else /* __LITTLE_ENDIAN */ + uint32_t flags; + uint32_t lock; + uint64_t head_addr; + uint32_t minor_version; + uint32_t major_version; + uint64_t app_data_addr; + uint64_t app_data_size; + + uint32_t named_block_name_len; + uint32_t named_block_num_blocks; + uint64_t named_block_array_addr; +#endif }; /** diff --git a/arch/mips/include/asm/octeon/cvmx-fau.h b/arch/mips/include/asm/octeon/cvmx-fau.h index ef98f7fc102f..dafeae300c97 100644 --- a/arch/mips/include/asm/octeon/cvmx-fau.h +++ b/arch/mips/include/asm/octeon/cvmx-fau.h @@ -105,6 +105,16 @@ typedef union { } s; } cvmx_fau_async_tagwait_result_t; +#ifdef __BIG_ENDIAN_BITFIELD +#define SWIZZLE_8 0 +#define SWIZZLE_16 0 +#define SWIZZLE_32 0 +#else +#define SWIZZLE_8 0x7 +#define SWIZZLE_16 0x6 +#define SWIZZLE_32 0x4 +#endif + /** * Builds a store I/O address for writing to the FAU * @@ -175,6 +185,7 @@ static inline int64_t cvmx_fau_fetch_and_add64(cvmx_fau_reg_64_t reg, static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, int32_t value) { + reg ^= SWIZZLE_32; return cvmx_read64_int32(__cvmx_fau_atomic_address(0, reg, value)); } @@ -189,6 +200,7 @@ static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg, static inline int16_t cvmx_fau_fetch_and_add16(cvmx_fau_reg_16_t reg, int16_t value) { + reg ^= SWIZZLE_16; return cvmx_read64_int16(__cvmx_fau_atomic_address(0, reg, value)); } @@ -201,6 +213,7 @@ static inline int16_t cvmx_fau_fetch_and_add16(cvmx_fau_reg_16_t reg, */ static inline int8_t cvmx_fau_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) { + reg ^= SWIZZLE_8; return cvmx_read64_int8(__cvmx_fau_atomic_address(0, reg, value)); } @@ -247,6 +260,7 @@ cvmx_fau_tagwait_fetch_and_add32(cvmx_fau_reg_32_t reg, int32_t value) uint64_t i32; cvmx_fau_tagwait32_t t; } result; + reg ^= SWIZZLE_32; result.i32 = cvmx_read64_int32(__cvmx_fau_atomic_address(1, reg, value)); return result.t; @@ -270,6 +284,7 @@ cvmx_fau_tagwait_fetch_and_add16(cvmx_fau_reg_16_t reg, int16_t value) uint64_t i16; cvmx_fau_tagwait16_t t; } result; + reg ^= SWIZZLE_16; result.i16 = cvmx_read64_int16(__cvmx_fau_atomic_address(1, reg, value)); return result.t; @@ -292,6 +307,7 @@ cvmx_fau_tagwait_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value) uint64_t i8; cvmx_fau_tagwait8_t t; } result; + reg ^= SWIZZLE_8; result.i8 = cvmx_read64_int8(__cvmx_fau_atomic_address(1, reg, value)); return result.t; } @@ -521,6 +537,7 @@ static inline void cvmx_fau_atomic_add64(cvmx_fau_reg_64_t reg, int64_t value) */ static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) { + reg ^= SWIZZLE_32; cvmx_write64_int32(__cvmx_fau_store_address(0, reg), value); } @@ -533,6 +550,7 @@ static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value) */ static inline void cvmx_fau_atomic_add16(cvmx_fau_reg_16_t reg, int16_t value) { + reg ^= SWIZZLE_16; cvmx_write64_int16(__cvmx_fau_store_address(0, reg), value); } @@ -544,6 +562,7 @@ static inline void cvmx_fau_atomic_add16(cvmx_fau_reg_16_t reg, int16_t value) */ static inline void cvmx_fau_atomic_add8(cvmx_fau_reg_8_t reg, int8_t value) { + reg ^= SWIZZLE_8; cvmx_write64_int8(__cvmx_fau_store_address(0, reg), value); } @@ -568,6 +587,7 @@ static inline void cvmx_fau_atomic_write64(cvmx_fau_reg_64_t reg, int64_t value) */ static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) { + reg ^= SWIZZLE_32; cvmx_write64_int32(__cvmx_fau_store_address(1, reg), value); } @@ -580,6 +600,7 @@ static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value) */ static inline void cvmx_fau_atomic_write16(cvmx_fau_reg_16_t reg, int16_t value) { + reg ^= SWIZZLE_16; cvmx_write64_int16(__cvmx_fau_store_address(1, reg), value); } @@ -591,6 +612,7 @@ static inline void cvmx_fau_atomic_write16(cvmx_fau_reg_16_t reg, int16_t value) */ static inline void cvmx_fau_atomic_write8(cvmx_fau_reg_8_t reg, int8_t value) { + reg ^= SWIZZLE_8; cvmx_write64_int8(__cvmx_fau_store_address(1, reg), value); } diff --git a/arch/mips/include/asm/octeon/cvmx-fpa.h b/arch/mips/include/asm/octeon/cvmx-fpa.h index aa26a2ce5a0e..c00501d0f7ae 100644 --- a/arch/mips/include/asm/octeon/cvmx-fpa.h +++ b/arch/mips/include/asm/octeon/cvmx-fpa.h @@ -49,6 +49,7 @@ typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * the (64-bit word) location in scratchpad to write * to (if len != 0) @@ -63,6 +64,12 @@ typedef union { * the NCB bus. */ uint64_t addr:40; +#else + uint64_t addr:40; + uint64_t did:8; + uint64_t len:8; + uint64_t scraddr:8; +#endif } s; } cvmx_fpa_iobdma_data_t; diff --git a/arch/mips/include/asm/octeon/cvmx-l2c.h b/arch/mips/include/asm/octeon/cvmx-l2c.h index 11c0a8fa8eb5..ddb429210a0e 100644 --- a/arch/mips/include/asm/octeon/cvmx-l2c.h +++ b/arch/mips/include/asm/octeon/cvmx-l2c.h @@ -53,12 +53,21 @@ union cvmx_l2c_tag { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved:28; uint64_t V:1; /* Line valid */ uint64_t D:1; /* Line dirty */ uint64_t L:1; /* Line locked */ uint64_t U:1; /* Use, LRU eviction */ uint64_t addr:32; /* Phys mem (not all bits valid) */ +#else + uint64_t addr:32; /* Phys mem (not all bits valid) */ + uint64_t U:1; /* Use, LRU eviction */ + uint64_t L:1; /* Line locked */ + uint64_t D:1; /* Line dirty */ + uint64_t V:1; /* Line valid */ + uint64_t reserved:28; +#endif } s; }; diff --git a/arch/mips/include/asm/octeon/cvmx-packet.h b/arch/mips/include/asm/octeon/cvmx-packet.h index 38aefa1bab9d..895e93d682c2 100644 --- a/arch/mips/include/asm/octeon/cvmx-packet.h +++ b/arch/mips/include/asm/octeon/cvmx-packet.h @@ -39,6 +39,7 @@ union cvmx_buf_ptr { void *ptr; uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* if set, invert the "free" pick of the overall * packet. HW always sets this bit to 0 on inbound * packet */ @@ -55,6 +56,13 @@ union cvmx_buf_ptr { uint64_t size:16; /* Pointer to the first byte of the data, NOT buffer */ uint64_t addr:40; +#else + uint64_t addr:40; + uint64_t size:16; + uint64_t pool:3; + uint64_t back:4; + uint64_t i:1; +#endif } s; }; diff --git a/arch/mips/include/asm/octeon/cvmx-pko.h b/arch/mips/include/asm/octeon/cvmx-pko.h index f7d2a6718849..3da59bb8ce24 100644 --- a/arch/mips/include/asm/octeon/cvmx-pko.h +++ b/arch/mips/include/asm/octeon/cvmx-pko.h @@ -127,6 +127,7 @@ typedef struct { typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Must CVMX_IO_SEG */ uint64_t mem_space:2; /* Must be zero */ @@ -151,6 +152,17 @@ typedef union { uint64_t queue:9; /* Must be zero */ uint64_t reserved4:3; +#else + uint64_t reserved4:3; + uint64_t queue:9; + uint64_t port:9; + uint64_t reserved3:15; + uint64_t reserved2:4; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved:13; + uint64_t mem_space:2; +#endif } s; } cvmx_pko_doorbell_address_t; @@ -160,6 +172,7 @@ typedef union { typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * The size of the reg1 operation - could be 8, 16, * 32, or 64 bits. @@ -229,6 +242,24 @@ typedef union { uint64_t segs:6; /* Including L2, but no trailing CRC */ uint64_t total_bytes:16; +#else + uint64_t total_bytes:16; + uint64_t segs:6; + uint64_t dontfree:1; + uint64_t ignore_i:1; + uint64_t ipoffp1:7; + uint64_t gather:1; + uint64_t rsp:1; + uint64_t wqp:1; + uint64_t n2:1; + uint64_t le:1; + uint64_t reg0:11; + uint64_t subone0:1; + uint64_t reg1:11; + uint64_t subone1:1; + uint64_t size0:2; + uint64_t size1:2; +#endif } s; } cvmx_pko_command_word0_t; diff --git a/arch/mips/include/asm/octeon/cvmx-pow.h b/arch/mips/include/asm/octeon/cvmx-pow.h index 2188e65afb86..d5565d758ddd 100644 --- a/arch/mips/include/asm/octeon/cvmx-pow.h +++ b/arch/mips/include/asm/octeon/cvmx-pow.h @@ -178,6 +178,7 @@ typedef enum { typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * Don't reschedule this entry. no_sched is used for * CVMX_POW_TAG_OP_SWTAG_DESCH and @@ -217,6 +218,17 @@ typedef union { * CVMX_POW_TAG_OP_*_NSCHED */ uint64_t tag:32; +#else + uint64_t tag:32; + uint64_t type:3; + uint64_t grp:4; + uint64_t qos:3; + uint64_t unused2:2; + cvmx_pow_tag_op_t op:4; + uint64_t index:13; + uint64_t unused:2; + uint64_t no_sched:1; +#endif } s; } cvmx_pow_tag_req_t; @@ -230,6 +242,7 @@ typedef union { * Address for new work request loads (did<2:0> == 0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Mips64 address region. Should be CVMX_IO_SEG */ uint64_t mem_region:2; /* Must be zero */ @@ -247,12 +260,22 @@ typedef union { uint64_t wait:1; /* Must be zero */ uint64_t reserved_0_2:3; +#else + uint64_t reserved_0_2:3; + uint64_t wait:1; + uint64_t reserved_4_39:36; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_region:2; +#endif } swork; /** * Address for loads to get POW internal status */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Mips64 address region. Should be CVMX_IO_SEG */ uint64_t mem_region:2; /* Must be zero */ @@ -282,12 +305,25 @@ typedef union { uint64_t get_wqp:1; /* Must be zero */ uint64_t reserved_0_2:3; +#else + uint64_t reserved_0_2:3; + uint64_t get_wqp:1; + uint64_t get_cur:1; + uint64_t get_rev:1; + uint64_t coreid:4; + uint64_t reserved_10_39:30; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_region:2; +#endif } sstatus; /** * Address for memory loads to get POW internal state */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Mips64 address region. Should be CVMX_IO_SEG */ uint64_t mem_region:2; /* Must be zero */ @@ -314,12 +350,24 @@ typedef union { uint64_t get_wqp:1; /* Must be zero */ uint64_t reserved_0_2:3; +#else + uint64_t reserved_0_2:3; + uint64_t get_wqp:1; + uint64_t get_des:1; + uint64_t index:11; + uint64_t reserved_16_39:24; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_region:2; +#endif } smemload; /** * Address for index/pointer loads */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Mips64 address region. Should be CVMX_IO_SEG */ uint64_t mem_region:2; /* Must be zero */ @@ -366,6 +414,17 @@ typedef union { uint64_t get_rmt:1; /* Must be zero */ uint64_t reserved_0_2:3; +#else + uint64_t reserved_0_2:3; + uint64_t get_rmt:1; + uint64_t get_des_get_tail:1; + uint64_t qosgrp:4; + uint64_t reserved_9_39:31; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_region:2; +#endif } sindexload; /** @@ -377,6 +436,7 @@ typedef union { * available.) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Mips64 address region. Should be CVMX_IO_SEG */ uint64_t mem_region:2; /* Must be zero */ @@ -387,6 +447,13 @@ typedef union { uint64_t did:8; /* Must be zero */ uint64_t reserved_0_39:40; +#else + uint64_t reserved_0_39:40; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_region:2; +#endif } snull_rd; } cvmx_pow_load_addr_t; @@ -401,6 +468,7 @@ typedef union { * Response to new work request loads */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * Set when no new work queue entry was returned. * * If there was de-scheduled work, the HW will @@ -419,12 +487,18 @@ typedef union { uint64_t reserved_40_62:23; /* 36 in O1 -- the work queue pointer */ uint64_t addr:40; +#else + uint64_t addr:40; + uint64_t reserved_40_62:23; + uint64_t no_work:1; +#endif } s_work; /** * Result for a POW Status Load (when get_cur==0 and get_wqp==0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* Set when there is a pending non-NULL SWTAG or * SWTAG_FULL, and the POW entry has not left the list @@ -476,12 +550,32 @@ typedef union { * AND pend_desched_switch) are set. */ uint64_t pend_tag:32; +#else + uint64_t pend_tag:32; + uint64_t pend_type:2; + uint64_t reserved_34_35:2; + uint64_t pend_grp:4; + uint64_t pend_index:11; + uint64_t reserved_51:1; + uint64_t pend_nosched_clr:1; + uint64_t pend_null_rd:1; + uint64_t pend_new_work_wait:1; + uint64_t pend_new_work:1; + uint64_t pend_nosched:1; + uint64_t pend_desched_switch:1; + uint64_t pend_desched:1; + uint64_t pend_switch_null:1; + uint64_t pend_switch_full:1; + uint64_t pend_switch:1; + uint64_t reserved_62_63:2; +#endif } s_sstatus0; /** * Result for a POW Status Load (when get_cur==0 and get_wqp==1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* * Set when there is a pending non-NULL SWTAG or @@ -529,6 +623,23 @@ typedef union { uint64_t pend_grp:4; /* This is the wqp when pend_nosched_clr is set. */ uint64_t pend_wqp:36; +#else + uint64_t pend_wqp:36; + uint64_t pend_grp:4; + uint64_t pend_index:11; + uint64_t reserved_51:1; + uint64_t pend_nosched_clr:1; + uint64_t pend_null_rd:1; + uint64_t pend_new_work_wait:1; + uint64_t pend_new_work:1; + uint64_t pend_nosched:1; + uint64_t pend_desched_switch:1; + uint64_t pend_desched:1; + uint64_t pend_switch_null:1; + uint64_t pend_switch_full:1; + uint64_t pend_switch:1; + uint64_t reserved_62_63:2; +#endif } s_sstatus1; /** @@ -536,6 +647,7 @@ typedef union { * get_rev==0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* * Points to the next POW entry in the tag list when @@ -573,12 +685,23 @@ typedef union { * SWTAG_DESCHED). */ uint64_t tag:32; +#else + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t tail:1; + uint64_t head:1; + uint64_t grp:4; + uint64_t index:11; + uint64_t link_index:11; + uint64_t reserved_62_63:2; +#endif } s_sstatus2; /** * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* * Points to the prior POW entry in the tag list when @@ -617,6 +740,16 @@ typedef union { * SWTAG_DESCHED). */ uint64_t tag:32; +#else + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t tail:1; + uint64_t head:1; + uint64_t grp:4; + uint64_t index:11; + uint64_t revlink_index:11; + uint64_t reserved_62_63:2; +#endif } s_sstatus3; /** @@ -624,6 +757,7 @@ typedef union { * get_rev==0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* * Points to the next POW entry in the tag list when @@ -642,6 +776,13 @@ typedef union { * list entered on SWTAG_FULL). */ uint64_t wqp:36; +#else + uint64_t wqp:36; + uint64_t grp:4; + uint64_t index:11; + uint64_t link_index:11; + uint64_t reserved_62_63:2; +#endif } s_sstatus4; /** @@ -649,6 +790,7 @@ typedef union { * get_rev==1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_62_63:2; /* * Points to the prior POW entry in the tag list when @@ -669,12 +811,20 @@ typedef union { * list entered on SWTAG_FULL). */ uint64_t wqp:36; +#else + uint64_t wqp:36; + uint64_t grp:4; + uint64_t index:11; + uint64_t revlink_index:11; + uint64_t reserved_62_63:2; +#endif } s_sstatus5; /** * Result For POW Memory Load (get_des == 0 and get_wqp == 0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_51_63:13; /* * The next entry in the input, free, descheduled_head @@ -695,12 +845,22 @@ typedef union { uint64_t tag_type:2; /* The tag of the POW entry. */ uint64_t tag:32; +#else + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t tail:1; + uint64_t reserved_35:1; + uint64_t grp:4; + uint64_t next_index:11; + uint64_t reserved_51_63:13; +#endif } s_smemload0; /** * Result For POW Memory Load (get_des == 0 and get_wqp == 1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_51_63:13; /* * The next entry in the input, free, descheduled_head @@ -712,12 +872,19 @@ typedef union { uint64_t grp:4; /* The WQP held in the POW entry. */ uint64_t wqp:36; +#else + uint64_t wqp:36; + uint64_t grp:4; + uint64_t next_index:11; + uint64_t reserved_51_63:13; +#endif } s_smemload1; /** * Result For POW Memory Load (get_des == 1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_51_63:13; /* * The next entry in the tag list connected to the @@ -740,12 +907,22 @@ typedef union { * is set. */ uint64_t pend_tag:32; +#else + uint64_t pend_tag:32; + uint64_t pend_type:2; + uint64_t pend_switch:1; + uint64_t nosched:1; + uint64_t grp:4; + uint64_t fwd_index:11; + uint64_t reserved_51_63:13; +#endif } s_smemload2; /** * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_52_63:12; /* * set when there is one or more POW entries on the @@ -791,12 +968,28 @@ typedef union { * the input Q list selected by qosgrp. */ uint64_t loc_tail:11; +#else + uint64_t loc_tail:11; + uint64_t reserved_11:1; + uint64_t loc_head:11; + uint64_t reserved_23:1; + uint64_t loc_one:1; + uint64_t loc_val:1; + uint64_t free_tail:11; + uint64_t reserved_37:1; + uint64_t free_head:11; + uint64_t reserved_49:1; + uint64_t free_one:1; + uint64_t free_val:1; + uint64_t reserved_52_63:12; +#endif } sindexload0; /** * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_52_63:12; /* * set when there is one or more POW entries on the @@ -843,12 +1036,28 @@ typedef union { * head on the descheduled list selected by qosgrp. */ uint64_t des_tail:11; +#else + uint64_t des_tail:11; + uint64_t reserved_11:1; + uint64_t des_head:11; + uint64_t reserved_23:1; + uint64_t des_one:1; + uint64_t des_val:1; + uint64_t nosched_tail:11; + uint64_t reserved_37:1; + uint64_t nosched_head:11; + uint64_t reserved_49:1; + uint64_t nosched_one:1; + uint64_t nosched_val:1; + uint64_t reserved_52_63:12; +#endif } sindexload1; /** * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_39_63:25; /* * Set when this DRAM list is the current head @@ -877,6 +1086,13 @@ typedef union { * qosgrp. */ uint64_t rmt_head:36; +#else + uint64_t rmt_head:36; + uint64_t rmt_one:1; + uint64_t rmt_val:1; + uint64_t rmt_is_head:1; + uint64_t reserved_39_63:25; +#endif } sindexload2; /** @@ -884,6 +1100,7 @@ typedef union { * 1/get_des_get_tail == 1) */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t reserved_39_63:25; /* * set when this DRAM list is the current head @@ -912,12 +1129,20 @@ typedef union { * qosgrp. */ uint64_t rmt_tail:36; +#else + uint64_t rmt_tail:36; + uint64_t rmt_one:1; + uint64_t rmt_val:1; + uint64_t rmt_is_head:1; + uint64_t reserved_39_63:25; +#endif } sindexload3; /** * Response to NULL_RD request loads */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t unused:62; /* of type cvmx_pow_tag_type_t. state is one of the * following: @@ -928,6 +1153,10 @@ typedef union { * - CVMX_POW_TAG_TYPE_NULL_NULL */ uint64_t state:2; +#else + uint64_t state:2; + uint64_t unused:62; +#endif } s_null_rd; } cvmx_pow_tag_load_resp_t; @@ -962,6 +1191,7 @@ typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* Memory region. Should be CVMX_IO_SEG in most cases */ uint64_t mem_reg:2; uint64_t reserved_49_61:13; /* Must be zero */ @@ -971,6 +1201,14 @@ typedef union { uint64_t reserved_36_39:4; /* Must be zero */ /* Address field. addr<2:0> must be zero */ uint64_t addr:36; +#else + uint64_t addr:36; + uint64_t reserved_36_39:4; + uint64_t did:8; + uint64_t is_io:1; + uint64_t reserved_49_61:13; + uint64_t mem_reg:2; +#endif } stag; } cvmx_pow_tag_store_addr_t; @@ -981,6 +1219,7 @@ typedef union { uint64_t u64; struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * the (64-bit word) location in scratchpad to write * to (if len != 0) @@ -994,6 +1233,14 @@ typedef union { /* if set, don't return load response until work is available */ uint64_t wait:1; uint64_t unused2:3; +#else + uint64_t unused2:3; + uint64_t wait:1; + uint64_t unused:36; + uint64_t did:8; + uint64_t len:8; + uint64_t scraddr:8; +#endif } s; } cvmx_pow_iobdma_store_t; diff --git a/arch/mips/include/asm/octeon/cvmx-wqe.h b/arch/mips/include/asm/octeon/cvmx-wqe.h index aa0d3d0de75c..2d6d0c7127a7 100644 --- a/arch/mips/include/asm/octeon/cvmx-wqe.h +++ b/arch/mips/include/asm/octeon/cvmx-wqe.h @@ -57,6 +57,7 @@ typedef union { /* Use this struct if the hardware determines that the packet is IP */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* HW sets this to the number of buffers used by this packet */ uint64_t bufs:8; /* HW sets to the number of L2 bytes prior to the IP */ @@ -166,13 +167,45 @@ typedef union { * the slow path */ /* type is cvmx_pip_err_t */ uint64_t err_code:8; +#else + uint64_t err_code:8; + uint64_t rcv_error:1; + uint64_t not_IP:1; + uint64_t is_mcast:1; + uint64_t is_bcast:1; + uint64_t IP_exc:1; + uint64_t is_frag:1; + uint64_t L4_error:1; + uint64_t software:1; + uint64_t is_v6:1; + uint64_t dec_ipsec:1; + uint64_t tcp_or_udp:1; + uint64_t dec_ipcomp:1; + uint64_t unassigned2:4; + uint64_t unassigned2a:4; + uint64_t pr:4; + uint64_t vlan_id:12; + uint64_t vlan_cfi:1; + uint64_t unassigned:1; + uint64_t vlan_stacked:1; + uint64_t vlan_valid:1; + uint64_t ip_offset:8; + uint64_t bufs:8; +#endif } s; /* use this to get at the 16 vlan bits */ struct { +#ifdef __BIG_ENDIAN_BITFIELD uint64_t unused1:16; uint64_t vlan:16; uint64_t unused2:32; +#else + uint64_t unused2:32; + uint64_t vlan:16; + uint64_t unused1:16; + +#endif } svlan; /* @@ -180,6 +213,7 @@ typedef union { * the packet is ip. */ struct { +#ifdef __BIG_ENDIAN_BITFIELD /* * HW sets this to the number of buffers used by this * packet. @@ -296,6 +330,27 @@ typedef union { */ /* type is cvmx_pip_err_t (union, so can't use directly */ uint64_t err_code:8; +#else + uint64_t err_code:8; + uint64_t rcv_error:1; + uint64_t not_IP:1; + uint64_t is_mcast:1; + uint64_t is_bcast:1; + uint64_t is_arp:1; + uint64_t is_rarp:1; + uint64_t unassigned3:1; + uint64_t software:1; + uint64_t unassigned2:4; + uint64_t unassigned2a:8; + uint64_t pr:4; + uint64_t vlan_id:12; + uint64_t vlan_cfi:1; + uint64_t unassigned:1; + uint64_t vlan_stacked:1; + uint64_t vlan_valid:1; + uint64_t unused:8; + uint64_t bufs:8; +#endif } snoip; } cvmx_pip_wqe_word2; @@ -312,6 +367,7 @@ typedef struct { * HW WRITE: the following 64 bits are filled by HW when a packet arrives */ +#ifdef __BIG_ENDIAN_BITFIELD /** * raw chksum result generated by the HW */ @@ -327,12 +383,18 @@ typedef struct { * (Only 36 bits used in Octeon 1) */ uint64_t next_ptr:40; +#else + uint64_t next_ptr:40; + uint8_t unused; + uint16_t hw_chksum; +#endif /***************************************************************** * WORD 1 * HW WRITE: the following 64 bits are filled by HW when a packet arrives */ +#ifdef __BIG_ENDIAN_BITFIELD /** * HW sets to the total number of bytes in the packet */ @@ -359,6 +421,15 @@ typedef struct { * the synchronization/ordering tag */ uint64_t tag:32; +#else + uint64_t tag:32; + uint64_t tag_type:2; + uint64_t zero_2:1; + uint64_t grp:4; + uint64_t qos:3; + uint64_t ipprt:6; + uint64_t len:16; +#endif /** * WORD 2 HW WRITE: the following 64-bits are filled in by diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 33db1c806b01..774bb45834cb 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -436,14 +436,6 @@ static inline uint64_t cvmx_get_cycle_global(void) /***************************************************************************/ -static inline void cvmx_reset_octeon(void) -{ - union cvmx_ciu_soft_rst ciu_soft_rst; - ciu_soft_rst.u64 = 0; - ciu_soft_rst.s.soft_rst = 1; - cvmx_write_csr(CVMX_CIU_SOFT_RST, ciu_soft_rst.u64); -} - /* Return the number of cores available in the chip */ static inline uint32_t cvmx_octeon_num_cores(void) { diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index 041596570856..de9f74ee5dd0 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -335,4 +335,6 @@ void octeon_irq_set_ip4_handler(octeon_irq_ip4_handler_t); extern void octeon_fixup_irqs(void); +extern struct semaphore octeon_bootbus_sem; + #endif /* __ASM_OCTEON_OCTEON_H */ diff --git a/arch/mips/include/asm/octeon/pci-octeon.h b/arch/mips/include/asm/octeon/pci-octeon.h index 64ba56a02843..1884609741a8 100644 --- a/arch/mips/include/asm/octeon/pci-octeon.h +++ b/arch/mips/include/asm/octeon/pci-octeon.h @@ -11,9 +11,6 @@ #include <linux/pci.h> -/* Some PCI cards require delays when accessing config space. */ -#define PCI_CONFIG_SPACE_DELAY 10000 - /* * The physical memory base mapped by BAR1. 256MB at the end of the * first 4GB. diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 154b70a10483..89dd7fed1a57 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -105,8 +105,6 @@ static inline void clear_user_page(void *addr, unsigned long vaddr, flush_data_cache_page((unsigned long)addr); } -extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, - struct page *to); struct vm_area_struct; extern void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr, struct vm_area_struct *vma); diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 193b4c6b7541..d9692993fc83 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -35,6 +35,8 @@ struct pci_controller { struct resource *io_resource; unsigned long io_offset; unsigned long io_map_base; + struct resource *busn_resource; + unsigned long busn_offset; unsigned int index; /* For compatibility with current (as of July 2003) pciutils diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h index af2c8a351ca7..8d7a63b52ac7 100644 --- a/arch/mips/include/asm/pci/bridge.h +++ b/arch/mips/include/asm/pci/bridge.h @@ -835,6 +835,7 @@ struct bridge_controller { struct pci_controller pc; struct resource mem; struct resource io; + struct resource busn; bridge_t *base; nasid_t nasid; unsigned int widget_id; diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index a6be006b6f75..7d56686c0e62 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -105,13 +105,16 @@ static inline void pmd_clear(pmd_t *pmdp) #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) #define pte_page(x) pfn_to_page(pte_pfn(x)) -#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) +#define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) { pte_t pte; - pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f); - pte.pte_low = pgprot_val(prot); + + pte.pte_low = (pfn >> _PAGE_PRESENT_SHIFT) | + (pgprot_val(prot) & ~_PFNX_MASK); + pte.pte_high = (pfn << _PFN_SHIFT) | + (pgprot_val(prot) & ~_PFN_MASK); return pte; } @@ -166,9 +169,9 @@ pfn_pte(unsigned long pfn, pgprot_t prot) #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) /* Swap entries must have VALID and GLOBAL bits cleared. */ -#define __swp_type(x) (((x).val >> 2) & 0x1f) -#define __swp_offset(x) ((x).val >> 7) -#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) +#define __swp_type(x) (((x).val >> 4) & 0x1f) +#define __swp_offset(x) ((x).val >> 9) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 4) | ((offset) << 9) }) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 1659bb91ae21..cf661a2fb141 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -279,14 +279,14 @@ extern void pgd_init(unsigned long page); extern void pmd_init(unsigned long page, unsigned long pagetable); /* - * Non-present pages: high 24 bits are offset, next 8 bits type, - * low 32 bits zero. + * Non-present pages: high 40 bits are offset, next 8 bits type, + * low 16 bits zero. */ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) -{ pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } +{ pte_t pte; pte_val(pte) = (type << 16) | (offset << 24); return pte; } -#define __swp_type(x) (((x).val >> 32) & 0xff) -#define __swp_offset(x) ((x).val >> 40) +#define __swp_type(x) (((x).val >> 16) & 0xff) +#define __swp_offset(x) ((x).val >> 24) #define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) }) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 91747c282bb3..18ae5ddef118 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h @@ -37,7 +37,11 @@ /* * The following bits are implemented by the TLB hardware */ -#define _PAGE_GLOBAL_SHIFT 0 +#define _PAGE_NO_EXEC_SHIFT 0 +#define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) +#define _PAGE_NO_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) +#define _PAGE_NO_READ (1 << _PAGE_NO_READ_SHIFT) +#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) #define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) @@ -49,7 +53,7 @@ /* * The following bits are implemented in software */ -#define _PAGE_PRESENT_SHIFT (_CACHE_SHIFT + 3) +#define _PAGE_PRESENT_SHIFT (24) #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) #define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) #define _PAGE_READ (1 << _PAGE_READ_SHIFT) @@ -62,6 +66,11 @@ #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) +/* + * Bits for extended EntryLo0/EntryLo1 registers + */ +#define _PFNX_MASK 0xffffff + #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) /* @@ -95,11 +104,7 @@ #else /* - * When using the RI/XI bit support, we have 13 bits of flags below - * the physical address. The RI/XI bits are placed such that a SRL 5 - * can strip off the software bits, then a ROTR 2 can move the RI/XI - * into bits [63:62]. This also limits physical address to 56 bits, - * which is more than we need right now. + * Below are the "Normal" R4K cases */ /* @@ -107,38 +112,59 @@ */ #define _PAGE_PRESENT_SHIFT 0 #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) -#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1) -#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; }) +/* R2 or later cores check for RI/XI support to determine _PAGE_READ */ +#ifdef CONFIG_CPU_MIPSR2 +#define _PAGE_WRITE_SHIFT (_PAGE_PRESENT_SHIFT + 1) +#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +#else +#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) +#define _PAGE_READ (1 << _PAGE_READ_SHIFT) #define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) +#endif #define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) #define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) -#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT -/* huge tlb page */ +#if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) +/* Huge TLB page */ #define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT + 1) #define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT) #define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT + 1) #define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT) + +/* Only R2 or newer cores have the XI bit */ +#ifdef CONFIG_CPU_MIPSR2 +#define _PAGE_NO_EXEC_SHIFT (_PAGE_SPLITTING_SHIFT + 1) #else -#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT) -#define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */ -#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT) -#define _PAGE_SPLITTING ({BUG(); 1; }) /* Dummy value */ -#endif +#define _PAGE_GLOBAL_SHIFT (_PAGE_SPLITTING_SHIFT + 1) +#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) +#endif /* CONFIG_CPU_MIPSR2 */ -/* Page cannot be executed */ -#define _PAGE_NO_EXEC_SHIFT (cpu_has_rixi ? _PAGE_SPLITTING_SHIFT + 1 : _PAGE_SPLITTING_SHIFT) -#define _PAGE_NO_EXEC ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; }) +#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */ -/* Page cannot be read */ -#define _PAGE_NO_READ_SHIFT (cpu_has_rixi ? _PAGE_NO_EXEC_SHIFT + 1 : _PAGE_NO_EXEC_SHIFT) -#define _PAGE_NO_READ ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_READ_SHIFT; }) +#ifdef CONFIG_CPU_MIPSR2 +/* XI - page cannot be executed */ +#ifndef _PAGE_NO_EXEC_SHIFT +#define _PAGE_NO_EXEC_SHIFT (_PAGE_MODIFIED_SHIFT + 1) +#endif +#define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) + +/* RI - page cannot be read */ +#define _PAGE_READ_SHIFT (_PAGE_NO_EXEC_SHIFT + 1) +#define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT)) +#define _PAGE_NO_READ_SHIFT _PAGE_READ_SHIFT +#define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0) #define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1) #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) + +#else /* !CONFIG_CPU_MIPSR2 */ +#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 1) +#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) +#endif /* CONFIG_CPU_MIPSR2 */ + #define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) #define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) @@ -150,18 +176,26 @@ #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ +#ifndef _PAGE_NO_EXEC +#define _PAGE_NO_EXEC 0 +#endif +#ifndef _PAGE_NO_READ +#define _PAGE_NO_READ 0 +#endif + #define _PAGE_SILENT_READ _PAGE_VALID #define _PAGE_SILENT_WRITE _PAGE_DIRTY #define _PFN_MASK (~((1 << (_PFN_SHIFT)) - 1)) -#ifndef _PAGE_NO_READ -#define _PAGE_NO_READ ({BUG(); 0; }) -#define _PAGE_NO_READ_SHIFT ({BUG(); 0; }) -#endif -#ifndef _PAGE_NO_EXEC -#define _PAGE_NO_EXEC ({BUG(); 0; }) -#endif +/* + * The final layouts of the PTE bits are: + * + * 64-bit, R1 or earlier: CCC D V G [S H] M A W R P + * 32-bit, R1 or earler: CCC D V G M A W R P + * 64-bit, R2 or later: CCC D V G RI/R XI [S H] M A W P + * 32-bit, R2 or later: CCC D V G RI/R XI M A W P + */ #ifndef __ASSEMBLY__ @@ -171,6 +205,7 @@ */ static inline uint64_t pte_to_entrylo(unsigned long pte_val) { +#ifdef CONFIG_CPU_MIPSR2 if (cpu_has_rixi) { int sa; #ifdef CONFIG_32BIT @@ -186,6 +221,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) return (pte_val >> _PAGE_GLOBAL_SHIFT) | ((pte_val & (_PAGE_NO_EXEC | _PAGE_NO_READ)) << sa); } +#endif return pte_val >> _PAGE_GLOBAL_SHIFT; } @@ -245,7 +281,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val) #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT) #endif -#define __READABLE (_PAGE_SILENT_READ | _PAGE_ACCESSED | (cpu_has_rixi ? 0 : _PAGE_READ)) +#define __READABLE (_PAGE_SILENT_READ | _PAGE_READ | _PAGE_ACCESSED) #define __WRITEABLE (_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (_PAGE_ACCESSED | _PAGE_MODIFIED | \ diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index bef782c4a44b..819af9d057a8 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -24,17 +24,17 @@ struct mm_struct; struct vm_area_struct; #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | (cpu_has_rixi ? 0 : _PAGE_READ) | \ +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | \ _page_cachable_default) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | \ - (cpu_has_rixi ? _PAGE_NO_EXEC : 0) | _page_cachable_default) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | \ +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_NO_EXEC | \ + _page_cachable_default) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _page_cachable_default) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _page_cachable_default) #define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT) -#define PAGE_USERIO __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | _PAGE_WRITE | \ +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ _page_cachable_default) #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED) @@ -127,13 +127,9 @@ do { \ } \ } while(0) - -extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, - pte_t pteval); - #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -#define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) +#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) static inline void set_pte(pte_t *ptep, pte_t pte) @@ -142,18 +138,17 @@ static inline void set_pte(pte_t *ptep, pte_t pte) smp_wmb(); ptep->pte_low = pte.pte_low; - if (pte.pte_low & _PAGE_GLOBAL) { + if (pte.pte_high & _PAGE_GLOBAL) { pte_t *buddy = ptep_buddy(ptep); /* * Make sure the buddy is global too (if it's !none, * it better already be global) */ - if (pte_none(*buddy)) { - buddy->pte_low |= _PAGE_GLOBAL; + if (pte_none(*buddy)) buddy->pte_high |= _PAGE_GLOBAL; - } } } +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -161,8 +156,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt htw_stop(); /* Preserve global status for the pair */ - if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) - null.pte_low = null.pte_high = _PAGE_GLOBAL; + if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) + null.pte_high = _PAGE_GLOBAL; set_pte_at(mm, addr, ptep, null); htw_start(); @@ -192,6 +187,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) } #endif } +#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -242,21 +238,21 @@ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } static inline pte_t pte_wrprotect(pte_t pte) { - pte.pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); + pte.pte_low &= ~_PAGE_WRITE; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } static inline pte_t pte_mkclean(pte_t pte) { - pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); + pte.pte_low &= ~_PAGE_MODIFIED; pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } static inline pte_t pte_mkold(pte_t pte) { - pte.pte_low &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); + pte.pte_low &= ~_PAGE_ACCESSED; pte.pte_high &= ~_PAGE_SILENT_READ; return pte; } @@ -264,30 +260,24 @@ static inline pte_t pte_mkold(pte_t pte) static inline pte_t pte_mkwrite(pte_t pte) { pte.pte_low |= _PAGE_WRITE; - if (pte.pte_low & _PAGE_MODIFIED) { - pte.pte_low |= _PAGE_SILENT_WRITE; + if (pte.pte_low & _PAGE_MODIFIED) pte.pte_high |= _PAGE_SILENT_WRITE; - } return pte; } static inline pte_t pte_mkdirty(pte_t pte) { pte.pte_low |= _PAGE_MODIFIED; - if (pte.pte_low & _PAGE_WRITE) { - pte.pte_low |= _PAGE_SILENT_WRITE; + if (pte.pte_low & _PAGE_WRITE) pte.pte_high |= _PAGE_SILENT_WRITE; - } return pte; } static inline pte_t pte_mkyoung(pte_t pte) { pte.pte_low |= _PAGE_ACCESSED; - if (pte.pte_low & _PAGE_READ) { - pte.pte_low |= _PAGE_SILENT_READ; + if (pte.pte_low & _PAGE_READ) pte.pte_high |= _PAGE_SILENT_READ; - } return pte; } #else @@ -332,13 +322,13 @@ static inline pte_t pte_mkdirty(pte_t pte) static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; - if (cpu_has_rixi) { - if (!(pte_val(pte) & _PAGE_NO_READ)) - pte_val(pte) |= _PAGE_SILENT_READ; - } else { - if (pte_val(pte) & _PAGE_READ) - pte_val(pte) |= _PAGE_SILENT_READ; - } +#ifdef CONFIG_CPU_MIPSR2 + if (!(pte_val(pte) & _PAGE_NO_READ)) + pte_val(pte) |= _PAGE_SILENT_READ; + else +#endif + if (pte_val(pte) & _PAGE_READ) + pte_val(pte) |= _PAGE_SILENT_READ; return pte; } @@ -391,10 +381,10 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - pte.pte_low &= _PAGE_CHG_MASK; + pte.pte_low &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); pte.pte_high &= (_PFN_MASK | _CACHE_MASK); - pte.pte_low |= pgprot_val(newprot); - pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); + pte.pte_low |= pgprot_val(newprot) & ~_PFNX_MASK; + pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK; return pte; } #else @@ -407,12 +397,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) extern void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte); +extern void __update_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte); static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { pte_t pte = *ptep; __update_tlb(vma, address, pte); + __update_cache(vma, address, pte); } static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, @@ -534,13 +527,13 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) { pmd_val(pmd) |= _PAGE_ACCESSED; - if (cpu_has_rixi) { - if (!(pmd_val(pmd) & _PAGE_NO_READ)) - pmd_val(pmd) |= _PAGE_SILENT_READ; - } else { - if (pmd_val(pmd) & _PAGE_READ) - pmd_val(pmd) |= _PAGE_SILENT_READ; - } +#ifdef CONFIG_CPU_MIPSR2 + if (!(pmd_val(pmd) & _PAGE_NO_READ)) + pmd_val(pmd) |= _PAGE_SILENT_READ; + else +#endif + if (pmd_val(pmd) & _PAGE_READ) + pmd_val(pmd) |= _PAGE_SILENT_READ; return pmd; } diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index b5dcbee01fd7..9b3b48e21c22 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -105,7 +105,7 @@ union fpureg { #ifdef CONFIG_CPU_LITTLE_ENDIAN # define FPR_IDX(width, idx) (idx) #else -# define FPR_IDX(width, idx) ((FPU_REG_WIDTH / (width)) - 1 - (idx)) +# define FPR_IDX(width, idx) ((idx) ^ ((64 / (width)) - 1)) #endif #define BUILD_FPR_ACCESS(width) \ diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index 1b22d2da88a1..38902bf97adc 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -12,6 +12,8 @@ #ifndef _ASM_R4KCACHE_H #define _ASM_R4KCACHE_H +#include <linux/stringify.h> + #include <asm/asm.h> #include <asm/cacheops.h> #include <asm/compiler.h> @@ -344,7 +346,7 @@ static inline void invalidate_tcache_page(unsigned long addr) " cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)\n" \ " cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)\n" \ " cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)\n" \ - " addiu $1, $0, 0x100 \n" \ + " "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x010($1)\n" \ " cache %1, 0x020($1); cache %1, 0x030($1)\n" \ " cache %1, 0x040($1); cache %1, 0x050($1)\n" \ @@ -368,17 +370,17 @@ static inline void invalidate_tcache_page(unsigned long addr) " cache %1, 0x040(%0); cache %1, 0x060(%0)\n" \ " cache %1, 0x080(%0); cache %1, 0x0a0(%0)\n" \ " cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x020($1)\n" \ " cache %1, 0x040($1); cache %1, 0x060($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \ " cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \ - " addiu $1, $1, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x020($1)\n" \ " cache %1, 0x040($1); cache %1, 0x060($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \ " cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \ - " addiu $1, $1, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100\n" \ " cache %1, 0x000($1); cache %1, 0x020($1)\n" \ " cache %1, 0x040($1); cache %1, 0x060($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \ @@ -396,25 +398,25 @@ static inline void invalidate_tcache_page(unsigned long addr) " .set noat\n" \ " cache %1, 0x000(%0); cache %1, 0x040(%0)\n" \ " cache %1, 0x080(%0); cache %1, 0x0c0(%0)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ " cache %1, 0x000($1); cache %1, 0x040($1)\n" \ " cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \ " .set pop\n" \ @@ -429,39 +431,38 @@ static inline void invalidate_tcache_page(unsigned long addr) " .set mips64r6\n" \ " .set noat\n" \ " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ - " cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \ - " addiu $1, %0, 0x100\n" \ + " "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ + " "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \ + " cache %1, 0x000($1); cache %1, 0x080($1)\n" \ " .set pop\n" \ : \ : "r" (base), \ diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index f29c75cf83c6..1d8a2e2c75c1 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h @@ -2,11 +2,6 @@ #include <linux/unistd.h> -#define __NR_seccomp_read __NR_read -#define __NR_seccomp_write __NR_write -#define __NR_seccomp_exit __NR_exit -#define __NR_seccomp_sigreturn __NR_rt_sigreturn - /* * Kludge alert: * @@ -29,4 +24,6 @@ #endif /* CONFIG_MIPS32_O32 */ +#include <asm-generic/seccomp.h> + #endif /* __ASM_SECCOMP_H */ diff --git a/arch/mips/include/asm/sgi/sgi.h b/arch/mips/include/asm/sgi/sgi.h index 645cea7c0f8e..b61557151e3f 100644 --- a/arch/mips/include/asm/sgi/sgi.h +++ b/arch/mips/include/asm/sgi/sgi.h @@ -22,14 +22,15 @@ enum sgi_mach { ip17, /* R4K UP */ ip19, /* R4K MP */ ip20, /* R4K UP, Indigo */ - ip21, /* TFP MP */ - ip22, /* R4x00 UP, Indigo2 */ + ip21, /* R8k/TFP MP */ + ip22, /* R4x00 UP, Indy, Indigo2 */ ip25, /* R10k MP */ - ip26, /* TFP UP, Indigo2 */ - ip27, /* R10k MP, R12k MP, Origin */ - ip28, /* R10k UP, Indigo2 */ - ip30, /* Octane */ - ip32, /* O2 */ + ip26, /* R8k/TFP UP, Indigo2 */ + ip27, /* R10k MP, R12k MP, R14k MP, Origin 200/2k, Onyx2 */ + ip28, /* R10k UP, Indigo2 Impact R10k */ + ip30, /* R10k MP, R12k MP, R14k MP, Octane */ + ip32, /* R5k UP, RM5200 UP, RM7k UP, R10k UP, R12k UP, O2 */ + ip35, /* R14k MP, R16k MP, Origin 300/3k, Onyx3, Fuel, Tezro */ }; extern enum sgi_mach sgimach; diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index b4548690ade9..1fca2e0793dc 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -263,7 +263,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) if (R10000_LLSC_WAR) { __asm__ __volatile__( "1: ll %1, %2 # arch_read_unlock \n" - " addiu %1, 1 \n" + " addiu %1, -1 \n" " sc %1, %0 \n" " beqzl %1, 1b \n" : "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp) diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 55ed6602204c..9c0014e87c17 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -23,7 +23,6 @@ */ struct thread_info { struct task_struct *task; /* main task structure */ - struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ unsigned long tp_value; /* thread pointer */ __u32 cpu; /* current CPU */ @@ -44,7 +43,6 @@ struct thread_info { #define INIT_THREAD_INFO(tsk) \ { \ .task = &tsk, \ - .exec_domain = &default_exec_domain, \ .flags = _TIF_FIXADE, \ .cpu = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ @@ -55,10 +53,10 @@ struct thread_info { #define init_stack (init_thread_union.stack) /* How to get the thread information struct from C. */ +register struct thread_info *__current_thread_info __asm__("$28"); + static inline struct thread_info *current_thread_info(void) { - register struct thread_info *__current_thread_info __asm__("$28"); - return __current_thread_info; } diff --git a/arch/mips/include/uapi/asm/kvm.h b/arch/mips/include/uapi/asm/kvm.h index 2c04b6d9ff85..6985eb59b085 100644 --- a/arch/mips/include/uapi/asm/kvm.h +++ b/arch/mips/include/uapi/asm/kvm.h @@ -36,77 +36,85 @@ struct kvm_regs { /* * for KVM_GET_FPU and KVM_SET_FPU - * - * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs - * are zero filled. */ struct kvm_fpu { - __u64 fpr[32]; - __u32 fir; - __u32 fccr; - __u32 fexr; - __u32 fenr; - __u32 fcsr; - __u32 pad; }; /* - * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0 + * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various * registers. The id field is broken down as follows: * - * bits[2..0] - Register 'sel' index. - * bits[7..3] - Register 'rd' index. - * bits[15..8] - Must be zero. - * bits[31..16] - 1 -> CP0 registers. - * bits[51..32] - Must be zero. * bits[63..52] - As per linux/kvm.h + * bits[51..32] - Must be zero. + * bits[31..16] - Register set. + * + * Register set = 0: GP registers from kvm_regs (see definitions below). + * + * Register set = 1: CP0 registers. + * bits[15..8] - Must be zero. + * bits[7..3] - Register 'rd' index. + * bits[2..0] - Register 'sel' index. + * + * Register set = 2: KVM specific registers (see definitions below). + * + * Register set = 3: FPU / MSA registers (see definitions below). * * Other sets registers may be added in the future. Each set would * have its own identifier in bits[31..16]. - * - * The registers defined in struct kvm_regs are also accessible, the - * id values for these are below. */ -#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0) -#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1) -#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2) -#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3) -#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4) -#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5) -#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6) -#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7) -#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8) -#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9) -#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10) -#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11) -#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12) -#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13) -#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14) -#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15) -#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16) -#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17) -#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18) -#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19) -#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20) -#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21) -#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22) -#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23) -#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24) -#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25) -#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26) -#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27) -#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28) -#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29) -#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30) -#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31) - -#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32) -#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33) -#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34) - -/* KVM specific control registers */ +#define KVM_REG_MIPS_GP (KVM_REG_MIPS | 0x0000000000000000ULL) +#define KVM_REG_MIPS_CP0 (KVM_REG_MIPS | 0x0000000000010000ULL) +#define KVM_REG_MIPS_KVM (KVM_REG_MIPS | 0x0000000000020000ULL) +#define KVM_REG_MIPS_FPU (KVM_REG_MIPS | 0x0000000000030000ULL) + + +/* + * KVM_REG_MIPS_GP - General purpose registers from kvm_regs. + */ + +#define KVM_REG_MIPS_R0 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 0) +#define KVM_REG_MIPS_R1 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_MIPS_R2 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 2) +#define KVM_REG_MIPS_R3 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 3) +#define KVM_REG_MIPS_R4 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_MIPS_R5 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 5) +#define KVM_REG_MIPS_R6 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 6) +#define KVM_REG_MIPS_R7 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 7) +#define KVM_REG_MIPS_R8 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 8) +#define KVM_REG_MIPS_R9 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 9) +#define KVM_REG_MIPS_R10 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10) +#define KVM_REG_MIPS_R11 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11) +#define KVM_REG_MIPS_R12 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12) +#define KVM_REG_MIPS_R13 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13) +#define KVM_REG_MIPS_R14 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14) +#define KVM_REG_MIPS_R15 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15) +#define KVM_REG_MIPS_R16 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16) +#define KVM_REG_MIPS_R17 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17) +#define KVM_REG_MIPS_R18 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18) +#define KVM_REG_MIPS_R19 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19) +#define KVM_REG_MIPS_R20 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20) +#define KVM_REG_MIPS_R21 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21) +#define KVM_REG_MIPS_R22 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22) +#define KVM_REG_MIPS_R23 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23) +#define KVM_REG_MIPS_R24 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24) +#define KVM_REG_MIPS_R25 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25) +#define KVM_REG_MIPS_R26 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26) +#define KVM_REG_MIPS_R27 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27) +#define KVM_REG_MIPS_R28 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28) +#define KVM_REG_MIPS_R29 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29) +#define KVM_REG_MIPS_R30 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30) +#define KVM_REG_MIPS_R31 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31) + +#define KVM_REG_MIPS_HI (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32) +#define KVM_REG_MIPS_LO (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33) +#define KVM_REG_MIPS_PC (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34) + + +/* + * KVM_REG_MIPS_KVM - KVM specific control registers. + */ /* * CP0_Count control @@ -118,8 +126,7 @@ struct kvm_fpu { * safely without losing time or guest timer interrupts. * Other: Reserved, do not change. */ -#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 0) +#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0) #define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001 /* @@ -131,15 +138,46 @@ struct kvm_fpu { * emulated. * Modifications to times in the future are rejected. */ -#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 1) +#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1) /* * CP0_Count rate in Hz * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without * discontinuities in CP0_Count. */ -#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS | KVM_REG_SIZE_U64 | \ - 0x20000 | 2) +#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2) + + +/* + * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers. + * + * bits[15..8] - Register subset (see definitions below). + * bits[7..5] - Must be zero. + * bits[4..0] - Register number within register subset. + */ + +#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL) +#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL) +#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL) + +/* + * KVM_REG_MIPS_FPR - Floating point / Vector registers. + */ +#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n)) +#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n)) +#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n)) + +/* + * KVM_REG_MIPS_FCR - Floating point control registers. + */ +#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0) +#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31) + +/* + * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers. + */ +#define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0) +#define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1) + /* * KVM MIPS specific structures and definitions diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform index ba91be9c21ef..c41d30080098 100644 --- a/arch/mips/jz4740/Platform +++ b/arch/mips/jz4740/Platform @@ -1,3 +1,4 @@ platform-$(CONFIG_MACH_JZ4740) += jz4740/ cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 +zload-$(CONFIG_MACH_JZ4740) += 0xffffffff80600000 diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c index 5e430ce9ac7e..72b0cecbc17c 100644 --- a/arch/mips/jz4740/time.c +++ b/arch/mips/jz4740/time.c @@ -18,6 +18,7 @@ #include <linux/time.h> #include <linux/clockchips.h> +#include <linux/sched_clock.h> #include <asm/mach-jz4740/irq.h> #include <asm/mach-jz4740/timer.h> @@ -43,6 +44,11 @@ static struct clocksource jz4740_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace jz4740_read_sched_clock(void) +{ + return jz4740_timer_get_count(TIMER_CLOCKSOURCE); +} + static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) { struct clock_event_device *cd = devid; @@ -126,6 +132,8 @@ void __init plat_time_init(void) if (ret) printk(KERN_ERR "Failed to register clocksource: %d\n", ret); + sched_clock_register(jz4740_read_sched_clock, 16, clk_rate); + setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction); ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT; diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 750d67ac41e9..beabe19ff8e5 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -92,7 +92,6 @@ void output_thread_info_defines(void) { COMMENT("MIPS thread_info offsets."); OFFSET(TI_TASK, thread_info, task); - OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain); OFFSET(TI_FLAGS, thread_info, flags); OFFSET(TI_TP_VALUE, thread_info, tp_value); OFFSET(TI_CPU, thread_info, cpu); @@ -167,72 +166,6 @@ void output_thread_fpu_defines(void) OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]); OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]); - /* the least significant 64 bits of each FP register */ - OFFSET(THREAD_FPR0_LS64, task_struct, - thread.fpu.fpr[0].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR1_LS64, task_struct, - thread.fpu.fpr[1].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR2_LS64, task_struct, - thread.fpu.fpr[2].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR3_LS64, task_struct, - thread.fpu.fpr[3].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR4_LS64, task_struct, - thread.fpu.fpr[4].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR5_LS64, task_struct, - thread.fpu.fpr[5].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR6_LS64, task_struct, - thread.fpu.fpr[6].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR7_LS64, task_struct, - thread.fpu.fpr[7].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR8_LS64, task_struct, - thread.fpu.fpr[8].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR9_LS64, task_struct, - thread.fpu.fpr[9].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR10_LS64, task_struct, - thread.fpu.fpr[10].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR11_LS64, task_struct, - thread.fpu.fpr[11].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR12_LS64, task_struct, - thread.fpu.fpr[12].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR13_LS64, task_struct, - thread.fpu.fpr[13].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR14_LS64, task_struct, - thread.fpu.fpr[14].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR15_LS64, task_struct, - thread.fpu.fpr[15].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR16_LS64, task_struct, - thread.fpu.fpr[16].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR17_LS64, task_struct, - thread.fpu.fpr[17].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR18_LS64, task_struct, - thread.fpu.fpr[18].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR19_LS64, task_struct, - thread.fpu.fpr[19].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR20_LS64, task_struct, - thread.fpu.fpr[20].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR21_LS64, task_struct, - thread.fpu.fpr[21].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR22_LS64, task_struct, - thread.fpu.fpr[22].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR23_LS64, task_struct, - thread.fpu.fpr[23].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR24_LS64, task_struct, - thread.fpu.fpr[24].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR25_LS64, task_struct, - thread.fpu.fpr[25].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR26_LS64, task_struct, - thread.fpu.fpr[26].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR27_LS64, task_struct, - thread.fpu.fpr[27].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR28_LS64, task_struct, - thread.fpu.fpr[28].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR29_LS64, task_struct, - thread.fpu.fpr[29].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR30_LS64, task_struct, - thread.fpu.fpr[30].val64[FPR_IDX(64, 0)]); - OFFSET(THREAD_FPR31_LS64, task_struct, - 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(); @@ -470,6 +403,45 @@ void output_kvm_defines(void) OFFSET(VCPU_LO, kvm_vcpu_arch, lo); OFFSET(VCPU_HI, kvm_vcpu_arch, hi); OFFSET(VCPU_PC, kvm_vcpu_arch, pc); + BLANK(); + + OFFSET(VCPU_FPR0, kvm_vcpu_arch, fpu.fpr[0]); + OFFSET(VCPU_FPR1, kvm_vcpu_arch, fpu.fpr[1]); + OFFSET(VCPU_FPR2, kvm_vcpu_arch, fpu.fpr[2]); + OFFSET(VCPU_FPR3, kvm_vcpu_arch, fpu.fpr[3]); + OFFSET(VCPU_FPR4, kvm_vcpu_arch, fpu.fpr[4]); + OFFSET(VCPU_FPR5, kvm_vcpu_arch, fpu.fpr[5]); + OFFSET(VCPU_FPR6, kvm_vcpu_arch, fpu.fpr[6]); + OFFSET(VCPU_FPR7, kvm_vcpu_arch, fpu.fpr[7]); + OFFSET(VCPU_FPR8, kvm_vcpu_arch, fpu.fpr[8]); + OFFSET(VCPU_FPR9, kvm_vcpu_arch, fpu.fpr[9]); + OFFSET(VCPU_FPR10, kvm_vcpu_arch, fpu.fpr[10]); + OFFSET(VCPU_FPR11, kvm_vcpu_arch, fpu.fpr[11]); + OFFSET(VCPU_FPR12, kvm_vcpu_arch, fpu.fpr[12]); + OFFSET(VCPU_FPR13, kvm_vcpu_arch, fpu.fpr[13]); + OFFSET(VCPU_FPR14, kvm_vcpu_arch, fpu.fpr[14]); + OFFSET(VCPU_FPR15, kvm_vcpu_arch, fpu.fpr[15]); + OFFSET(VCPU_FPR16, kvm_vcpu_arch, fpu.fpr[16]); + OFFSET(VCPU_FPR17, kvm_vcpu_arch, fpu.fpr[17]); + OFFSET(VCPU_FPR18, kvm_vcpu_arch, fpu.fpr[18]); + OFFSET(VCPU_FPR19, kvm_vcpu_arch, fpu.fpr[19]); + OFFSET(VCPU_FPR20, kvm_vcpu_arch, fpu.fpr[20]); + OFFSET(VCPU_FPR21, kvm_vcpu_arch, fpu.fpr[21]); + OFFSET(VCPU_FPR22, kvm_vcpu_arch, fpu.fpr[22]); + OFFSET(VCPU_FPR23, kvm_vcpu_arch, fpu.fpr[23]); + OFFSET(VCPU_FPR24, kvm_vcpu_arch, fpu.fpr[24]); + OFFSET(VCPU_FPR25, kvm_vcpu_arch, fpu.fpr[25]); + OFFSET(VCPU_FPR26, kvm_vcpu_arch, fpu.fpr[26]); + OFFSET(VCPU_FPR27, kvm_vcpu_arch, fpu.fpr[27]); + OFFSET(VCPU_FPR28, kvm_vcpu_arch, fpu.fpr[28]); + OFFSET(VCPU_FPR29, kvm_vcpu_arch, fpu.fpr[29]); + OFFSET(VCPU_FPR30, kvm_vcpu_arch, fpu.fpr[30]); + OFFSET(VCPU_FPR31, kvm_vcpu_arch, fpu.fpr[31]); + + OFFSET(VCPU_FCR31, kvm_vcpu_arch, fpu.fcr31); + OFFSET(VCPU_MSA_CSR, kvm_vcpu_arch, fpu.msacsr); + BLANK(); + OFFSET(VCPU_COP0, kvm_vcpu_arch, cop0); OFFSET(VCPU_GUEST_KERNEL_ASID, kvm_vcpu_arch, guest_kernel_asid); OFFSET(VCPU_GUEST_USER_ASID, kvm_vcpu_arch, guest_user_asid); diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index c2e0f45ddf6c..c0c5e5972256 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -36,8 +36,10 @@ int __isa_exception_epc(struct pt_regs *regs) return epc; } if (cpu_has_mips16) { - if (((union mips16e_instruction)inst).ri.opcode - == MIPS16e_jal_op) + union mips16e_instruction inst_mips16e; + + inst_mips16e.full = inst; + if (inst_mips16e.ri.opcode == MIPS16e_jal_op) epc += 4; else epc += 2; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 82bd2b278a24..d70c4d893219 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -37,6 +37,24 @@ void mips_set_clock_mode(enum clock_event_mode mode, DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); int cp0_timer_irq_installed; +/* + * Possibly handle a performance counter interrupt. + * Return true if the timer interrupt should not be checked + */ +static inline int handle_perf_irq(int r2) +{ + /* + * The performance counter overflow interrupt may be shared with the + * timer interrupt (cp0_perfcount_irq < 0). If it is and a + * performance counter has overflowed (perf_irq() == IRQ_HANDLED) + * and we can't reliably determine if a counter interrupt has also + * happened (!r2) then don't check for a timer interrupt. + */ + return (cp0_perfcount_irq < 0) && + perf_irq() == IRQ_HANDLED && + !r2; +} + irqreturn_t c0_compare_interrupt(int irq, void *dev_id) { const int r2 = cpu_has_mips_r2_r6; @@ -50,27 +68,32 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id) * the performance counter interrupt handler anyway. */ if (handle_perf_irq(r2)) - goto out; + return IRQ_HANDLED; /* * The same applies to performance counter interrupts. But with the * above we now know that the reason we got here must be a timer * interrupt. Being the paranoiacs we are we check anyway. */ - if (!r2 || (read_c0_cause() & (1 << 30))) { + if (!r2 || (read_c0_cause() & CAUSEF_TI)) { /* Clear Count/Compare Interrupt */ write_c0_compare(read_c0_compare()); cd = &per_cpu(mips_clockevent_device, cpu); cd->event_handler(cd); + + return IRQ_HANDLED; } -out: - return IRQ_HANDLED; + return IRQ_NONE; } struct irqaction c0_compare_irqaction = { .handler = c0_compare_interrupt, - .flags = IRQF_PERCPU | IRQF_TIMER, + /* + * IRQF_SHARED: The timer interrupt may be shared with other interrupts + * such as perf counter and FDC interrupts. + */ + .flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED, .name = "timer", }; diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index 2ae08462e46e..723932441ecc 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/sched_clock.h> #include <asm/time.h> #include <asm/txx9tmr.h> @@ -46,6 +47,11 @@ static struct txx9_clocksource txx9_clocksource = { }, }; +static u64 notrace txx9_read_sched_clock(void) +{ + return __raw_readl(&txx9_clocksource.tmrptr->trr); +} + void __init txx9_clocksource_init(unsigned long baseaddr, unsigned int imbusclk) { @@ -61,6 +67,9 @@ void __init txx9_clocksource_init(unsigned long baseaddr, __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra); __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); txx9_clocksource.tmrptr = tmrptr; + + sched_clock_register(txx9_read_sched_clock, TXX9_CLOCKSOURCE_BITS, + TIMER_CLK(imbusclk)); } struct txx9_clock_event_device { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 48dfb9de853d..e36515dcd3b2 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -20,6 +20,7 @@ #include <asm/bugs.h> #include <asm/cpu.h> +#include <asm/cpu-features.h> #include <asm/cpu-type.h> #include <asm/fpu.h> #include <asm/mipsregs.h> @@ -31,11 +32,127 @@ #include <asm/spram.h> #include <asm/uaccess.h> +/* + * Get the FPU Implementation/Revision. + */ +static inline unsigned long cpu_get_fpu_id(void) +{ + unsigned long tmp, fpu_id; + + tmp = read_c0_status(); + __enable_fpu(FPU_AS_IS); + fpu_id = read_32bit_cp1_register(CP1_REVISION); + write_c0_status(tmp); + return fpu_id; +} + +/* + * Check if the CPU has an external FPU. + */ +static inline int __cpu_has_fpu(void) +{ + return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; +} + +static inline unsigned long cpu_get_msa_id(void) +{ + unsigned long status, msa_id; + + status = read_c0_status(); + __enable_fpu(FPU_64BIT); + enable_msa(); + msa_id = read_msa_ir(); + disable_msa(); + write_c0_status(status); + return msa_id; +} + +/* + * Determine the FCSR mask for FPU hardware. + */ +static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c) +{ + unsigned long sr, mask, fcsr, fcsr0, fcsr1; + + mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM; + + sr = read_c0_status(); + __enable_fpu(FPU_AS_IS); + + fcsr = read_32bit_cp1_register(CP1_STATUS); + + fcsr0 = fcsr & mask; + write_32bit_cp1_register(CP1_STATUS, fcsr0); + fcsr0 = read_32bit_cp1_register(CP1_STATUS); + + fcsr1 = fcsr | ~mask; + write_32bit_cp1_register(CP1_STATUS, fcsr1); + fcsr1 = read_32bit_cp1_register(CP1_STATUS); + + write_32bit_cp1_register(CP1_STATUS, fcsr); + + write_c0_status(sr); + + c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask; +} + +/* + * Set the FIR feature flags for the FPU emulator. + */ +static void cpu_set_nofpu_id(struct cpuinfo_mips *c) +{ + u32 value; + + value = 0; + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) + value |= MIPS_FPIR_D | MIPS_FPIR_S; + if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) + value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W; + c->fpu_id = value; +} + +/* Determined FPU emulator mask to use for the boot CPU with "nofpu". */ +static unsigned int mips_nofpu_msk31; + +/* + * Set options for FPU hardware. + */ +static void cpu_set_fpu_opts(struct cpuinfo_mips *c) +{ + c->fpu_id = cpu_get_fpu_id(); + mips_nofpu_msk31 = c->fpu_msk31; + + if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | + MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | + MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { + if (c->fpu_id & MIPS_FPIR_3D) + c->ases |= MIPS_ASE_MIPS3D; + if (c->fpu_id & MIPS_FPIR_FREP) + c->options |= MIPS_CPU_FRE; + } + + cpu_set_fpu_fcsr_mask(c); +} + +/* + * Set options for the FPU emulator. + */ +static void cpu_set_nofpu_opts(struct cpuinfo_mips *c) +{ + c->options &= ~MIPS_CPU_FPU; + c->fpu_msk31 = mips_nofpu_msk31; + + cpu_set_nofpu_id(c); +} + static int mips_fpu_disabled; static int __init fpu_disable(char *s) { - cpu_data[0].options &= ~MIPS_CPU_FPU; + cpu_set_nofpu_opts(&boot_cpu_data); mips_fpu_disabled = 1; return 1; @@ -178,41 +295,6 @@ static inline void set_elf_platform(int cpu, const char *plat) __elf_platform = plat; } -/* - * Get the FPU Implementation/Revision. - */ -static inline unsigned long cpu_get_fpu_id(void) -{ - unsigned long tmp, fpu_id; - - tmp = read_c0_status(); - __enable_fpu(FPU_AS_IS); - fpu_id = read_32bit_cp1_register(CP1_REVISION); - write_c0_status(tmp); - return fpu_id; -} - -/* - * Check the CPU has an FPU the official way. - */ -static inline int __cpu_has_fpu(void) -{ - return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; -} - -static inline unsigned long cpu_get_msa_id(void) -{ - unsigned long status, msa_id; - - status = read_c0_status(); - __enable_fpu(FPU_64BIT); - enable_msa(); - msa_id = read_msa_ir(); - disable_msa(); - write_c0_status(status); - return msa_id; -} - static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) { #ifdef __NEED_VMBITS_PROBE @@ -441,6 +523,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->htw_seq = 0; c->options |= MIPS_CPU_HTW; } + if (config3 & MIPS_CONF3_CDMM) + c->options |= MIPS_CPU_CDMM; return config3 & MIPS_CONF_M; } @@ -516,6 +600,10 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c) c->options |= MIPS_CPU_MAAR; if (config5 & MIPS_CONF5_LLB) c->options |= MIPS_CPU_RW_LLB; +#ifdef CONFIG_XPA + if (config5 & MIPS_CONF5_MVH) + c->options |= MIPS_CPU_XPA; +#endif return config5 & MIPS_CONF_M; } @@ -575,6 +663,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) case PRID_IMP_R2000: c->cputype = CPU_R2000; __cpu_name[cpu] = "R2000"; + c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS; c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) @@ -594,6 +683,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R3000; __cpu_name[cpu] = "R3000"; } + c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS; c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) @@ -642,6 +732,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) } set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_WATCH | MIPS_CPU_VCE | MIPS_CPU_LLSC; @@ -649,6 +740,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) break; case PRID_IMP_VR41XX: set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS; c->tlbsize = 32; switch (c->processor_id & 0xf0) { @@ -690,6 +782,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R4300; __cpu_name[cpu] = "R4300"; set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_LLSC; c->tlbsize = 32; @@ -698,6 +791,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R4600; __cpu_name[cpu] = "R4600"; set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_LLSC; c->tlbsize = 48; @@ -713,11 +807,13 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R4650; __cpu_name[cpu] = "R4650"; set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; c->tlbsize = 48; break; #endif case PRID_IMP_TX39: + c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS; c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE; if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) { @@ -743,6 +839,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R4700; __cpu_name[cpu] = "R4700"; set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_LLSC; c->tlbsize = 48; @@ -751,6 +848,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_TX49XX; __cpu_name[cpu] = "R49XX"; set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; c->options = R4K_OPTS | MIPS_CPU_LLSC; if (!(c->processor_id & 0x08)) c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; @@ -792,6 +890,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R6000; __cpu_name[cpu] = "R6000"; set_isa(c, MIPS_CPU_ISA_II); + c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS; c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | MIPS_CPU_LLSC; c->tlbsize = 32; @@ -800,6 +899,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R6000A; __cpu_name[cpu] = "R6000A"; set_isa(c, MIPS_CPU_ISA_II); + c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS; c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | MIPS_CPU_LLSC; c->tlbsize = 32; @@ -850,8 +950,13 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->tlbsize = 64; break; case PRID_IMP_R14000: - c->cputype = CPU_R14000; - __cpu_name[cpu] = "R14000"; + if (((c->processor_id >> 4) & 0x0f) > 2) { + c->cputype = CPU_R16000; + __cpu_name[cpu] = "R16000"; + } else { + c->cputype = CPU_R14000; + __cpu_name[cpu] = "R14000"; + } set_isa(c, MIPS_CPU_ISA_IV); c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | MIPS_CPU_FPU | MIPS_CPU_32FPR | @@ -866,12 +971,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "ICT Loongson-2"; set_elf_platform(cpu, "loongson2e"); set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; break; case PRID_REV_LOONGSON2F: c->cputype = CPU_LOONGSON2; __cpu_name[cpu] = "ICT Loongson-2"; set_elf_platform(cpu, "loongson2f"); set_isa(c, MIPS_CPU_ISA_III); + c->fpu_msk31 |= FPU_CSR_CONDX; break; case PRID_REV_LOONGSON3A: c->cputype = CPU_LOONGSON3; @@ -1308,6 +1415,9 @@ void cpu_probe(void) c->cputype = CPU_UNKNOWN; c->writecombine = _CACHE_UNCACHED; + c->fpu_csr31 = FPU_CSR_RN; + c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008; + c->processor_id = read_c0_prid(); switch (c->processor_id & PRID_COMP_MASK) { case PRID_COMP_LEGACY: @@ -1364,16 +1474,10 @@ void cpu_probe(void) ~(1 << MIPS_PWCTL_PWEN_SHIFT)); } - if (c->options & MIPS_CPU_FPU) { - c->fpu_id = cpu_get_fpu_id(); - - if (c->isa_level & cpu_has_mips_r) { - if (c->fpu_id & MIPS_FPIR_3D) - c->ases |= MIPS_ASE_MIPS3D; - if (c->fpu_id & MIPS_FPIR_FREP) - c->options |= MIPS_CPU_FRE; - } - } + if (c->options & MIPS_CPU_FPU) + cpu_set_fpu_opts(c); + else + cpu_set_nofpu_opts(c); if (cpu_has_mips_r2_r6) { c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; diff --git a/arch/mips/kernel/csrc-bcm1480.c b/arch/mips/kernel/csrc-bcm1480.c index 468f3eba4132..7f65b53d1b24 100644 --- a/arch/mips/kernel/csrc-bcm1480.c +++ b/arch/mips/kernel/csrc-bcm1480.c @@ -10,12 +10,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/clocksource.h> +#include <linux/sched_clock.h> #include <asm/addrspace.h> #include <asm/io.h> @@ -41,6 +38,11 @@ struct clocksource bcm1480_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace sb1480_read_sched_clock(void) +{ + return __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT)); +} + void __init sb1480_clocksource_init(void) { struct clocksource *cs = &bcm1480_clocksource; @@ -50,4 +52,6 @@ void __init sb1480_clocksource_init(void) plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000); clocksource_register_hz(cs, zbbus); + + sched_clock_register(sb1480_read_sched_clock, 64, zbbus); } diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c index 6cbbf6e106b9..722f5589cd1d 100644 --- a/arch/mips/kernel/csrc-ioasic.c +++ b/arch/mips/kernel/csrc-ioasic.c @@ -12,12 +12,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/clocksource.h> +#include <linux/sched_clock.h> #include <linux/init.h> #include <asm/ds1287.h> @@ -37,6 +34,11 @@ static struct clocksource clocksource_dec = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace dec_ioasic_read_sched_clock(void) +{ + return ioasic_read(IO_REG_FCTR); +} + int __init dec_ioasic_clocksource_init(void) { unsigned int freq; @@ -65,5 +67,8 @@ int __init dec_ioasic_clocksource_init(void) clocksource_dec.rating = 200 + freq / 10000000; clocksource_register_hz(&clocksource_dec, freq); + + sched_clock_register(dec_ioasic_read_sched_clock, 32, freq); + return 0; } diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c index decd1fa38d55..e5ed7ada1433 100644 --- a/arch/mips/kernel/csrc-r4k.c +++ b/arch/mips/kernel/csrc-r4k.c @@ -7,6 +7,7 @@ */ #include <linux/clocksource.h> #include <linux/init.h> +#include <linux/sched_clock.h> #include <asm/time.h> @@ -22,6 +23,11 @@ static struct clocksource clocksource_mips = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace r4k_read_sched_clock(void) +{ + return read_c0_count(); +} + int __init init_r4k_clocksource(void) { if (!cpu_has_counter || !mips_hpt_frequency) @@ -32,5 +38,7 @@ int __init init_r4k_clocksource(void) clocksource_register_hz(&clocksource_mips, mips_hpt_frequency); + sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency); + return 0; } diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c index 6ecb77d82063..d915652b4d56 100644 --- a/arch/mips/kernel/csrc-sb1250.c +++ b/arch/mips/kernel/csrc-sb1250.c @@ -10,12 +10,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/clocksource.h> +#include <linux/sched_clock.h> #include <asm/addrspace.h> #include <asm/io.h> @@ -33,15 +30,22 @@ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over * again. */ -static cycle_t sb1250_hpt_read(struct clocksource *cs) +static inline cycle_t sb1250_hpt_get_cycles(void) { unsigned int count; + void __iomem *addr; - count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); + addr = IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)); + count = G_SCD_TIMER_CNT(__raw_readq(addr)); return SB1250_HPT_VALUE - count; } +static cycle_t sb1250_hpt_read(struct clocksource *cs) +{ + return sb1250_hpt_get_cycles(); +} + struct clocksource bcm1250_clocksource = { .name = "bcm1250-counter-3", .rating = 200, @@ -50,6 +54,11 @@ struct clocksource bcm1250_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace sb1250_read_sched_clock(void) +{ + return sb1250_hpt_get_cycles(); +} + void __init sb1250_clocksource_init(void) { struct clocksource *cs = &bcm1250_clocksource; @@ -66,4 +75,6 @@ void __init sb1250_clocksource_init(void) R_SCD_TIMER_CFG))); clocksource_register_hz(cs, V_SCD_TIMER_FREQ); + + sched_clock_register(sb1250_read_sched_clock, 23, V_SCD_TIMER_FREQ); } diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c index d2c09f6475c5..be4899f3c393 100644 --- a/arch/mips/kernel/elf.c +++ b/arch/mips/kernel/elf.c @@ -131,16 +131,6 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, return 0; } -static inline unsigned get_fp_abi(int in_abi) -{ - /* If the ABI requirement is provided, simply return that */ - if (in_abi != MIPS_ABI_FP_UNKNOWN) - return in_abi; - - /* Unknown ABI */ - return MIPS_ABI_FP_UNKNOWN; -} - int arch_check_elf(void *_ehdr, bool has_interpreter, struct arch_elf_state *state) { @@ -151,10 +141,10 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) return 0; - fp_abi = get_fp_abi(state->fp_abi); + fp_abi = state->fp_abi; if (has_interpreter) { - interp_fp_abi = get_fp_abi(state->interp_fp_abi); + interp_fp_abi = state->interp_fp_abi; abi0 = min(fp_abi, interp_fp_abi); abi1 = max(fp_abi, interp_fp_abi); diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index af41ba6db960..7791840cf22c 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -10,6 +10,7 @@ #include <asm/asm.h> #include <asm/asmmacro.h> +#include <asm/compiler.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> @@ -185,7 +186,7 @@ syscall_exit_work: * For C code use the inline version named instruction_hazard(). */ LEAF(mips_ihb) - .set mips32r2 + .set MIPS_ISA_LEVEL_RAW jr.hb ra nop END(mips_ihb) diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 2ebaabe3af15..af42e7003f12 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -360,12 +360,15 @@ NESTED(nmi_handler, PT_SIZE, sp) .set mips1 SET_HARDFLOAT cfc1 a1, fcr31 - li a2, ~(0x3f << 12) - and a2, a1 - ctc1 a2, fcr31 .set pop - TRACE_IRQS_ON - STI + CLI + TRACE_IRQS_OFF + .endm + + .macro __build_clear_msa_fpe + _cfcmsa a1, MSA_CSR + CLI + TRACE_IRQS_OFF .endm .macro __build_clear_ade @@ -426,7 +429,7 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER cpu cpu sti silent /* #11 */ BUILD_HANDLER ov ov sti silent /* #12 */ BUILD_HANDLER tr tr sti silent /* #13 */ - BUILD_HANDLER msa_fpe msa_fpe sti silent /* #14 */ + BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent /* #14 */ BUILD_HANDLER fpe fpe fpe silent /* #15 */ BUILD_HANDLER ftlb ftlb none silent /* #16 */ BUILD_HANDLER msa msa sti silent /* #21 */ diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 368c88b7eb6c..e4f62b7875d2 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -176,6 +176,17 @@ void __init check_wait(void) cpu_wait = rm7k_wait_irqoff; break; + case CPU_PROAPTIV: + case CPU_P5600: + /* + * Incoming Fast Debug Channel (FDC) data during a wait + * instruction causes the wait never to resume, even if an + * interrupt is received. Avoid using wait at all if FDC data is + * likely to be received. + */ + if (IS_ENABLED(CONFIG_MIPS_EJTAG_FDC_TTY)) + break; + /* fall through */ case CPU_M14KC: case CPU_M14KEC: case CPU_24K: @@ -183,8 +194,6 @@ void __init check_wait(void) case CPU_1004K: case CPU_1074K: case CPU_INTERAPTIV: - case CPU_PROAPTIV: - case CPU_P5600: case CPU_M5150: case CPU_QEMU_GENERIC: cpu_wait = r4k_wait; diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 64d17e41093b..f2977f00911b 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -187,7 +187,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir) } /** - * movt_func - Emulate a MOVT instruction + * movf_func - Emulate a MOVF instruction * @regs: Process register set * @ir: Instruction * @@ -200,9 +200,12 @@ static int movf_func(struct pt_regs *regs, u32 ir) csr = current->thread.fpu.fcr31; cond = fpucondbit[MIPSInst_RT(ir) >> 2]; + if (((csr & cond) == 0) && MIPSInst_RD(ir)) regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)]; + MIPS_R2_STATS(movs); + return 0; } @@ -895,8 +898,9 @@ static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst, * mipsr2_decoder: Decode and emulate a MIPS R2 instruction * @regs: Process register set * @inst: Instruction to decode and emulate + * @fcr31: Floating Point Control and Status Register returned */ -int mipsr2_decoder(struct pt_regs *regs, u32 inst) +int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) { int err = 0; unsigned long vaddr; @@ -1165,6 +1169,13 @@ fpu_emul: err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, &fault_addr); + *fcr31 = current->thread.fpu.fcr31; + + /* + * We can't allow the emulated instruction to leave any of + * the cause bits set in $fcr31. + */ + current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* * this is a tricky issue - lose_fpu() uses LL/SC atomics diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 9466184d0039..cc1b6fadf089 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -558,8 +558,10 @@ static int mipspmu_get_irq(void) if (mipspmu.irq >= 0) { /* Request my own irq handler. */ err = request_irq(mipspmu.irq, mipsxx_pmu_handle_irq, - IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD, - "mips_perf_pmu", NULL); + IRQF_PERCPU | IRQF_NOBALANCING | + IRQF_NO_THREAD | IRQF_NO_SUSPEND | + IRQF_SHARED, + "mips_perf_pmu", &mipspmu); if (err) { pr_warn("Unable to request IRQ%d for MIPS performance counters!\n", mipspmu.irq); @@ -582,7 +584,7 @@ static int mipspmu_get_irq(void) static void mipspmu_free_irq(void) { if (mipspmu.irq >= 0) - free_irq(mipspmu.irq, NULL); + free_irq(mipspmu.irq, &mipspmu); else if (cp0_perfcount_irq < 0) perf_irq = save_perf_irq; } @@ -775,6 +777,7 @@ static int n_counters(void) case CPU_R12000: case CPU_R14000: + case CPU_R16000: counters = 4; break; @@ -822,6 +825,13 @@ static const struct mips_perf_event mipsxxcore_event_map2 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T }, }; +static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = { + [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN }, + [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD }, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x01, CNTR_EVEN }, + [PERF_COUNT_HW_BRANCH_MISSES] = { 0x01, CNTR_ODD }, +}; + static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL }, [PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL }, @@ -1005,6 +1015,61 @@ static const struct mips_perf_event mipsxxcore_cache_map2 }, }; +static const struct mips_perf_event loongson3_cache_map + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +[C(L1D)] = { + /* + * Like some other architectures (e.g. ARM), the performance + * counters don't differentiate between read and write + * accesses/misses, so this isn't strictly correct, but it's the + * best we can do. Writes and reads get combined. + */ + [C(OP_READ)] = { + [C(RESULT_MISS)] = { 0x04, CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_MISS)] = { 0x04, CNTR_ODD }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_MISS)] = { 0x04, CNTR_EVEN }, + }, + [C(OP_WRITE)] = { + [C(RESULT_MISS)] = { 0x04, CNTR_EVEN }, + }, +}, +[C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_MISS)] = { 0x09, CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_MISS)] = { 0x09, CNTR_ODD }, + }, +}, +[C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_MISS)] = { 0x0c, CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_MISS)] = { 0x0c, CNTR_ODD }, + }, +}, +[C(BPU)] = { + /* Using the same code for *HW_BRANCH* */ + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x02, CNTR_EVEN }, + [C(RESULT_MISS)] = { 0x02, CNTR_ODD }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x02, CNTR_EVEN }, + [C(RESULT_MISS)] = { 0x02, CNTR_ODD }, + }, +}, +}; + /* BMIPS5000 */ static const struct mips_perf_event bmips5000_cache_map [PERF_COUNT_HW_CACHE_MAX] @@ -1539,6 +1604,10 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config) else raw_event.cntr_mask = raw_id > 127 ? CNTR_ODD : CNTR_EVEN; + break; + case CPU_LOONGSON3: + raw_event.cntr_mask = raw_id > 127 ? CNTR_ODD : CNTR_EVEN; + break; } raw_event.event_id = base_id; @@ -1615,8 +1684,7 @@ init_hw_perf_events(void) if (get_c0_perfcount_int) irq = get_c0_perfcount_int(); - else if ((cp0_perfcount_irq >= 0) && - (cp0_compare_irq != cp0_perfcount_irq)) + else if (cp0_perfcount_irq >= 0) irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; else irq = -1; @@ -1669,6 +1737,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.cache_event_map = &mipsxxcore_cache_map; break; + case CPU_LOONGSON3: + mipspmu.name = "mips/loongson3"; + mipspmu.general_event_map = &loongson3_event_map; + mipspmu.cache_event_map = &loongson3_cache_map; + break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 130af7d26a9c..298b2b773d12 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -120,6 +120,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) 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"); + if (cpu_has_xpa) seq_printf(m, "%s", " xpa"); seq_printf(m, "\n"); if (cpu_has_mmips) { diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index bf85cc180d91..d295bd1e4996 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -107,8 +107,11 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) return 0; } +/* + * Copy architecture-specific thread state + */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) + unsigned long kthread_arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs, *regs = current_pt_regs(); @@ -123,11 +126,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childksp = (unsigned long) childregs; p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); if (unlikely(p->flags & PF_KTHREAD)) { + /* kernel thread */ unsigned long status = p->thread.cp0_status; memset(childregs, 0, sizeof(struct pt_regs)); ti->addr_limit = KERNEL_DS; p->thread.reg16 = usp; /* fn */ - p->thread.reg17 = arg; + p->thread.reg17 = kthread_arg; p->thread.reg29 = childksp; p->thread.reg31 = (unsigned long) ret_from_kernel_thread; #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) @@ -139,6 +143,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->cp0_status = status; return 0; } + + /* user thread */ *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */ childregs->regs[2] = 0; /* Child gets zero as return value */ diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 452d4350ce42..e303cb1ef2f4 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -64,7 +64,10 @@ int __init __dt_register_buses(const char *bus0, const char *bus1) panic("device tree not present"); strlcpy(of_ids[0].compatible, bus0, sizeof(of_ids[0].compatible)); - strlcpy(of_ids[1].compatible, bus1, sizeof(of_ids[1].compatible)); + if (bus1) { + strlcpy(of_ids[1].compatible, bus1, + sizeof(of_ids[1].compatible)); + } if (of_platform_populate(NULL, of_ids, NULL, NULL)) panic("failed to populate DT"); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 510452812594..d544e774eea6 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -32,6 +32,7 @@ #include <asm/byteorder.h> #include <asm/cpu.h> +#include <asm/cpu-info.h> #include <asm/dsp.h> #include <asm/fpu.h> #include <asm/mipsregs.h> @@ -46,6 +47,26 @@ #define CREATE_TRACE_POINTS #include <trace/events/syscalls.h> +static void init_fp_ctx(struct task_struct *target) +{ + /* If FP has been used then the target already has context */ + if (tsk_used_math(target)) + return; + + /* Begin with data registers set to all 1s... */ + memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr)); + + /* ...and FCSR zeroed */ + target->thread.fpu.fcr31 = 0; + + /* + * Record that the target has "used" math, such that the context + * just initialised, and any modifications made by the caller, + * aren't discarded. + */ + set_stopped_child_used_math(target); +} + /* * Called by kernel/ptrace.c when detaching.. * @@ -137,11 +158,15 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) { union fpureg *fregs; u64 fpr_val; + u32 fcr31; + u32 value; + u32 mask; int i; if (!access_ok(VERIFY_READ, data, 33 * 8)) return -EIO; + init_fp_ctx(child); fregs = get_fpu_regs(child); for (i = 0; i < 32; i++) { @@ -149,8 +174,10 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) set_fpr64(&fregs[i], 0, fpr_val); } - __get_user(child->thread.fpu.fcr31, data + 64); - child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + __get_user(value, data + 64); + fcr31 = child->thread.fpu.fcr31; + mask = current_cpu_data.fpu_msk31; + child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); /* FIR may not be written. */ @@ -439,6 +466,8 @@ static int fpr_set(struct task_struct *target, /* XXX fcr31 */ + init_fp_ctx(target); + if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fpu, @@ -660,12 +689,7 @@ long arch_ptrace(struct task_struct *child, long request, case FPR_BASE ... FPR_BASE + 31: { union fpureg *fregs = get_fpu_regs(child); - if (!tsk_used_math(child)) { - /* FP not yet used */ - memset(&child->thread.fpu, ~0, - sizeof(child->thread.fpu)); - child->thread.fpu.fcr31 = 0; - } + init_fp_ctx(child); #ifdef CONFIG_32BIT if (test_thread_flag(TIF_32BIT_FPREGS)) { /* diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index 435ea652f5fa..5087a4b72e6b 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S @@ -115,11 +115,9 @@ LEAF(_restore_fp) * the property that no matter whether considered as single or as double * precision represents signaling NANS. * - * We initialize fcr31 to rounding to nearest, no exceptions. + * The value to initialize fcr31 to comes in $a0. */ -#define FPU_DEFAULT 0x00000000 - .set push SET_HARDFLOAT @@ -129,8 +127,7 @@ LEAF(_init_fpu) or t0, t1 mtc0 t0, CP0_STATUS - li t1, FPU_DEFAULT - ctc1 t1, fcr31 + ctc1 a0, fcr31 li t0, -1 diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 676c5030a953..1d88af26ba82 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -34,7 +34,6 @@ .endm .set noreorder - .set MIPS_ISA_ARCH_LEVEL_RAW LEAF(_save_fp_context) .set push @@ -103,6 +102,7 @@ LEAF(_save_fp_context) /* Save 32-bit process floating point context */ LEAF(_save_fp_context32) .set push + .set MIPS_ISA_ARCH_LEVEL_RAW SET_HARDFLOAT cfc1 t1, fcr31 diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 3b1a36f13a7d..04cbbde3521b 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -165,11 +165,9 @@ LEAF(_init_msa_upper) * the property that no matter whether considered as single or as double * precision represents signaling NANS. * - * We initialize fcr31 to rounding to nearest, no exceptions. + * The value to initialize fcr31 to comes in $a0. */ -#define FPU_DEFAULT 0x00000000 - .set push SET_HARDFLOAT @@ -180,8 +178,7 @@ LEAF(_init_fpu) mtc0 t0, CP0_STATUS enable_fpu_hazard - li t1, FPU_DEFAULT - ctc1 t1, fcr31 + ctc1 a0, fcr31 li t1, -1 # SNaN diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index 07fc5244aed4..7c746d3458e7 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -11,6 +11,7 @@ #include <linux/pm.h> #include <linux/types.h> #include <linux/reboot.h> +#include <linux/delay.h> #include <asm/reboot.h> @@ -29,16 +30,40 @@ void machine_restart(char *command) { if (_machine_restart) _machine_restart(command); + +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + do_kernel_restart(command); + mdelay(1000); + pr_emerg("Reboot failed -- System halted\n"); + local_irq_disable(); + while (1); } void machine_halt(void) { if (_machine_halt) _machine_halt(); + +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + local_irq_disable(); + while (1); } void machine_power_off(void) { if (pm_power_off) pm_power_off(); + +#ifdef CONFIG_SMP + preempt_disable(); + smp_send_stop(); +#endif + local_irq_disable(); + while (1); } diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 058929041368..be73c491182b 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -31,6 +31,7 @@ #include <asm/bootinfo.h> #include <asm/bugs.h> #include <asm/cache.h> +#include <asm/cdmm.h> #include <asm/cpu.h> #include <asm/sections.h> #include <asm/setup.h> @@ -763,6 +764,7 @@ void __init setup_arch(char **cmdline_p) cpu_probe(); prom_init(); + setup_early_fdc_console(); #ifdef CONFIG_EARLY_PRINTK setup_early_printk(); #endif diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index bed7590e475f..d5589bedd0a4 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -88,6 +88,12 @@ static void __init cps_smp_setup(void) /* Make core 0 coherent with everything */ write_gcr_cl_coherence(0xff); + +#ifdef CONFIG_MIPS_MT_FPAFF + /* If we have an FPU, enroll ourselves in the FPU-full mask */ + if (cpu_has_fpu) + cpu_set(0, mt_fpu_cpumask); +#endif /* CONFIG_MIPS_MT_FPAFF */ } static void __init cps_prepare_cpus(unsigned int max_cpus) diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1c0d8c50b7e1..5b020bda3e05 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -176,10 +176,8 @@ static void stop_this_cpu(void *dummy) * Remove this CPU: */ set_cpu_online(smp_processor_id(), false); - for (;;) { - if (cpu_wait) - (*cpu_wait)(); /* Wait if available. */ - } + local_irq_disable(); + while (1); } void smp_send_stop(void) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 33984c04b60b..e334c641a81b 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -12,6 +12,7 @@ * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. * Copyright (C) 2014, Imagination Technologies Ltd. */ +#include <linux/bitops.h> #include <linux/bug.h> #include <linux/compiler.h> #include <linux/context_tracking.h> @@ -699,29 +700,60 @@ asmlinkage void do_ov(struct pt_regs *regs) exception_exit(prev_state); } -int process_fpemu_return(int sig, void __user *fault_addr) +int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31) { - if (sig == SIGSEGV || sig == SIGBUS) { - struct siginfo si = {0}; + struct siginfo si = { 0 }; + + switch (sig) { + case 0: + return 0; + + case SIGFPE: si.si_addr = fault_addr; si.si_signo = sig; - if (sig == SIGSEGV) { - down_read(¤t->mm->mmap_sem); - if (find_vma(current->mm, (unsigned long)fault_addr)) - si.si_code = SEGV_ACCERR; - else - si.si_code = SEGV_MAPERR; - up_read(¤t->mm->mmap_sem); - } else { - si.si_code = BUS_ADRERR; - } + /* + * Inexact can happen together with Overflow or Underflow. + * Respect the mask to deliver the correct exception. + */ + fcr31 &= (fcr31 & FPU_CSR_ALL_E) << + (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); + if (fcr31 & FPU_CSR_INV_X) + si.si_code = FPE_FLTINV; + else if (fcr31 & FPU_CSR_DIV_X) + si.si_code = FPE_FLTDIV; + else if (fcr31 & FPU_CSR_OVF_X) + si.si_code = FPE_FLTOVF; + else if (fcr31 & FPU_CSR_UDF_X) + si.si_code = FPE_FLTUND; + else if (fcr31 & FPU_CSR_INE_X) + si.si_code = FPE_FLTRES; + else + si.si_code = __SI_FAULT; + force_sig_info(sig, &si, current); + return 1; + + case SIGBUS: + si.si_addr = fault_addr; + si.si_signo = sig; + si.si_code = BUS_ADRERR; force_sig_info(sig, &si, current); return 1; - } else if (sig) { + + case SIGSEGV: + si.si_addr = fault_addr; + si.si_signo = sig; + down_read(¤t->mm->mmap_sem); + if (find_vma(current->mm, (unsigned long)fault_addr)) + si.si_code = SEGV_ACCERR; + else + si.si_code = SEGV_MAPERR; + up_read(¤t->mm->mmap_sem); + force_sig_info(sig, &si, current); + return 1; + + default: force_sig(sig, current); return 1; - } else { - return 0; } } @@ -729,7 +761,8 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode, unsigned long old_epc, unsigned long old_ra) { union mips_instruction inst = { .word = opcode }; - void __user *fault_addr = NULL; + void __user *fault_addr; + unsigned long fcr31; int sig; /* If it's obviously not an FP instruction, skip it */ @@ -759,13 +792,20 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode, /* Run the emulator */ sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, &fault_addr); + fcr31 = current->thread.fpu.fcr31; - /* If something went wrong, signal */ - process_fpemu_return(sig, fault_addr); + /* + * We can't allow the emulated instruction to leave any of + * the cause bits set in $fcr31. + */ + current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ own_fpu(1); + /* Send a signal if required. */ + process_fpemu_return(sig, fault_addr, fcr31); + return 0; } @@ -775,18 +815,21 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode, asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { enum ctx_state prev_state; - siginfo_t info = {0}; + void __user *fault_addr; + int sig; prev_state = exception_enter(); if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) goto out; + + /* Clear FCSR.Cause before enabling interrupts */ + write_32bit_cp1_register(CP1_STATUS, fcr31 & ~FPU_CSR_ALL_X); + local_irq_enable(); + die_if_kernel("FP exception in kernel code", regs); if (fcr31 & FPU_CSR_UNI_X) { - int sig; - void __user *fault_addr = NULL; - /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... @@ -803,36 +846,23 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) /* Run the emulator */ sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, &fault_addr); + fcr31 = current->thread.fpu.fcr31; /* * We can't allow the emulated instruction to leave any of - * the cause bit set in $fcr31. + * the cause bits set in $fcr31. */ current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ own_fpu(1); /* Using the FPU again. */ + } else { + sig = SIGFPE; + fault_addr = (void __user *) regs->cp0_epc; + } - /* If something went wrong, signal */ - process_fpemu_return(sig, fault_addr); - - goto out; - } else if (fcr31 & FPU_CSR_INV_X) - info.si_code = FPE_FLTINV; - else if (fcr31 & FPU_CSR_DIV_X) - info.si_code = FPE_FLTDIV; - else if (fcr31 & FPU_CSR_OVF_X) - info.si_code = FPE_FLTOVF; - else if (fcr31 & FPU_CSR_UDF_X) - info.si_code = FPE_FLTUND; - else if (fcr31 & FPU_CSR_INE_X) - info.si_code = FPE_FLTRES; - else - info.si_code = __SI_FAULT; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *) regs->cp0_epc; - force_sig_info(SIGFPE, &info, current); + /* Send a signal if required. */ + process_fpemu_return(sig, fault_addr, fcr31); out: exception_exit(prev_state); @@ -879,9 +909,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, break; case BRK_MEMU: /* - * Address errors may be deliberately induced by the FPU - * emulator to retake control of the CPU after executing the - * instruction in the delay slot of an emulated branch. + * This breakpoint code is used by the FPU emulator to retake + * control of the CPU after executing the instruction from the + * delay slot of an emulated branch. * * Terminate if exception was recognized as a delay slot return * otherwise handle as normal. @@ -901,10 +931,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, asmlinkage void do_bp(struct pt_regs *regs) { + unsigned long epc = msk_isa16_mode(exception_epc(regs)); unsigned int opcode, bcode; enum ctx_state prev_state; - unsigned long epc; - u16 instr[2]; mm_segment_t seg; seg = get_fs(); @@ -913,26 +942,28 @@ asmlinkage void do_bp(struct pt_regs *regs) prev_state = exception_enter(); if (get_isa16_mode(regs->cp0_epc)) { - /* Calculate EPC. */ - epc = exception_epc(regs); - if (cpu_has_mmips) { - if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) || - (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2))))) - goto out_sigsegv; - opcode = (instr[0] << 16) | instr[1]; - } else { + u16 instr[2]; + + if (__get_user(instr[0], (u16 __user *)epc)) + goto out_sigsegv; + + if (!cpu_has_mmips) { /* MIPS16e mode */ - if (__get_user(instr[0], - (u16 __user *)msk_isa16_mode(epc))) + bcode = (instr[0] >> 5) & 0x3f; + } else if (mm_insn_16bit(instr[0])) { + /* 16-bit microMIPS BREAK */ + bcode = instr[0] & 0xf; + } else { + /* 32-bit microMIPS BREAK */ + if (__get_user(instr[1], (u16 __user *)(epc + 2))) goto out_sigsegv; - bcode = (instr[0] >> 6) & 0x3f; - do_trap_or_bp(regs, bcode, "Break"); - goto out; + opcode = (instr[0] << 16) | instr[1]; + bcode = (opcode >> 6) & ((1 << 20) - 1); } } else { - if (__get_user(opcode, - (unsigned int __user *) exception_epc(regs))) + if (__get_user(opcode, (unsigned int __user *)epc)) goto out_sigsegv; + bcode = (opcode >> 6) & ((1 << 20) - 1); } /* @@ -941,9 +972,8 @@ asmlinkage void do_bp(struct pt_regs *regs) * Gas is bug-compatible, but not always, grrr... * We handle both cases with a simple heuristics. --macro */ - bcode = ((opcode >> 6) & ((1 << 20) - 1)); if (bcode >= (1 << 10)) - bcode >>= 10; + bcode = ((bcode & ((1 << 10) - 1)) << 10) | (bcode >> 10); /* * notify the kprobe handlers, if instruction is likely to @@ -1033,22 +1063,24 @@ asmlinkage void do_ri(struct pt_regs *regs) * as quickly as possible. */ if (mipsr2_emulation && cpu_has_mips_r6 && - likely(user_mode(regs))) { - if (likely(get_user(opcode, epc) >= 0)) { - status = mipsr2_decoder(regs, opcode); - switch (status) { - case 0: - case SIGEMT: - task_thread_info(current)->r2_emul_return = 1; - return; - case SIGILL: - goto no_r2_instr; - default: - process_fpemu_return(status, - ¤t->thread.cp0_baduaddr); - task_thread_info(current)->r2_emul_return = 1; - return; - } + likely(user_mode(regs)) && + likely(get_user(opcode, epc) >= 0)) { + unsigned long fcr31 = 0; + + status = mipsr2_decoder(regs, opcode, &fcr31); + switch (status) { + case 0: + case SIGEMT: + task_thread_info(current)->r2_emul_return = 1; + return; + case SIGILL: + goto no_r2_instr; + default: + process_fpemu_return(status, + ¤t->thread.cp0_baduaddr, + fcr31); + task_thread_info(current)->r2_emul_return = 1; + return; } } @@ -1293,10 +1325,13 @@ asmlinkage void do_cpu(struct pt_regs *regs) enum ctx_state prev_state; unsigned int __user *epc; unsigned long old_epc, old31; + void __user *fault_addr; unsigned int opcode; + unsigned long fcr31; unsigned int cpid; int status, err; unsigned long __maybe_unused flags; + int sig; prev_state = exception_enter(); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; @@ -1313,7 +1348,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) status = -1; if (unlikely(compute_return_epc(regs) < 0)) - goto out; + break; if (get_isa16_mode(regs->cp0_epc)) { unsigned short mmop[2] = { 0 }; @@ -1346,59 +1381,73 @@ asmlinkage void do_cpu(struct pt_regs *regs) force_sig(status, current); } - goto out; + break; case 3: /* - * Old (MIPS I and MIPS II) processors will set this code - * for COP1X opcode instructions that replaced the original - * COP3 space. We don't limit COP1 space instructions in - * the emulator according to the CPU ISA, so we want to - * treat COP1X instructions consistently regardless of which - * code the CPU chose. Therefore we redirect this trap to - * the FP emulator too. - * - * Then some newer FPU-less processors use this code - * erroneously too, so they are covered by this choice - * as well. + * The COP3 opcode space and consequently the CP0.Status.CU3 + * bit and the CP0.Cause.CE=3 encoding have been removed as + * of the MIPS III ISA. From the MIPS IV and MIPS32r2 ISAs + * up the space has been reused for COP1X instructions, that + * are enabled by the CP0.Status.CU1 bit and consequently + * use the CP0.Cause.CE=1 encoding for Coprocessor Unusable + * exceptions. Some FPU-less processors that implement one + * of these ISAs however use this code erroneously for COP1X + * instructions. Therefore we redirect this trap to the FP + * emulator too. */ - if (raw_cpu_has_fpu) + if (raw_cpu_has_fpu || !cpu_has_mips_4_5_64_r2_r6) { + force_sig(SIGILL, current); break; + } /* Fall through. */ case 1: err = enable_restore_fp_context(0); - if (!raw_cpu_has_fpu || err) { - int sig; - void __user *fault_addr = NULL; - sig = fpu_emulator_cop1Handler(regs, - ¤t->thread.fpu, - 0, &fault_addr); - if (!process_fpemu_return(sig, fault_addr) && !err) - mt_ase_fp_affinity(); - } + if (raw_cpu_has_fpu && !err) + break; - goto out; + sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, + &fault_addr); + fcr31 = current->thread.fpu.fcr31; + + /* + * We can't allow the emulated instruction to leave + * any of the cause bits set in $fcr31. + */ + current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + + /* Send a signal if required. */ + if (!process_fpemu_return(sig, fault_addr, fcr31) && !err) + mt_ase_fp_affinity(); + + break; case 2: raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); - goto out; + break; } - force_sig(SIGILL, current); - -out: exception_exit(prev_state); } -asmlinkage void do_msa_fpe(struct pt_regs *regs) +asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr) { enum ctx_state prev_state; prev_state = exception_enter(); + if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0, + regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) + goto out; + + /* Clear MSACSR.Cause before enabling interrupts */ + write_msa_csr(msacsr & ~MSA_CSR_CAUSEF); + local_irq_enable(); + die_if_kernel("do_msa_fpe invoked from kernel context!", regs); force_sig(SIGFPE, current); +out: exception_exit(prev_state); } @@ -1969,6 +2018,12 @@ int cp0_compare_irq_shift; int cp0_perfcount_irq; EXPORT_SYMBOL_GPL(cp0_perfcount_irq); +/* + * Fast debug channel IRQ or -1 if not present + */ +int cp0_fdc_irq; +EXPORT_SYMBOL_GPL(cp0_fdc_irq); + static int noulri; static int __init ulri_disable(char *s) @@ -2050,17 +2105,21 @@ void per_cpu_trap_init(bool is_boot_cpu) * * o read IntCtl.IPTI to determine the timer interrupt * o read IntCtl.IPPCI to determine the performance counter interrupt + * o read IntCtl.IPFDC to determine the fast debug channel interrupt */ if (cpu_has_mips_r2_r6) { cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP; cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7; cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7; - if (cp0_perfcount_irq == cp0_compare_irq) - cp0_perfcount_irq = -1; + cp0_fdc_irq = (read_c0_intctl() >> INTCTLB_IPFDC) & 7; + if (!cp0_fdc_irq) + cp0_fdc_irq = -1; + } else { cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; cp0_compare_irq_shift = CP0_LEGACY_PERFCNT_IRQ; cp0_perfcount_irq = -1; + cp0_fdc_irq = -1; } if (!cpu_data[cpu].asid_cache) diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index bbb69695a0a1..af84bef0c90d 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -89,8 +89,6 @@ #include <asm/fpu_emulator.h> #include <asm/inst.h> #include <asm/uaccess.h> -#include <asm/fpu.h> -#include <asm/fpu_emulator.h> #define STR(x) __STR(x) #define __STR(x) #x @@ -109,10 +107,11 @@ static u32 unaligned_action; extern void show_registers(struct pt_regs *regs); #ifdef __BIG_ENDIAN -#define LoadHW(addr, value, res) \ +#define _LoadHW(addr, value, res, type) \ +do { \ __asm__ __volatile__ (".set\tnoat\n" \ - "1:\t"user_lb("%0", "0(%2)")"\n" \ - "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ + "1:\t"type##_lb("%0", "0(%2)")"\n" \ + "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -127,13 +126,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) #ifndef CONFIG_CPU_MIPSR6 -#define LoadW(addr, value, res) \ +#define _LoadW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "(%2)")"\n" \ - "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "(%2)")"\n" \ + "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ "li\t%1, 0\n" \ "3:\n\t" \ ".insn\n\t" \ @@ -146,21 +147,24 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has no lwl instruction */ -#define LoadW(addr, value, res) \ +#define _LoadW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n" \ ".set\tnoat\n\t" \ - "1:"user_lb("%0", "0(%2)")"\n\t" \ - "2:"user_lbu("$1", "1(%2)")"\n\t" \ + "1:"type##_lb("%0", "0(%2)")"\n\t" \ + "2:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "2(%2)")"\n\t" \ + "3:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "3(%2)")"\n\t" \ + "4:"type##_lbu("$1", "3(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -178,14 +182,17 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t4b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #endif /* CONFIG_CPU_MIPSR6 */ -#define LoadHWU(addr, value, res) \ +#define _LoadHWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_lbu("%0", "0(%2)")"\n" \ - "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ + "1:\t"type##_lbu("%0", "0(%2)")"\n" \ + "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -201,13 +208,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) #ifndef CONFIG_CPU_MIPSR6 -#define LoadWU(addr, value, res) \ +#define _LoadWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "(%2)")"\n" \ - "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "(%2)")"\n" \ + "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ "dsll\t%0, %0, 32\n\t" \ "dsrl\t%0, %0, 32\n\t" \ "li\t%1, 0\n" \ @@ -222,9 +231,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define LoadDW(addr, value, res) \ +#define _LoadDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ "1:\tldl\t%0, (%2)\n" \ "2:\tldr\t%0, 7(%2)\n\t" \ @@ -240,21 +251,24 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has not lwl and ldl instructions */ -#define LoadWU(addr, value, res) \ +#define _LoadWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_lbu("%0", "0(%2)")"\n\t" \ - "2:"user_lbu("$1", "1(%2)")"\n\t" \ + "1:"type##_lbu("%0", "0(%2)")"\n\t" \ + "2:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "2(%2)")"\n\t" \ + "3:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "3(%2)")"\n\t" \ + "4:"type##_lbu("$1", "3(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -272,9 +286,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t4b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define LoadDW(addr, value, res) \ +#define _LoadDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ @@ -319,16 +335,19 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t8b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #endif /* CONFIG_CPU_MIPSR6 */ -#define StoreHW(addr, value, res) \ +#define _StoreHW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_sb("%1", "1(%2)")"\n" \ + "1:\t"type##_sb("%1", "1(%2)")"\n" \ "srl\t$1, %1, 0x8\n" \ - "2:\t"user_sb("$1", "0(%2)")"\n" \ + "2:\t"type##_sb("$1", "0(%2)")"\n" \ ".set\tat\n\t" \ "li\t%0, 0\n" \ "3:\n\t" \ @@ -342,13 +361,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT));\ +} while(0) #ifndef CONFIG_CPU_MIPSR6 -#define StoreW(addr, value, res) \ +#define _StoreW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_swl("%1", "(%2)")"\n" \ - "2:\t"user_swr("%1", "3(%2)")"\n\t" \ + "1:\t"type##_swl("%1", "(%2)")"\n" \ + "2:\t"type##_swr("%1", "3(%2)")"\n\t"\ "li\t%0, 0\n" \ "3:\n\t" \ ".insn\n\t" \ @@ -361,9 +382,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define StoreDW(addr, value, res) \ +#define _StoreDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ "1:\tsdl\t%1,(%2)\n" \ "2:\tsdr\t%1, 7(%2)\n\t" \ @@ -379,20 +402,23 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has no swl and sdl instructions */ -#define StoreW(addr, value, res) \ +#define _StoreW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_sb("%1", "3(%2)")"\n\t" \ + "1:"type##_sb("%1", "3(%2)")"\n\t" \ "srl\t$1, %1, 0x8\n\t" \ - "2:"user_sb("$1", "2(%2)")"\n\t" \ + "2:"type##_sb("$1", "2(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "3:"user_sb("$1", "1(%2)")"\n\t" \ + "3:"type##_sb("$1", "1(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "4:"user_sb("$1", "0(%2)")"\n\t" \ + "4:"type##_sb("$1", "0(%2)")"\n\t" \ ".set\tpop\n\t" \ "li\t%0, 0\n" \ "10:\n\t" \ @@ -409,9 +435,11 @@ extern void show_registers(struct pt_regs *regs); ".previous" \ : "=&r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT) \ - : "memory"); + : "memory"); \ +} while(0) #define StoreDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ @@ -451,15 +479,18 @@ extern void show_registers(struct pt_regs *regs); ".previous" \ : "=&r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT) \ - : "memory"); + : "memory"); \ +} while(0) + #endif /* CONFIG_CPU_MIPSR6 */ #else /* __BIG_ENDIAN */ -#define LoadHW(addr, value, res) \ +#define _LoadHW(addr, value, res, type) \ +do { \ __asm__ __volatile__ (".set\tnoat\n" \ - "1:\t"user_lb("%0", "1(%2)")"\n" \ - "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ + "1:\t"type##_lb("%0", "1(%2)")"\n" \ + "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -474,13 +505,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) #ifndef CONFIG_CPU_MIPSR6 -#define LoadW(addr, value, res) \ +#define _LoadW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "3(%2)")"\n" \ - "2:\t"user_lwr("%0", "(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "3(%2)")"\n" \ + "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ "li\t%1, 0\n" \ "3:\n\t" \ ".insn\n\t" \ @@ -493,21 +526,24 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has no lwl instruction */ -#define LoadW(addr, value, res) \ +#define _LoadW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n" \ ".set\tnoat\n\t" \ - "1:"user_lb("%0", "3(%2)")"\n\t" \ - "2:"user_lbu("$1", "2(%2)")"\n\t" \ + "1:"type##_lb("%0", "3(%2)")"\n\t" \ + "2:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "1(%2)")"\n\t" \ + "3:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "0(%2)")"\n\t" \ + "4:"type##_lbu("$1", "0(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -525,15 +561,18 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t4b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #endif /* CONFIG_CPU_MIPSR6 */ -#define LoadHWU(addr, value, res) \ +#define _LoadHWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_lbu("%0", "1(%2)")"\n" \ - "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ + "1:\t"type##_lbu("%0", "1(%2)")"\n" \ + "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -549,13 +588,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) #ifndef CONFIG_CPU_MIPSR6 -#define LoadWU(addr, value, res) \ +#define _LoadWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "3(%2)")"\n" \ - "2:\t"user_lwr("%0", "(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "3(%2)")"\n" \ + "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ "dsll\t%0, %0, 32\n\t" \ "dsrl\t%0, %0, 32\n\t" \ "li\t%1, 0\n" \ @@ -570,9 +611,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define LoadDW(addr, value, res) \ +#define _LoadDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ "1:\tldl\t%0, 7(%2)\n" \ "2:\tldr\t%0, (%2)\n\t" \ @@ -588,21 +631,24 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has not lwl and ldl instructions */ -#define LoadWU(addr, value, res) \ +#define _LoadWU(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_lbu("%0", "3(%2)")"\n\t" \ - "2:"user_lbu("$1", "2(%2)")"\n\t" \ + "1:"type##_lbu("%0", "3(%2)")"\n\t" \ + "2:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "1(%2)")"\n\t" \ + "3:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "0(%2)")"\n\t" \ + "4:"type##_lbu("$1", "0(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \ @@ -620,9 +666,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t4b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define LoadDW(addr, value, res) \ +#define _LoadDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ @@ -667,15 +715,17 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t8b, 11b\n\t" \ ".previous" \ : "=&r" (value), "=r" (res) \ - : "r" (addr), "i" (-EFAULT)); + : "r" (addr), "i" (-EFAULT)); \ +} while(0) #endif /* CONFIG_CPU_MIPSR6 */ -#define StoreHW(addr, value, res) \ +#define _StoreHW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_sb("%1", "0(%2)")"\n" \ + "1:\t"type##_sb("%1", "0(%2)")"\n" \ "srl\t$1,%1, 0x8\n" \ - "2:\t"user_sb("$1", "1(%2)")"\n" \ + "2:\t"type##_sb("$1", "1(%2)")"\n" \ ".set\tat\n\t" \ "li\t%0, 0\n" \ "3:\n\t" \ @@ -689,12 +739,15 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT));\ +} while(0) + #ifndef CONFIG_CPU_MIPSR6 -#define StoreW(addr, value, res) \ +#define _StoreW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ - "1:\t"user_swl("%1", "3(%2)")"\n" \ - "2:\t"user_swr("%1", "(%2)")"\n\t" \ + "1:\t"type##_swl("%1", "3(%2)")"\n" \ + "2:\t"type##_swr("%1", "(%2)")"\n\t"\ "li\t%0, 0\n" \ "3:\n\t" \ ".insn\n\t" \ @@ -707,9 +760,11 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +} while(0) -#define StoreDW(addr, value, res) \ +#define _StoreDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ "1:\tsdl\t%1, 7(%2)\n" \ "2:\tsdr\t%1, (%2)\n\t" \ @@ -725,20 +780,23 @@ extern void show_registers(struct pt_regs *regs); STR(PTR)"\t2b, 4b\n\t" \ ".previous" \ : "=r" (res) \ - : "r" (value), "r" (addr), "i" (-EFAULT)); + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +} while(0) + #else /* MIPSR6 has no swl and sdl instructions */ -#define StoreW(addr, value, res) \ +#define _StoreW(addr, value, res, type) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_sb("%1", "0(%2)")"\n\t" \ + "1:"type##_sb("%1", "0(%2)")"\n\t" \ "srl\t$1, %1, 0x8\n\t" \ - "2:"user_sb("$1", "1(%2)")"\n\t" \ + "2:"type##_sb("$1", "1(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "3:"user_sb("$1", "2(%2)")"\n\t" \ + "3:"type##_sb("$1", "2(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "4:"user_sb("$1", "3(%2)")"\n\t" \ + "4:"type##_sb("$1", "3(%2)")"\n\t" \ ".set\tpop\n\t" \ "li\t%0, 0\n" \ "10:\n\t" \ @@ -755,9 +813,11 @@ extern void show_registers(struct pt_regs *regs); ".previous" \ : "=&r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT) \ - : "memory"); + : "memory"); \ +} while(0) -#define StoreDW(addr, value, res) \ +#define _StoreDW(addr, value, res) \ +do { \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ @@ -797,10 +857,28 @@ extern void show_registers(struct pt_regs *regs); ".previous" \ : "=&r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT) \ - : "memory"); + : "memory"); \ +} while(0) + #endif /* CONFIG_CPU_MIPSR6 */ #endif +#define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel) +#define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user) +#define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel) +#define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user) +#define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel) +#define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user) +#define LoadW(addr, value, res) _LoadW(addr, value, res, kernel) +#define LoadWE(addr, value, res) _LoadW(addr, value, res, user) +#define LoadDW(addr, value, res) _LoadDW(addr, value, res) + +#define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel) +#define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user) +#define StoreW(addr, value, res) _StoreW(addr, value, res, kernel) +#define StoreWE(addr, value, res) _StoreW(addr, value, res, user) +#define StoreDW(addr, value, res) _StoreDW(addr, value, res) + static void emulate_load_store_insn(struct pt_regs *regs, void __user *addr, unsigned int __user *pc) { @@ -872,7 +950,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, set_fs(seg); goto sigbus; } - LoadHW(addr, value, res); + LoadHWE(addr, value, res); if (res) { set_fs(seg); goto fault; @@ -885,7 +963,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, set_fs(seg); goto sigbus; } - LoadW(addr, value, res); + LoadWE(addr, value, res); if (res) { set_fs(seg); goto fault; @@ -898,7 +976,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, set_fs(seg); goto sigbus; } - LoadHWU(addr, value, res); + LoadHWUE(addr, value, res); if (res) { set_fs(seg); goto fault; @@ -913,7 +991,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, } compute_return_epc(regs); value = regs->regs[insn.spec3_format.rt]; - StoreHW(addr, value, res); + StoreHWE(addr, value, res); if (res) { set_fs(seg); goto fault; @@ -926,7 +1004,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, } compute_return_epc(regs); value = regs->regs[insn.spec3_format.rt]; - StoreW(addr, value, res); + StoreWE(addr, value, res); if (res) { set_fs(seg); goto fault; @@ -943,7 +1021,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 2)) goto sigbus; - LoadHW(addr, value, res); + if (config_enabled(CONFIG_EVA)) { + if (segment_eq(get_fs(), get_ds())) + LoadHW(addr, value, res); + else + LoadHWE(addr, value, res); + } else { + LoadHW(addr, value, res); + } + if (res) goto fault; compute_return_epc(regs); @@ -954,7 +1040,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 4)) goto sigbus; - LoadW(addr, value, res); + if (config_enabled(CONFIG_EVA)) { + if (segment_eq(get_fs(), get_ds())) + LoadW(addr, value, res); + else + LoadWE(addr, value, res); + } else { + LoadW(addr, value, res); + } + if (res) goto fault; compute_return_epc(regs); @@ -965,7 +1059,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 2)) goto sigbus; - LoadHWU(addr, value, res); + if (config_enabled(CONFIG_EVA)) { + if (segment_eq(get_fs(), get_ds())) + LoadHWU(addr, value, res); + else + LoadHWUE(addr, value, res); + } else { + LoadHWU(addr, value, res); + } + if (res) goto fault; compute_return_epc(regs); @@ -1024,7 +1126,16 @@ static void emulate_load_store_insn(struct pt_regs *regs, compute_return_epc(regs); value = regs->regs[insn.i_format.rt]; - StoreHW(addr, value, res); + + if (config_enabled(CONFIG_EVA)) { + if (segment_eq(get_fs(), get_ds())) + StoreHW(addr, value, res); + else + StoreHWE(addr, value, res); + } else { + StoreHW(addr, value, res); + } + if (res) goto fault; break; @@ -1035,7 +1146,16 @@ static void emulate_load_store_insn(struct pt_regs *regs, compute_return_epc(regs); value = regs->regs[insn.i_format.rt]; - StoreW(addr, value, res); + + if (config_enabled(CONFIG_EVA)) { + if (segment_eq(get_fs(), get_ds())) + StoreW(addr, value, res); + else + StoreWE(addr, value, res); + } else { + StoreW(addr, value, res); + } + if (res) goto fault; break; @@ -1076,7 +1196,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, own_fpu(1); /* Restore FPU state. */ /* Signal if something went wrong. */ - process_fpemu_return(res, fault_addr); + process_fpemu_return(res, fault_addr, 0); if (res == 0) break; @@ -1511,7 +1631,7 @@ fpu_emul: own_fpu(1); /* restore FPU state */ /* If something went wrong, signal */ - process_fpemu_return(res, fault_addr); + process_fpemu_return(res, fault_addr, 0); if (res == 0) goto success; diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile index 401fe027c261..637ebbebd549 100644 --- a/arch/mips/kvm/Makefile +++ b/arch/mips/kvm/Makefile @@ -1,13 +1,15 @@ # Makefile for KVM support for MIPS # -common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) +common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm -kvm-objs := $(common-objs) mips.o emulate.o locore.o \ +common-objs-$(CONFIG_CPU_HAS_MSA) += msa.o + +kvm-objs := $(common-objs-y) mips.o emulate.o locore.o \ interrupt.o stats.o commpage.o \ - dyntrans.o trap_emul.o + dyntrans.o trap_emul.o fpu.o obj-$(CONFIG_KVM) += kvm.o obj-y += callback.o tlb.o diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index fb3e8dfd1ff6..6230f376a44e 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -884,6 +884,84 @@ enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu) return EMULATE_DONE; } +/** + * kvm_mips_config1_wrmask() - Find mask of writable bits in guest Config1 + * @vcpu: Virtual CPU. + * + * Finds the mask of bits which are writable in the guest's Config1 CP0 + * register, by userland (currently read-only to the guest). + */ +unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu) +{ + unsigned int mask = 0; + + /* Permit FPU to be present if FPU is supported */ + if (kvm_mips_guest_can_have_fpu(&vcpu->arch)) + mask |= MIPS_CONF1_FP; + + return mask; +} + +/** + * kvm_mips_config3_wrmask() - Find mask of writable bits in guest Config3 + * @vcpu: Virtual CPU. + * + * Finds the mask of bits which are writable in the guest's Config3 CP0 + * register, by userland (currently read-only to the guest). + */ +unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu) +{ + /* Config4 is optional */ + unsigned int mask = MIPS_CONF_M; + + /* Permit MSA to be present if MSA is supported */ + if (kvm_mips_guest_can_have_msa(&vcpu->arch)) + mask |= MIPS_CONF3_MSA; + + return mask; +} + +/** + * kvm_mips_config4_wrmask() - Find mask of writable bits in guest Config4 + * @vcpu: Virtual CPU. + * + * Finds the mask of bits which are writable in the guest's Config4 CP0 + * register, by userland (currently read-only to the guest). + */ +unsigned int kvm_mips_config4_wrmask(struct kvm_vcpu *vcpu) +{ + /* Config5 is optional */ + return MIPS_CONF_M; +} + +/** + * kvm_mips_config5_wrmask() - Find mask of writable bits in guest Config5 + * @vcpu: Virtual CPU. + * + * Finds the mask of bits which are writable in the guest's Config5 CP0 + * register, by the guest itself. + */ +unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu) +{ + unsigned int mask = 0; + + /* Permit MSAEn changes if MSA supported and enabled */ + if (kvm_mips_guest_has_msa(&vcpu->arch)) + mask |= MIPS_CONF5_MSAEN; + + /* + * Permit guest FPU mode changes if FPU is enabled and the relevant + * feature exists according to FIR register. + */ + if (kvm_mips_guest_has_fpu(&vcpu->arch)) { + if (cpu_has_fre) + mask |= MIPS_CONF5_FRE; + /* We don't support UFR or UFE */ + } + + return mask; +} + enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause, struct kvm_run *run, struct kvm_vcpu *vcpu) @@ -1021,18 +1099,114 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, kvm_mips_write_compare(vcpu, vcpu->arch.gprs[rt]); } else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) { - kvm_write_c0_guest_status(cop0, - vcpu->arch.gprs[rt]); + unsigned int old_val, val, change; + + old_val = kvm_read_c0_guest_status(cop0); + val = vcpu->arch.gprs[rt]; + change = val ^ old_val; + + /* Make sure that the NMI bit is never set */ + val &= ~ST0_NMI; + + /* + * Don't allow CU1 or FR to be set unless FPU + * capability enabled and exists in guest + * configuration. + */ + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + val &= ~(ST0_CU1 | ST0_FR); + + /* + * Also don't allow FR to be set if host doesn't + * support it. + */ + if (!(current_cpu_data.fpu_id & MIPS_FPIR_F64)) + val &= ~ST0_FR; + + + /* Handle changes in FPU mode */ + preempt_disable(); + + /* + * FPU and Vector register state is made + * UNPREDICTABLE by a change of FR, so don't + * even bother saving it. + */ + if (change & ST0_FR) + kvm_drop_fpu(vcpu); + + /* + * If MSA state is already live, it is undefined + * how it interacts with FR=0 FPU state, and we + * don't want to hit reserved instruction + * exceptions trying to save the MSA state later + * when CU=1 && FR=1, so play it safe and save + * it first. + */ + if (change & ST0_CU1 && !(val & ST0_FR) && + vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) + kvm_lose_fpu(vcpu); + /* - * Make sure that CU1 and NMI bits are - * never set + * Propagate CU1 (FPU enable) changes + * immediately if the FPU context is already + * loaded. When disabling we leave the context + * loaded so it can be quickly enabled again in + * the near future. */ - kvm_clear_c0_guest_status(cop0, - (ST0_CU1 | ST0_NMI)); + if (change & ST0_CU1 && + vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) + change_c0_status(ST0_CU1, val); + + preempt_enable(); + + kvm_write_c0_guest_status(cop0, val); #ifdef CONFIG_KVM_MIPS_DYN_TRANS - kvm_mips_trans_mtc0(inst, opc, vcpu); + /* + * If FPU present, we need CU1/FR bits to take + * effect fairly soon. + */ + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + kvm_mips_trans_mtc0(inst, opc, vcpu); #endif + } else if ((rd == MIPS_CP0_CONFIG) && (sel == 5)) { + unsigned int old_val, val, change, wrmask; + + old_val = kvm_read_c0_guest_config5(cop0); + val = vcpu->arch.gprs[rt]; + + /* Only a few bits are writable in Config5 */ + wrmask = kvm_mips_config5_wrmask(vcpu); + change = (val ^ old_val) & wrmask; + val = old_val ^ change; + + + /* Handle changes in FPU/MSA modes */ + preempt_disable(); + + /* + * Propagate FRE changes immediately if the FPU + * context is already loaded. + */ + if (change & MIPS_CONF5_FRE && + vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) + change_c0_config5(MIPS_CONF5_FRE, val); + + /* + * Propagate MSAEn changes immediately if the + * MSA context is already loaded. When disabling + * we leave the context loaded so it can be + * quickly enabled again in the near future. + */ + if (change & MIPS_CONF5_MSAEN && + vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) + change_c0_config5(MIPS_CONF5_MSAEN, + val); + + preempt_enable(); + + kvm_write_c0_guest_config5(cop0, val); } else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) { uint32_t old_cause, new_cause; @@ -1970,6 +2144,146 @@ enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause, return er; } +enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering TRAP @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_TRAP << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_err("Trying to deliver TRAP when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result kvm_mips_emulate_msafpe_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering MSAFPE @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_MSAFPE << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_err("Trying to deliver MSAFPE when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering FPE @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_FPE << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_err("Trying to deliver FPE when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result kvm_mips_emulate_msadis_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering MSADIS @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_MSADIS << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_err("Trying to deliver MSADIS when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + /* ll/sc, rdhwr, sync emulation */ #define OPCODE 0xfc000000 @@ -2176,6 +2490,10 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause, case T_SYSCALL: case T_BREAK: case T_RES_INST: + case T_TRAP: + case T_MSAFPE: + case T_FPE: + case T_MSADIS: break; case T_COP_UNUSABLE: diff --git a/arch/mips/kvm/fpu.S b/arch/mips/kvm/fpu.S new file mode 100644 index 000000000000..531fbf5131c0 --- /dev/null +++ b/arch/mips/kvm/fpu.S @@ -0,0 +1,122 @@ +/* + * 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. + * + * FPU context handling code for KVM. + * + * Copyright (C) 2015 Imagination Technologies Ltd. + */ + +#include <asm/asm.h> +#include <asm/asm-offsets.h> +#include <asm/fpregdef.h> +#include <asm/mipsregs.h> +#include <asm/regdef.h> + + .set noreorder + .set noat + +LEAF(__kvm_save_fpu) + .set push + .set mips64r2 + SET_HARDFLOAT + mfc0 t0, CP0_STATUS + sll t0, t0, 5 # is Status.FR set? + bgez t0, 1f # no: skip odd doubles + nop + sdc1 $f1, VCPU_FPR1(a0) + sdc1 $f3, VCPU_FPR3(a0) + sdc1 $f5, VCPU_FPR5(a0) + sdc1 $f7, VCPU_FPR7(a0) + sdc1 $f9, VCPU_FPR9(a0) + sdc1 $f11, VCPU_FPR11(a0) + sdc1 $f13, VCPU_FPR13(a0) + sdc1 $f15, VCPU_FPR15(a0) + sdc1 $f17, VCPU_FPR17(a0) + sdc1 $f19, VCPU_FPR19(a0) + sdc1 $f21, VCPU_FPR21(a0) + sdc1 $f23, VCPU_FPR23(a0) + sdc1 $f25, VCPU_FPR25(a0) + sdc1 $f27, VCPU_FPR27(a0) + sdc1 $f29, VCPU_FPR29(a0) + sdc1 $f31, VCPU_FPR31(a0) +1: sdc1 $f0, VCPU_FPR0(a0) + sdc1 $f2, VCPU_FPR2(a0) + sdc1 $f4, VCPU_FPR4(a0) + sdc1 $f6, VCPU_FPR6(a0) + sdc1 $f8, VCPU_FPR8(a0) + sdc1 $f10, VCPU_FPR10(a0) + sdc1 $f12, VCPU_FPR12(a0) + sdc1 $f14, VCPU_FPR14(a0) + sdc1 $f16, VCPU_FPR16(a0) + sdc1 $f18, VCPU_FPR18(a0) + sdc1 $f20, VCPU_FPR20(a0) + sdc1 $f22, VCPU_FPR22(a0) + sdc1 $f24, VCPU_FPR24(a0) + sdc1 $f26, VCPU_FPR26(a0) + sdc1 $f28, VCPU_FPR28(a0) + jr ra + sdc1 $f30, VCPU_FPR30(a0) + .set pop + END(__kvm_save_fpu) + +LEAF(__kvm_restore_fpu) + .set push + .set mips64r2 + SET_HARDFLOAT + mfc0 t0, CP0_STATUS + sll t0, t0, 5 # is Status.FR set? + bgez t0, 1f # no: skip odd doubles + nop + ldc1 $f1, VCPU_FPR1(a0) + ldc1 $f3, VCPU_FPR3(a0) + ldc1 $f5, VCPU_FPR5(a0) + ldc1 $f7, VCPU_FPR7(a0) + ldc1 $f9, VCPU_FPR9(a0) + ldc1 $f11, VCPU_FPR11(a0) + ldc1 $f13, VCPU_FPR13(a0) + ldc1 $f15, VCPU_FPR15(a0) + ldc1 $f17, VCPU_FPR17(a0) + ldc1 $f19, VCPU_FPR19(a0) + ldc1 $f21, VCPU_FPR21(a0) + ldc1 $f23, VCPU_FPR23(a0) + ldc1 $f25, VCPU_FPR25(a0) + ldc1 $f27, VCPU_FPR27(a0) + ldc1 $f29, VCPU_FPR29(a0) + ldc1 $f31, VCPU_FPR31(a0) +1: ldc1 $f0, VCPU_FPR0(a0) + ldc1 $f2, VCPU_FPR2(a0) + ldc1 $f4, VCPU_FPR4(a0) + ldc1 $f6, VCPU_FPR6(a0) + ldc1 $f8, VCPU_FPR8(a0) + ldc1 $f10, VCPU_FPR10(a0) + ldc1 $f12, VCPU_FPR12(a0) + ldc1 $f14, VCPU_FPR14(a0) + ldc1 $f16, VCPU_FPR16(a0) + ldc1 $f18, VCPU_FPR18(a0) + ldc1 $f20, VCPU_FPR20(a0) + ldc1 $f22, VCPU_FPR22(a0) + ldc1 $f24, VCPU_FPR24(a0) + ldc1 $f26, VCPU_FPR26(a0) + ldc1 $f28, VCPU_FPR28(a0) + jr ra + ldc1 $f30, VCPU_FPR30(a0) + .set pop + END(__kvm_restore_fpu) + +LEAF(__kvm_restore_fcsr) + .set push + SET_HARDFLOAT + lw t0, VCPU_FCR31(a0) + /* + * The ctc1 must stay at this offset in __kvm_restore_fcsr. + * See kvm_mips_csr_die_notify() which handles t0 containing a value + * which triggers an FP Exception, which must be stepped over and + * ignored since the set cause bits must remain there for the guest. + */ + ctc1 t0, fcr31 + jr ra + nop + .set pop + END(__kvm_restore_fcsr) diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index 4a68b176d6e4..c567240386a0 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -36,6 +36,8 @@ #define PT_HOST_USERLOCAL PT_EPC #define CP0_DDATA_LO $28,3 +#define CP0_CONFIG3 $16,3 +#define CP0_CONFIG5 $16,5 #define CP0_EBASE $15,1 #define CP0_INTCTL $12,1 @@ -353,6 +355,42 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) LONG_L k0, VCPU_HOST_EBASE(k1) mtc0 k0,CP0_EBASE + /* + * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't + * trigger FPE for pending exceptions. + */ + .set at + and v1, v0, ST0_CU1 + beqz v1, 1f + nop + .set push + SET_HARDFLOAT + cfc1 t0, fcr31 + sw t0, VCPU_FCR31(k1) + ctc1 zero,fcr31 + .set pop + .set noat +1: + +#ifdef CONFIG_CPU_HAS_MSA + /* + * If MSA is enabled, save MSACSR and clear it so that later + * instructions don't trigger MSAFPE for pending exceptions. + */ + mfc0 t0, CP0_CONFIG3 + ext t0, t0, 28, 1 /* MIPS_CONF3_MSAP */ + beqz t0, 1f + nop + mfc0 t0, CP0_CONFIG5 + ext t0, t0, 27, 1 /* MIPS_CONF5_MSAEN */ + beqz t0, 1f + nop + _cfcmsa t0, MSA_CSR + sw t0, VCPU_MSA_CSR(k1) + _ctcmsa MSA_CSR, zero +1: +#endif + /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */ .set at and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE) diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index c9eccf5df912..bb68e8d520e8 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -11,6 +11,7 @@ #include <linux/errno.h> #include <linux/err.h> +#include <linux/kdebug.h> #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/fs.h> @@ -48,6 +49,10 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "syscall", VCPU_STAT(syscall_exits), KVM_STAT_VCPU }, { "resvd_inst", VCPU_STAT(resvd_inst_exits), KVM_STAT_VCPU }, { "break_inst", VCPU_STAT(break_inst_exits), KVM_STAT_VCPU }, + { "trap_inst", VCPU_STAT(trap_inst_exits), KVM_STAT_VCPU }, + { "msa_fpe", VCPU_STAT(msa_fpe_exits), KVM_STAT_VCPU }, + { "fpe", VCPU_STAT(fpe_exits), KVM_STAT_VCPU }, + { "msa_disabled", VCPU_STAT(msa_disabled_exits), KVM_STAT_VCPU }, { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU }, { "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU }, { "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU }, @@ -504,10 +509,13 @@ static u64 kvm_mips_get_one_regs[] = { KVM_REG_MIPS_CP0_STATUS, KVM_REG_MIPS_CP0_CAUSE, KVM_REG_MIPS_CP0_EPC, + KVM_REG_MIPS_CP0_PRID, KVM_REG_MIPS_CP0_CONFIG, KVM_REG_MIPS_CP0_CONFIG1, KVM_REG_MIPS_CP0_CONFIG2, KVM_REG_MIPS_CP0_CONFIG3, + KVM_REG_MIPS_CP0_CONFIG4, + KVM_REG_MIPS_CP0_CONFIG5, KVM_REG_MIPS_CP0_CONFIG7, KVM_REG_MIPS_CP0_ERROREPC, @@ -520,10 +528,14 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_fpu_struct *fpu = &vcpu->arch.fpu; int ret; s64 v; + s64 vs[2]; + unsigned int idx; switch (reg->id) { + /* General purpose registers */ case KVM_REG_MIPS_R0 ... KVM_REG_MIPS_R31: v = (long)vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0]; break; @@ -537,6 +549,67 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, v = (long)vcpu->arch.pc; break; + /* Floating point registers */ + case KVM_REG_MIPS_FPR_32(0) ... KVM_REG_MIPS_FPR_32(31): + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_FPR_32(0); + /* Odd singles in top of even double when FR=0 */ + if (kvm_read_c0_guest_status(cop0) & ST0_FR) + v = get_fpr32(&fpu->fpr[idx], 0); + else + v = get_fpr32(&fpu->fpr[idx & ~1], idx & 1); + break; + case KVM_REG_MIPS_FPR_64(0) ... KVM_REG_MIPS_FPR_64(31): + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_FPR_64(0); + /* Can't access odd doubles in FR=0 mode */ + if (idx & 1 && !(kvm_read_c0_guest_status(cop0) & ST0_FR)) + return -EINVAL; + v = get_fpr64(&fpu->fpr[idx], 0); + break; + case KVM_REG_MIPS_FCR_IR: + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + v = boot_cpu_data.fpu_id; + break; + case KVM_REG_MIPS_FCR_CSR: + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + v = fpu->fcr31; + break; + + /* MIPS SIMD Architecture (MSA) registers */ + case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31): + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + /* Can't access MSA registers in FR=0 mode */ + if (!(kvm_read_c0_guest_status(cop0) & ST0_FR)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_VEC_128(0); +#ifdef CONFIG_CPU_LITTLE_ENDIAN + /* least significant byte first */ + vs[0] = get_fpr64(&fpu->fpr[idx], 0); + vs[1] = get_fpr64(&fpu->fpr[idx], 1); +#else + /* most significant byte first */ + vs[0] = get_fpr64(&fpu->fpr[idx], 1); + vs[1] = get_fpr64(&fpu->fpr[idx], 0); +#endif + break; + case KVM_REG_MIPS_MSA_IR: + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + v = boot_cpu_data.msa_id; + break; + case KVM_REG_MIPS_MSA_CSR: + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + v = fpu->msacsr; + break; + + /* Co-processor 0 registers */ case KVM_REG_MIPS_CP0_INDEX: v = (long)kvm_read_c0_guest_index(cop0); break; @@ -573,8 +646,8 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_EPC: v = (long)kvm_read_c0_guest_epc(cop0); break; - case KVM_REG_MIPS_CP0_ERROREPC: - v = (long)kvm_read_c0_guest_errorepc(cop0); + case KVM_REG_MIPS_CP0_PRID: + v = (long)kvm_read_c0_guest_prid(cop0); break; case KVM_REG_MIPS_CP0_CONFIG: v = (long)kvm_read_c0_guest_config(cop0); @@ -588,9 +661,18 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_CONFIG3: v = (long)kvm_read_c0_guest_config3(cop0); break; + case KVM_REG_MIPS_CP0_CONFIG4: + v = (long)kvm_read_c0_guest_config4(cop0); + break; + case KVM_REG_MIPS_CP0_CONFIG5: + v = (long)kvm_read_c0_guest_config5(cop0); + break; case KVM_REG_MIPS_CP0_CONFIG7: v = (long)kvm_read_c0_guest_config7(cop0); break; + case KVM_REG_MIPS_CP0_ERROREPC: + v = (long)kvm_read_c0_guest_errorepc(cop0); + break; /* registers to be handled specially */ case KVM_REG_MIPS_CP0_COUNT: case KVM_REG_MIPS_COUNT_CTL: @@ -612,6 +694,10 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, u32 v32 = (u32)v; return put_user(v32, uaddr32); + } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { + void __user *uaddr = (void __user *)(long)reg->addr; + + return copy_to_user(uaddr, vs, 16); } else { return -EINVAL; } @@ -621,7 +707,10 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { struct mips_coproc *cop0 = vcpu->arch.cop0; - u64 v; + struct mips_fpu_struct *fpu = &vcpu->arch.fpu; + s64 v; + s64 vs[2]; + unsigned int idx; if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) { u64 __user *uaddr64 = (u64 __user *)(long)reg->addr; @@ -635,11 +724,16 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, if (get_user(v32, uaddr32) != 0) return -EFAULT; v = (s64)v32; + } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { + void __user *uaddr = (void __user *)(long)reg->addr; + + return copy_from_user(vs, uaddr, 16); } else { return -EINVAL; } switch (reg->id) { + /* General purpose registers */ case KVM_REG_MIPS_R0: /* Silently ignore requests to set $0 */ break; @@ -656,6 +750,64 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, vcpu->arch.pc = v; break; + /* Floating point registers */ + case KVM_REG_MIPS_FPR_32(0) ... KVM_REG_MIPS_FPR_32(31): + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_FPR_32(0); + /* Odd singles in top of even double when FR=0 */ + if (kvm_read_c0_guest_status(cop0) & ST0_FR) + set_fpr32(&fpu->fpr[idx], 0, v); + else + set_fpr32(&fpu->fpr[idx & ~1], idx & 1, v); + break; + case KVM_REG_MIPS_FPR_64(0) ... KVM_REG_MIPS_FPR_64(31): + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_FPR_64(0); + /* Can't access odd doubles in FR=0 mode */ + if (idx & 1 && !(kvm_read_c0_guest_status(cop0) & ST0_FR)) + return -EINVAL; + set_fpr64(&fpu->fpr[idx], 0, v); + break; + case KVM_REG_MIPS_FCR_IR: + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + /* Read-only */ + break; + case KVM_REG_MIPS_FCR_CSR: + if (!kvm_mips_guest_has_fpu(&vcpu->arch)) + return -EINVAL; + fpu->fcr31 = v; + break; + + /* MIPS SIMD Architecture (MSA) registers */ + case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31): + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + idx = reg->id - KVM_REG_MIPS_VEC_128(0); +#ifdef CONFIG_CPU_LITTLE_ENDIAN + /* least significant byte first */ + set_fpr64(&fpu->fpr[idx], 0, vs[0]); + set_fpr64(&fpu->fpr[idx], 1, vs[1]); +#else + /* most significant byte first */ + set_fpr64(&fpu->fpr[idx], 1, vs[0]); + set_fpr64(&fpu->fpr[idx], 0, vs[1]); +#endif + break; + case KVM_REG_MIPS_MSA_IR: + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + /* Read-only */ + break; + case KVM_REG_MIPS_MSA_CSR: + if (!kvm_mips_guest_has_msa(&vcpu->arch)) + return -EINVAL; + fpu->msacsr = v; + break; + + /* Co-processor 0 registers */ case KVM_REG_MIPS_CP0_INDEX: kvm_write_c0_guest_index(cop0, v); break; @@ -686,6 +838,9 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_EPC: kvm_write_c0_guest_epc(cop0, v); break; + case KVM_REG_MIPS_CP0_PRID: + kvm_write_c0_guest_prid(cop0, v); + break; case KVM_REG_MIPS_CP0_ERROREPC: kvm_write_c0_guest_errorepc(cop0, v); break; @@ -693,6 +848,12 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_COUNT: case KVM_REG_MIPS_CP0_COMPARE: case KVM_REG_MIPS_CP0_CAUSE: + case KVM_REG_MIPS_CP0_CONFIG: + case KVM_REG_MIPS_CP0_CONFIG1: + case KVM_REG_MIPS_CP0_CONFIG2: + case KVM_REG_MIPS_CP0_CONFIG3: + case KVM_REG_MIPS_CP0_CONFIG4: + case KVM_REG_MIPS_CP0_CONFIG5: case KVM_REG_MIPS_COUNT_CTL: case KVM_REG_MIPS_COUNT_RESUME: case KVM_REG_MIPS_COUNT_HZ: @@ -703,6 +864,33 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, return 0; } +static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, + struct kvm_enable_cap *cap) +{ + int r = 0; + + if (!kvm_vm_ioctl_check_extension(vcpu->kvm, cap->cap)) + return -EINVAL; + if (cap->flags) + return -EINVAL; + if (cap->args[0]) + return -EINVAL; + + switch (cap->cap) { + case KVM_CAP_MIPS_FPU: + vcpu->arch.fpu_enabled = true; + break; + case KVM_CAP_MIPS_MSA: + vcpu->arch.msa_enabled = true; + break; + default: + r = -EINVAL; + break; + } + + return r; +} + long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -760,6 +948,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, r = kvm_vcpu_ioctl_interrupt(vcpu, &irq); break; } + case KVM_ENABLE_CAP: { + struct kvm_enable_cap cap; + + r = -EFAULT; + if (copy_from_user(&cap, argp, sizeof(cap))) + goto out; + r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap); + break; + } default: r = -ENOIOCTLCMD; } @@ -868,11 +1065,30 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) switch (ext) { case KVM_CAP_ONE_REG: + case KVM_CAP_ENABLE_CAP: r = 1; break; case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; + case KVM_CAP_MIPS_FPU: + r = !!cpu_has_fpu; + break; + case KVM_CAP_MIPS_MSA: + /* + * We don't support MSA vector partitioning yet: + * 1) It would require explicit support which can't be tested + * yet due to lack of support in current hardware. + * 2) It extends the state that would need to be saved/restored + * by e.g. QEMU for migration. + * + * When vector partitioning hardware becomes available, support + * could be added by requiring a flag when enabling + * KVM_CAP_MIPS_MSA capability to indicate that userland knows + * to save/restore the appropriate extra state. + */ + r = cpu_has_msa && !(boot_cpu_data.msa_id & MSA_IR_WRPF); + break; default: r = 0; break; @@ -1119,6 +1335,30 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) ret = kvm_mips_callbacks->handle_break(vcpu); break; + case T_TRAP: + ++vcpu->stat.trap_inst_exits; + trace_kvm_exit(vcpu, TRAP_INST_EXITS); + ret = kvm_mips_callbacks->handle_trap(vcpu); + break; + + case T_MSAFPE: + ++vcpu->stat.msa_fpe_exits; + trace_kvm_exit(vcpu, MSA_FPE_EXITS); + ret = kvm_mips_callbacks->handle_msa_fpe(vcpu); + break; + + case T_FPE: + ++vcpu->stat.fpe_exits; + trace_kvm_exit(vcpu, FPE_EXITS); + ret = kvm_mips_callbacks->handle_fpe(vcpu); + break; + + case T_MSADIS: + ++vcpu->stat.msa_disabled_exits; + trace_kvm_exit(vcpu, MSA_DISABLED_EXITS); + ret = kvm_mips_callbacks->handle_msa_disabled(vcpu); + break; + default: kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n", exccode, opc, kvm_get_inst(opc, vcpu), badvaddr, @@ -1146,12 +1386,233 @@ skip_emul: } } + if (ret == RESUME_GUEST) { + /* + * If FPU / MSA are enabled (i.e. the guest's FPU / MSA context + * is live), restore FCR31 / MSACSR. + * + * This should be before returning to the guest exception + * vector, as it may well cause an [MSA] FP exception if there + * are pending exception bits unmasked. (see + * kvm_mips_csr_die_notifier() for how that is handled). + */ + if (kvm_mips_guest_has_fpu(&vcpu->arch) && + read_c0_status() & ST0_CU1) + __kvm_restore_fcsr(&vcpu->arch); + + if (kvm_mips_guest_has_msa(&vcpu->arch) && + read_c0_config5() & MIPS_CONF5_MSAEN) + __kvm_restore_msacsr(&vcpu->arch); + } + /* Disable HTW before returning to guest or host */ htw_stop(); return ret; } +/* Enable FPU for guest and restore context */ +void kvm_own_fpu(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + unsigned int sr, cfg5; + + preempt_disable(); + + sr = kvm_read_c0_guest_status(cop0); + + /* + * If MSA state is already live, it is undefined how it interacts with + * FR=0 FPU state, and we don't want to hit reserved instruction + * exceptions trying to save the MSA state later when CU=1 && FR=1, so + * play it safe and save it first. + * + * In theory we shouldn't ever hit this case since kvm_lose_fpu() should + * get called when guest CU1 is set, however we can't trust the guest + * not to clobber the status register directly via the commpage. + */ + if (cpu_has_msa && sr & ST0_CU1 && !(sr & ST0_FR) && + vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) + kvm_lose_fpu(vcpu); + + /* + * Enable FPU for guest + * We set FR and FRE according to guest context + */ + change_c0_status(ST0_CU1 | ST0_FR, sr); + if (cpu_has_fre) { + cfg5 = kvm_read_c0_guest_config5(cop0); + change_c0_config5(MIPS_CONF5_FRE, cfg5); + } + enable_fpu_hazard(); + + /* If guest FPU state not active, restore it now */ + if (!(vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)) { + __kvm_restore_fpu(&vcpu->arch); + vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_FPU; + } + + preempt_enable(); +} + +#ifdef CONFIG_CPU_HAS_MSA +/* Enable MSA for guest and restore context */ +void kvm_own_msa(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + unsigned int sr, cfg5; + + preempt_disable(); + + /* + * Enable FPU if enabled in guest, since we're restoring FPU context + * anyway. We set FR and FRE according to guest context. + */ + if (kvm_mips_guest_has_fpu(&vcpu->arch)) { + sr = kvm_read_c0_guest_status(cop0); + + /* + * If FR=0 FPU state is already live, it is undefined how it + * interacts with MSA state, so play it safe and save it first. + */ + if (!(sr & ST0_FR) && + (vcpu->arch.fpu_inuse & (KVM_MIPS_FPU_FPU | + KVM_MIPS_FPU_MSA)) == KVM_MIPS_FPU_FPU) + kvm_lose_fpu(vcpu); + + change_c0_status(ST0_CU1 | ST0_FR, sr); + if (sr & ST0_CU1 && cpu_has_fre) { + cfg5 = kvm_read_c0_guest_config5(cop0); + change_c0_config5(MIPS_CONF5_FRE, cfg5); + } + } + + /* Enable MSA for guest */ + set_c0_config5(MIPS_CONF5_MSAEN); + enable_fpu_hazard(); + + switch (vcpu->arch.fpu_inuse & (KVM_MIPS_FPU_FPU | KVM_MIPS_FPU_MSA)) { + case KVM_MIPS_FPU_FPU: + /* + * Guest FPU state already loaded, only restore upper MSA state + */ + __kvm_restore_msa_upper(&vcpu->arch); + vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_MSA; + break; + case 0: + /* Neither FPU or MSA already active, restore full MSA state */ + __kvm_restore_msa(&vcpu->arch); + vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_MSA; + if (kvm_mips_guest_has_fpu(&vcpu->arch)) + vcpu->arch.fpu_inuse |= KVM_MIPS_FPU_FPU; + break; + default: + break; + } + + preempt_enable(); +} +#endif + +/* Drop FPU & MSA without saving it */ +void kvm_drop_fpu(struct kvm_vcpu *vcpu) +{ + preempt_disable(); + if (cpu_has_msa && vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) { + disable_msa(); + vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_MSA; + } + if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) { + clear_c0_status(ST0_CU1 | ST0_FR); + vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_FPU; + } + preempt_enable(); +} + +/* Save and disable FPU & MSA */ +void kvm_lose_fpu(struct kvm_vcpu *vcpu) +{ + /* + * FPU & MSA get disabled in root context (hardware) when it is disabled + * in guest context (software), but the register state in the hardware + * may still be in use. This is why we explicitly re-enable the hardware + * before saving. + */ + + preempt_disable(); + if (cpu_has_msa && vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA) { + set_c0_config5(MIPS_CONF5_MSAEN); + enable_fpu_hazard(); + + __kvm_save_msa(&vcpu->arch); + + /* Disable MSA & FPU */ + disable_msa(); + if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) + clear_c0_status(ST0_CU1 | ST0_FR); + vcpu->arch.fpu_inuse &= ~(KVM_MIPS_FPU_FPU | KVM_MIPS_FPU_MSA); + } else if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) { + set_c0_status(ST0_CU1); + enable_fpu_hazard(); + + __kvm_save_fpu(&vcpu->arch); + vcpu->arch.fpu_inuse &= ~KVM_MIPS_FPU_FPU; + + /* Disable FPU */ + clear_c0_status(ST0_CU1 | ST0_FR); + } + preempt_enable(); +} + +/* + * Step over a specific ctc1 to FCSR and a specific ctcmsa to MSACSR which are + * used to restore guest FCSR/MSACSR state and may trigger a "harmless" FP/MSAFP + * exception if cause bits are set in the value being written. + */ +static int kvm_mips_csr_die_notify(struct notifier_block *self, + unsigned long cmd, void *ptr) +{ + struct die_args *args = (struct die_args *)ptr; + struct pt_regs *regs = args->regs; + unsigned long pc; + + /* Only interested in FPE and MSAFPE */ + if (cmd != DIE_FP && cmd != DIE_MSAFP) + return NOTIFY_DONE; + + /* Return immediately if guest context isn't active */ + if (!(current->flags & PF_VCPU)) + return NOTIFY_DONE; + + /* Should never get here from user mode */ + BUG_ON(user_mode(regs)); + + pc = instruction_pointer(regs); + switch (cmd) { + case DIE_FP: + /* match 2nd instruction in __kvm_restore_fcsr */ + if (pc != (unsigned long)&__kvm_restore_fcsr + 4) + return NOTIFY_DONE; + break; + case DIE_MSAFP: + /* match 2nd/3rd instruction in __kvm_restore_msacsr */ + if (!cpu_has_msa || + pc < (unsigned long)&__kvm_restore_msacsr + 4 || + pc > (unsigned long)&__kvm_restore_msacsr + 8) + return NOTIFY_DONE; + break; + } + + /* Move PC forward a little and continue executing */ + instruction_pointer(regs) += 4; + + return NOTIFY_STOP; +} + +static struct notifier_block kvm_mips_csr_die_notifier = { + .notifier_call = kvm_mips_csr_die_notify, +}; + int __init kvm_mips_init(void) { int ret; @@ -1161,6 +1622,8 @@ int __init kvm_mips_init(void) if (ret) return ret; + register_die_notifier(&kvm_mips_csr_die_notifier); + /* * On MIPS, kernel modules are executed from "mapped space", which * requires TLBs. The TLB handling code is statically linked with @@ -1173,7 +1636,6 @@ int __init kvm_mips_init(void) kvm_mips_release_pfn_clean = kvm_release_pfn_clean; kvm_mips_is_error_pfn = is_error_pfn; - pr_info("KVM/MIPS Initialized\n"); return 0; } @@ -1185,7 +1647,7 @@ void __exit kvm_mips_exit(void) kvm_mips_release_pfn_clean = NULL; kvm_mips_is_error_pfn = NULL; - pr_info("KVM/MIPS unloaded\n"); + unregister_die_notifier(&kvm_mips_csr_die_notifier); } module_init(kvm_mips_init); diff --git a/arch/mips/kvm/msa.S b/arch/mips/kvm/msa.S new file mode 100644 index 000000000000..d02f0c6cc2cc --- /dev/null +++ b/arch/mips/kvm/msa.S @@ -0,0 +1,161 @@ +/* + * 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. + * + * MIPS SIMD Architecture (MSA) context handling code for KVM. + * + * Copyright (C) 2015 Imagination Technologies Ltd. + */ + +#include <asm/asm.h> +#include <asm/asm-offsets.h> +#include <asm/asmmacro.h> +#include <asm/regdef.h> + + .set noreorder + .set noat + +LEAF(__kvm_save_msa) + st_d 0, VCPU_FPR0, a0 + st_d 1, VCPU_FPR1, a0 + st_d 2, VCPU_FPR2, a0 + st_d 3, VCPU_FPR3, a0 + st_d 4, VCPU_FPR4, a0 + st_d 5, VCPU_FPR5, a0 + st_d 6, VCPU_FPR6, a0 + st_d 7, VCPU_FPR7, a0 + st_d 8, VCPU_FPR8, a0 + st_d 9, VCPU_FPR9, a0 + st_d 10, VCPU_FPR10, a0 + st_d 11, VCPU_FPR11, a0 + st_d 12, VCPU_FPR12, a0 + st_d 13, VCPU_FPR13, a0 + st_d 14, VCPU_FPR14, a0 + st_d 15, VCPU_FPR15, a0 + st_d 16, VCPU_FPR16, a0 + st_d 17, VCPU_FPR17, a0 + st_d 18, VCPU_FPR18, a0 + st_d 19, VCPU_FPR19, a0 + st_d 20, VCPU_FPR20, a0 + st_d 21, VCPU_FPR21, a0 + st_d 22, VCPU_FPR22, a0 + st_d 23, VCPU_FPR23, a0 + st_d 24, VCPU_FPR24, a0 + st_d 25, VCPU_FPR25, a0 + st_d 26, VCPU_FPR26, a0 + st_d 27, VCPU_FPR27, a0 + st_d 28, VCPU_FPR28, a0 + st_d 29, VCPU_FPR29, a0 + st_d 30, VCPU_FPR30, a0 + st_d 31, VCPU_FPR31, a0 + jr ra + nop + END(__kvm_save_msa) + +LEAF(__kvm_restore_msa) + ld_d 0, VCPU_FPR0, a0 + ld_d 1, VCPU_FPR1, a0 + ld_d 2, VCPU_FPR2, a0 + ld_d 3, VCPU_FPR3, a0 + ld_d 4, VCPU_FPR4, a0 + ld_d 5, VCPU_FPR5, a0 + ld_d 6, VCPU_FPR6, a0 + ld_d 7, VCPU_FPR7, a0 + ld_d 8, VCPU_FPR8, a0 + ld_d 9, VCPU_FPR9, a0 + ld_d 10, VCPU_FPR10, a0 + ld_d 11, VCPU_FPR11, a0 + ld_d 12, VCPU_FPR12, a0 + ld_d 13, VCPU_FPR13, a0 + ld_d 14, VCPU_FPR14, a0 + ld_d 15, VCPU_FPR15, a0 + ld_d 16, VCPU_FPR16, a0 + ld_d 17, VCPU_FPR17, a0 + ld_d 18, VCPU_FPR18, a0 + ld_d 19, VCPU_FPR19, a0 + ld_d 20, VCPU_FPR20, a0 + ld_d 21, VCPU_FPR21, a0 + ld_d 22, VCPU_FPR22, a0 + ld_d 23, VCPU_FPR23, a0 + ld_d 24, VCPU_FPR24, a0 + ld_d 25, VCPU_FPR25, a0 + ld_d 26, VCPU_FPR26, a0 + ld_d 27, VCPU_FPR27, a0 + ld_d 28, VCPU_FPR28, a0 + ld_d 29, VCPU_FPR29, a0 + ld_d 30, VCPU_FPR30, a0 + ld_d 31, VCPU_FPR31, a0 + jr ra + nop + END(__kvm_restore_msa) + + .macro kvm_restore_msa_upper wr, off, base + .set push + .set noat +#ifdef CONFIG_64BIT + ld $1, \off(\base) + insert_d \wr, 1 +#elif defined(CONFIG_CPU_LITTLE_ENDIAN) + lw $1, \off(\base) + insert_w \wr, 2 + lw $1, (\off+4)(\base) + insert_w \wr, 3 +#else /* CONFIG_CPU_BIG_ENDIAN */ + lw $1, (\off+4)(\base) + insert_w \wr, 2 + lw $1, \off(\base) + insert_w \wr, 3 +#endif + .set pop + .endm + +LEAF(__kvm_restore_msa_upper) + kvm_restore_msa_upper 0, VCPU_FPR0 +8, a0 + kvm_restore_msa_upper 1, VCPU_FPR1 +8, a0 + kvm_restore_msa_upper 2, VCPU_FPR2 +8, a0 + kvm_restore_msa_upper 3, VCPU_FPR3 +8, a0 + kvm_restore_msa_upper 4, VCPU_FPR4 +8, a0 + kvm_restore_msa_upper 5, VCPU_FPR5 +8, a0 + kvm_restore_msa_upper 6, VCPU_FPR6 +8, a0 + kvm_restore_msa_upper 7, VCPU_FPR7 +8, a0 + kvm_restore_msa_upper 8, VCPU_FPR8 +8, a0 + kvm_restore_msa_upper 9, VCPU_FPR9 +8, a0 + kvm_restore_msa_upper 10, VCPU_FPR10+8, a0 + kvm_restore_msa_upper 11, VCPU_FPR11+8, a0 + kvm_restore_msa_upper 12, VCPU_FPR12+8, a0 + kvm_restore_msa_upper 13, VCPU_FPR13+8, a0 + kvm_restore_msa_upper 14, VCPU_FPR14+8, a0 + kvm_restore_msa_upper 15, VCPU_FPR15+8, a0 + kvm_restore_msa_upper 16, VCPU_FPR16+8, a0 + kvm_restore_msa_upper 17, VCPU_FPR17+8, a0 + kvm_restore_msa_upper 18, VCPU_FPR18+8, a0 + kvm_restore_msa_upper 19, VCPU_FPR19+8, a0 + kvm_restore_msa_upper 20, VCPU_FPR20+8, a0 + kvm_restore_msa_upper 21, VCPU_FPR21+8, a0 + kvm_restore_msa_upper 22, VCPU_FPR22+8, a0 + kvm_restore_msa_upper 23, VCPU_FPR23+8, a0 + kvm_restore_msa_upper 24, VCPU_FPR24+8, a0 + kvm_restore_msa_upper 25, VCPU_FPR25+8, a0 + kvm_restore_msa_upper 26, VCPU_FPR26+8, a0 + kvm_restore_msa_upper 27, VCPU_FPR27+8, a0 + kvm_restore_msa_upper 28, VCPU_FPR28+8, a0 + kvm_restore_msa_upper 29, VCPU_FPR29+8, a0 + kvm_restore_msa_upper 30, VCPU_FPR30+8, a0 + kvm_restore_msa_upper 31, VCPU_FPR31+8, a0 + jr ra + nop + END(__kvm_restore_msa_upper) + +LEAF(__kvm_restore_msacsr) + lw t0, VCPU_MSA_CSR(a0) + /* + * The ctcmsa must stay at this offset in __kvm_restore_msacsr. + * See kvm_mips_csr_die_notify() which handles t0 containing a value + * which triggers an MSA FP Exception, which must be stepped over and + * ignored since the set cause bits must remain there for the guest. + */ + _ctcmsa MSA_CSR, t0 + jr ra + nop + END(__kvm_restore_msacsr) diff --git a/arch/mips/kvm/stats.c b/arch/mips/kvm/stats.c index a74d6024c5ad..888bb67070ac 100644 --- a/arch/mips/kvm/stats.c +++ b/arch/mips/kvm/stats.c @@ -25,6 +25,10 @@ char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = { "System Call", "Reserved Inst", "Break Inst", + "Trap Inst", + "MSA FPE", + "FPE", + "MSA Disabled", "D-Cache Flushes", }; diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index b6beb0e07b1b..aed0ac2a4972 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -733,6 +733,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) } } + /* restore guest state to registers */ + kvm_mips_callbacks->vcpu_set_regs(vcpu); + local_irq_restore(flags); } @@ -751,6 +754,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) vcpu->arch.preempt_entryhi = read_c0_entryhi(); vcpu->arch.last_sched_cpu = cpu; + /* save guest state in registers */ + kvm_mips_callbacks->vcpu_get_regs(vcpu); + if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) & ASID_VERSION_MASK)) { kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__, diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index fd7257b70e65..d836ed5b0bc7 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c @@ -39,16 +39,30 @@ static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva) static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) { + struct mips_coproc *cop0 = vcpu->arch.cop0; struct kvm_run *run = vcpu->run; uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; unsigned long cause = vcpu->arch.host_cp0_cause; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; - if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) - er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu); - else + if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) { + /* FPU Unusable */ + if (!kvm_mips_guest_has_fpu(&vcpu->arch) || + (kvm_read_c0_guest_status(cop0) & ST0_CU1) == 0) { + /* + * Unusable/no FPU in guest: + * deliver guest COP1 Unusable Exception + */ + er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu); + } else { + /* Restore FPU state */ + kvm_own_fpu(vcpu); + er = EMULATE_DONE; + } + } else { er = kvm_mips_emulate_inst(cause, opc, run, vcpu); + } switch (er) { case EMULATE_DONE: @@ -330,6 +344,107 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu) return ret; } +static int kvm_trap_emul_handle_trap(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_emulate_trap_exc(cause, opc, run, vcpu); + if (er == EMULATE_DONE) { + ret = RESUME_GUEST; + } else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_msa_fpe(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_emulate_msafpe_exc(cause, opc, run, vcpu); + if (er == EMULATE_DONE) { + ret = RESUME_GUEST; + } else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_fpe(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *)vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_emulate_fpe_exc(cause, opc, run, vcpu); + if (er == EMULATE_DONE) { + ret = RESUME_GUEST; + } else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +/** + * kvm_trap_emul_handle_msa_disabled() - Guest used MSA while disabled in root. + * @vcpu: Virtual CPU context. + * + * Handle when the guest attempts to use MSA when it is disabled. + */ +static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (!kvm_mips_guest_has_msa(&vcpu->arch) || + (kvm_read_c0_guest_status(cop0) & (ST0_CU1 | ST0_FR)) == ST0_CU1) { + /* + * No MSA in guest, or FPU enabled and not in FR=1 mode, + * guest reserved instruction exception + */ + er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); + } else if (!(kvm_read_c0_guest_config5(cop0) & MIPS_CONF5_MSAEN)) { + /* MSA disabled by guest, guest MSA disabled exception */ + er = kvm_mips_emulate_msadis_exc(cause, opc, run, vcpu); + } else { + /* Restore MSA/FPU state */ + kvm_own_msa(vcpu); + er = EMULATE_DONE; + } + + switch (er) { + case EMULATE_DONE: + ret = RESUME_GUEST; + break; + + case EMULATE_FAIL: + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + break; + + default: + BUG(); + } + return ret; +} + static int kvm_trap_emul_vm_init(struct kvm *kvm) { return 0; @@ -351,8 +466,9 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu) * guest will come up as expected, for now we simulate a MIPS 24kc */ kvm_write_c0_guest_prid(cop0, 0x00019300); - kvm_write_c0_guest_config(cop0, - MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + /* Have config1, Cacheable, noncoherent, write-back, write allocate */ + kvm_write_c0_guest_config(cop0, MIPS_CONF_M | (0x3 << CP0C0_K0) | + (0x1 << CP0C0_AR) | (MMU_TYPE_R4000 << CP0C0_MT)); /* Read the cache characteristics from the host Config1 Register */ @@ -368,10 +484,18 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu) (1 << CP0C1_WR) | (1 << CP0C1_CA)); kvm_write_c0_guest_config1(cop0, config1); - kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2); - /* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */ - kvm_write_c0_guest_config3(cop0, MIPS_CONFIG3 | (0 << CP0C3_VInt) | - (1 << CP0C3_ULRI)); + /* Have config3, no tertiary/secondary caches implemented */ + kvm_write_c0_guest_config2(cop0, MIPS_CONF_M); + /* MIPS_CONF_M | (read_c0_config2() & 0xfff) */ + + /* Have config4, UserLocal */ + kvm_write_c0_guest_config3(cop0, MIPS_CONF_M | MIPS_CONF3_ULRI); + + /* Have config5 */ + kvm_write_c0_guest_config4(cop0, MIPS_CONF_M); + + /* No config6 */ + kvm_write_c0_guest_config5(cop0, 0); /* Set Wait IE/IXMT Ignore in Config7, IAR, AR */ kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10)); @@ -416,6 +540,7 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu, { struct mips_coproc *cop0 = vcpu->arch.cop0; int ret = 0; + unsigned int cur, change; switch (reg->id) { case KVM_REG_MIPS_CP0_COUNT: @@ -444,6 +569,44 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu, kvm_write_c0_guest_cause(cop0, v); } break; + case KVM_REG_MIPS_CP0_CONFIG: + /* read-only for now */ + break; + case KVM_REG_MIPS_CP0_CONFIG1: + cur = kvm_read_c0_guest_config1(cop0); + change = (cur ^ v) & kvm_mips_config1_wrmask(vcpu); + if (change) { + v = cur ^ change; + kvm_write_c0_guest_config1(cop0, v); + } + break; + case KVM_REG_MIPS_CP0_CONFIG2: + /* read-only for now */ + break; + case KVM_REG_MIPS_CP0_CONFIG3: + cur = kvm_read_c0_guest_config3(cop0); + change = (cur ^ v) & kvm_mips_config3_wrmask(vcpu); + if (change) { + v = cur ^ change; + kvm_write_c0_guest_config3(cop0, v); + } + break; + case KVM_REG_MIPS_CP0_CONFIG4: + cur = kvm_read_c0_guest_config4(cop0); + change = (cur ^ v) & kvm_mips_config4_wrmask(vcpu); + if (change) { + v = cur ^ change; + kvm_write_c0_guest_config4(cop0, v); + } + break; + case KVM_REG_MIPS_CP0_CONFIG5: + cur = kvm_read_c0_guest_config5(cop0); + change = (cur ^ v) & kvm_mips_config5_wrmask(vcpu); + if (change) { + v = cur ^ change; + kvm_write_c0_guest_config5(cop0, v); + } + break; case KVM_REG_MIPS_COUNT_CTL: ret = kvm_mips_set_count_ctl(vcpu, v); break; @@ -459,6 +622,18 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu, return ret; } +static int kvm_trap_emul_vcpu_get_regs(struct kvm_vcpu *vcpu) +{ + kvm_lose_fpu(vcpu); + + return 0; +} + +static int kvm_trap_emul_vcpu_set_regs(struct kvm_vcpu *vcpu) +{ + return 0; +} + static struct kvm_mips_callbacks kvm_trap_emul_callbacks = { /* exit handlers */ .handle_cop_unusable = kvm_trap_emul_handle_cop_unusable, @@ -470,6 +645,10 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = { .handle_syscall = kvm_trap_emul_handle_syscall, .handle_res_inst = kvm_trap_emul_handle_res_inst, .handle_break = kvm_trap_emul_handle_break, + .handle_trap = kvm_trap_emul_handle_trap, + .handle_msa_fpe = kvm_trap_emul_handle_msa_fpe, + .handle_fpe = kvm_trap_emul_handle_fpe, + .handle_msa_disabled = kvm_trap_emul_handle_msa_disabled, .vm_init = kvm_trap_emul_vm_init, .vcpu_init = kvm_trap_emul_vcpu_init, @@ -483,6 +662,8 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = { .irq_clear = kvm_mips_irq_clear_cb, .get_one_reg = kvm_trap_emul_get_one_reg, .set_one_reg = kvm_trap_emul_set_one_reg, + .vcpu_get_regs = kvm_trap_emul_vcpu_get_regs, + .vcpu_set_regs = kvm_trap_emul_vcpu_set_regs, }; int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks) diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index 39ab3e786e59..0db099ecc016 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -41,7 +41,7 @@ int ltq_soc_type(void) return soc_info.type; } -void prom_free_prom_memory(void) +void __init prom_free_prom_memory(void) { } diff --git a/arch/mips/lantiq/xway/vmmc.c b/arch/mips/lantiq/xway/vmmc.c index 696cd57f6f13..d001bc38908a 100644 --- a/arch/mips/lantiq/xway/vmmc.c +++ b/arch/mips/lantiq/xway/vmmc.c @@ -61,7 +61,6 @@ static struct platform_driver vmmc_driver = { .probe = vmmc_probe, .driver = { .name = "lantiq,vmmc", - .owner = THIS_MODULE, .of_match_table = vmmc_match, }, }; diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index 3b7f65cc4218..a57959e648a6 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c @@ -53,21 +53,6 @@ int proc_dolasatstring(struct ctl_table *table, int write, return 0; } -/* proc function to write EEPROM after changing int entry */ -int proc_dolasatint(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - int r; - - r = proc_dointvec(table, write, buffer, lenp, ppos); - if ((!write) || r) - return r; - - lasat_write_eeprom_info(); - - return 0; -} - #ifdef CONFIG_DS1603 static int rtctmp; @@ -75,11 +60,11 @@ static int rtctmp; int proc_dolasatrtc(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct timespec ts; + struct timespec64 ts; int r; if (!write) { - read_persistent_clock(&ts); + read_persistent_clock64(&ts); rtctmp = ts.tv_sec; /* check for time < 0 and set to 0 */ if (rtctmp < 0) diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 4c721e247ac9..ed88647b57e2 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -76,10 +76,10 @@ LOAD _t1, (offset + UNIT(1))(src); \ LOAD _t2, (offset + UNIT(2))(src); \ LOAD _t3, (offset + UNIT(3))(src); \ + ADDC(_t0, _t1); \ + ADDC(_t2, _t3); \ ADDC(sum, _t0); \ - ADDC(sum, _t1); \ - ADDC(sum, _t2); \ - ADDC(sum, _t3) + ADDC(sum, _t2) #ifdef USE_DOUBLE #define CSUM_BIGCHUNK(src, offset, sum, _t0, _t1, _t2, _t3) \ @@ -504,21 +504,21 @@ LEAF(csum_partial) SUB len, len, 8*NBYTES ADD src, src, 8*NBYTES STORE(t0, UNIT(0)(dst), .Ls_exc\@) - ADDC(sum, t0) + ADDC(t0, t1) STORE(t1, UNIT(1)(dst), .Ls_exc\@) - ADDC(sum, t1) + ADDC(sum, t0) STORE(t2, UNIT(2)(dst), .Ls_exc\@) - ADDC(sum, t2) + ADDC(t2, t3) STORE(t3, UNIT(3)(dst), .Ls_exc\@) - ADDC(sum, t3) + ADDC(sum, t2) STORE(t4, UNIT(4)(dst), .Ls_exc\@) - ADDC(sum, t4) + ADDC(t4, t5) STORE(t5, UNIT(5)(dst), .Ls_exc\@) - ADDC(sum, t5) + ADDC(sum, t4) STORE(t6, UNIT(6)(dst), .Ls_exc\@) - ADDC(sum, t6) + ADDC(t6, t7) STORE(t7, UNIT(7)(dst), .Ls_exc\@) - ADDC(sum, t7) + ADDC(sum, t6) .set reorder /* DADDI_WAR */ ADD dst, dst, 8*NBYTES bgez len, 1b @@ -544,13 +544,13 @@ LEAF(csum_partial) SUB len, len, 4*NBYTES ADD src, src, 4*NBYTES STORE(t0, UNIT(0)(dst), .Ls_exc\@) - ADDC(sum, t0) + ADDC(t0, t1) STORE(t1, UNIT(1)(dst), .Ls_exc\@) - ADDC(sum, t1) + ADDC(sum, t0) STORE(t2, UNIT(2)(dst), .Ls_exc\@) - ADDC(sum, t2) + ADDC(t2, t3) STORE(t3, UNIT(3)(dst), .Ls_exc\@) - ADDC(sum, t3) + ADDC(sum, t2) .set reorder /* DADDI_WAR */ ADD dst, dst, 4*NBYTES beqz len, .Ldone\@ @@ -649,13 +649,13 @@ LEAF(csum_partial) nop # improves slotting #endif STORE(t0, UNIT(0)(dst), .Ls_exc\@) - ADDC(sum, t0) + ADDC(t0, t1) STORE(t1, UNIT(1)(dst), .Ls_exc\@) - ADDC(sum, t1) + ADDC(sum, t0) STORE(t2, UNIT(2)(dst), .Ls_exc\@) - ADDC(sum, t2) + ADDC(t2, t3) STORE(t3, UNIT(3)(dst), .Ls_exc\@) - ADDC(sum, t3) + ADDC(sum, t2) .set reorder /* DADDI_WAR */ ADD dst, dst, 4*NBYTES bne len, rem, 1b diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index 045ea3d47c87..22f04ca2ff3e 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c @@ -29,6 +29,7 @@ struct efi_memory_map_loongson *loongson_memmap; struct loongson_system_configuration loongson_sysconf; u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180}; +u64 loongson_chiptemp[MAX_PACKAGES]; u64 loongson_freqctrl[MAX_PACKAGES]; unsigned long long smp_group[4]; @@ -97,6 +98,10 @@ void __init prom_init_env(void) loongson_chipcfg[1] = 0x900010001fe00180; loongson_chipcfg[2] = 0x900020001fe00180; loongson_chipcfg[3] = 0x900030001fe00180; + loongson_chiptemp[0] = 0x900000001fe0019c; + loongson_chiptemp[1] = 0x900010001fe0019c; + loongson_chiptemp[2] = 0x900020001fe0019c; + loongson_chiptemp[3] = 0x900030001fe0019c; loongson_sysconf.ht_control_base = 0x90000EFDFB000000; loongson_sysconf.workarounds = WORKAROUND_CPUFREQ; } else if (ecpu->cputype == Loongson_3B) { @@ -110,6 +115,10 @@ void __init prom_init_env(void) loongson_chipcfg[1] = 0x900020001fe00180; loongson_chipcfg[2] = 0x900040001fe00180; loongson_chipcfg[3] = 0x900060001fe00180; + loongson_chiptemp[0] = 0x900000001fe0019c; + loongson_chiptemp[1] = 0x900020001fe0019c; + loongson_chiptemp[2] = 0x900040001fe0019c; + loongson_chiptemp[3] = 0x900060001fe0019c; loongson_freqctrl[0] = 0x900000001fe001d0; loongson_freqctrl[1] = 0x900020001fe001d0; loongson_freqctrl[2] = 0x900040001fe001d0; diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c index 003ab4e618b3..4e2575643781 100644 --- a/arch/mips/loongson/common/pci.c +++ b/arch/mips/loongson/common/pci.c @@ -78,6 +78,8 @@ static void __init setup_pcimap(void) #endif } +extern int sbx00_acpi_init(void); + static int __init pcibios_init(void) { setup_pcimap(); @@ -89,6 +91,10 @@ static int __init pcibios_init(void) #endif register_pci_controller(&loongson_pci_controller); +#ifdef CONFIG_CPU_LOONGSON3 + sbx00_acpi_init(); +#endif + return 0; } diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c index b03e37d2071a..ea13764d0a03 100644 --- a/arch/mips/loongson/loongson-3/cop2-ex.c +++ b/arch/mips/loongson/loongson-3/cop2-ex.c @@ -43,7 +43,7 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action, if (!fpu_owned) { set_thread_flag(TIF_USEDFPU); if (!used_math()) { - _init_fpu(); + _init_fpu(current->thread.fpu.fcr31); set_used_math(); } else _restore_fp(current); diff --git a/arch/mips/loongson/loongson-3/hpet.c b/arch/mips/loongson/loongson-3/hpet.c index e898d68668a9..5c21cd3bd339 100644 --- a/arch/mips/loongson/loongson-3/hpet.c +++ b/arch/mips/loongson/loongson-3/hpet.c @@ -162,7 +162,7 @@ static irqreturn_t hpet_irq_handler(int irq, void *data) static struct irqaction hpet_irq = { .handler = hpet_irq_handler, - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, + .flags = IRQF_NOBALANCING | IRQF_TIMER, .name = "hpet", }; diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c index 21221edda7a9..0f75b6b3d218 100644 --- a/arch/mips/loongson/loongson-3/irq.c +++ b/arch/mips/loongson/loongson-3/irq.c @@ -44,6 +44,7 @@ void mach_irq_dispatch(unsigned int pending) static struct irqaction cascade_irqaction = { .handler = no_action, + .flags = IRQF_NO_SUSPEND, .name = "cascade", }; diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 619cfc1a2442..2e5f96275c38 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -2,12 +2,15 @@ # Makefile for the Linux/MIPS kernel FPU emulation. # -obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \ - dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ - dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \ - sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \ - sp_tlong.o sp_flong.o dsemul.o +obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \ + dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \ + dp_tint.o dp_fint.o \ + sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \ + sp_tint.o sp_fint.o \ + dsemul.o -lib-y += ieee754d.o dp_sqrt.o sp_sqrt.o +lib-y += ieee754d.o \ + dp_tlong.o dp_flong.o dp_sqrt.o \ + sp_tlong.o sp_flong.o sp_sqrt.o obj-$(CONFIG_DEBUG_FS) += me-debugfs.o diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b30bf65c7d7d..d31c537ace1d 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -45,6 +45,7 @@ #include <asm/signal.h> #include <asm/uaccess.h> +#include <asm/cpu-info.h> #include <asm/processor.h> #include <asm/fpu_emulator.h> #include <asm/fpu.h> @@ -63,14 +64,14 @@ static int fpux_emu(struct pt_regs *, /* Control registers */ #define FPCREG_RID 0 /* $0 = revision id */ +#define FPCREG_FCCR 25 /* $25 = fccr */ +#define FPCREG_FEXR 26 /* $26 = fexr */ +#define FPCREG_FENR 28 /* $28 = fenr */ #define FPCREG_CSR 31 /* $31 = csr */ -/* Determine rounding mode from the RM bits of the FCSR */ -#define modeindex(v) ((v) & FPU_CSR_RM) - /* convert condition code register number to csr bit */ const unsigned int fpucondbit[8] = { - FPU_CSR_COND0, + FPU_CSR_COND, FPU_CSR_COND1, FPU_CSR_COND2, FPU_CSR_COND3, @@ -843,6 +844,127 @@ do { \ #define DPTOREG(dp, x) DITOREG((dp).bits, x) /* + * Emulate a CFC1 instruction. + */ +static inline void cop1_cfc(struct pt_regs *xcp, struct mips_fpu_struct *ctx, + mips_instruction ir) +{ + u32 fcr31 = ctx->fcr31; + u32 value = 0; + + switch (MIPSInst_RD(ir)) { + case FPCREG_CSR: + value = fcr31; + pr_debug("%p gpr[%d]<-csr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + break; + + case FPCREG_FENR: + if (!cpu_has_mips_r) + break; + value = (fcr31 >> (FPU_CSR_FS_S - MIPS_FENR_FS_S)) & + MIPS_FENR_FS; + value |= fcr31 & (FPU_CSR_ALL_E | FPU_CSR_RM); + pr_debug("%p gpr[%d]<-enr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + break; + + case FPCREG_FEXR: + if (!cpu_has_mips_r) + break; + value = fcr31 & (FPU_CSR_ALL_X | FPU_CSR_ALL_S); + pr_debug("%p gpr[%d]<-exr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + break; + + case FPCREG_FCCR: + if (!cpu_has_mips_r) + break; + value = (fcr31 >> (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) & + MIPS_FCCR_COND0; + value |= (fcr31 >> (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) & + (MIPS_FCCR_CONDX & ~MIPS_FCCR_COND0); + pr_debug("%p gpr[%d]<-ccr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + break; + + case FPCREG_RID: + value = current_cpu_data.fpu_id; + break; + + default: + break; + } + + if (MIPSInst_RT(ir)) + xcp->regs[MIPSInst_RT(ir)] = value; +} + +/* + * Emulate a CTC1 instruction. + */ +static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct *ctx, + mips_instruction ir) +{ + u32 fcr31 = ctx->fcr31; + u32 value; + u32 mask; + + if (MIPSInst_RT(ir) == 0) + value = 0; + else + value = xcp->regs[MIPSInst_RT(ir)]; + + switch (MIPSInst_RD(ir)) { + case FPCREG_CSR: + pr_debug("%p gpr[%d]->csr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + + /* Preserve read-only bits. */ + mask = current_cpu_data.fpu_msk31; + fcr31 = (value & ~mask) | (fcr31 & mask); + break; + + case FPCREG_FENR: + if (!cpu_has_mips_r) + break; + pr_debug("%p gpr[%d]->enr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + fcr31 &= ~(FPU_CSR_FS | FPU_CSR_ALL_E | FPU_CSR_RM); + fcr31 |= (value << (FPU_CSR_FS_S - MIPS_FENR_FS_S)) & + FPU_CSR_FS; + fcr31 |= value & (FPU_CSR_ALL_E | FPU_CSR_RM); + break; + + case FPCREG_FEXR: + if (!cpu_has_mips_r) + break; + pr_debug("%p gpr[%d]->exr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + fcr31 &= ~(FPU_CSR_ALL_X | FPU_CSR_ALL_S); + fcr31 |= value & (FPU_CSR_ALL_X | FPU_CSR_ALL_S); + break; + + case FPCREG_FCCR: + if (!cpu_has_mips_r) + break; + pr_debug("%p gpr[%d]->ccr=%08x\n", + (void *)xcp->cp0_epc, MIPSInst_RT(ir), value); + fcr31 &= ~(FPU_CSR_CONDX | FPU_CSR_COND); + fcr31 |= (value << (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) & + FPU_CSR_COND; + fcr31 |= (value << (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) & + FPU_CSR_CONDX; + break; + + default: + break; + } + + ctx->fcr31 = fcr31; +} + +/* * Emulate the single floating point instruction pointed at by EPC. * Two instructions if the instruction is in a branch delay slot. */ @@ -856,7 +978,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int likely, pc_inc; u32 __user *wva; u64 __user *dva; - u32 value; u32 wval; u64 dval; int sig; @@ -1049,42 +1170,12 @@ emul: case cfc_op: /* cop control register rd -> gpr[rt] */ - if (MIPSInst_RD(ir) == FPCREG_CSR) { - value = ctx->fcr31; - value = (value & ~FPU_CSR_RM) | modeindex(value); - pr_debug("%p gpr[%d]<-csr=%08x\n", - (void *) (xcp->cp0_epc), - MIPSInst_RT(ir), value); - } - else if (MIPSInst_RD(ir) == FPCREG_RID) - value = 0; - else - value = 0; - if (MIPSInst_RT(ir)) - xcp->regs[MIPSInst_RT(ir)] = value; + cop1_cfc(xcp, ctx, ir); break; case ctc_op: /* copregister rd <- rt */ - if (MIPSInst_RT(ir) == 0) - value = 0; - else - value = xcp->regs[MIPSInst_RT(ir)]; - - /* we only have one writable control reg - */ - if (MIPSInst_RD(ir) == FPCREG_CSR) { - pr_debug("%p gpr[%d]->csr=%08x\n", - (void *) (xcp->cp0_epc), - MIPSInst_RT(ir), value); - - /* - * Don't write reserved bits, - * and convert to ieee library modes - */ - ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) | - modeindex(value); - } + cop1_ctc(xcp, ctx, ir); if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { return SIGFPE; } @@ -1103,17 +1194,18 @@ emul: likely = 0; switch (MIPSInst_RT(ir) & 3) { case bcfl_op: - likely = 1; + if (cpu_has_mips_2_3_4_5_r) + likely = 1; + /* Fall through */ case bcf_op: cond = !cond; break; case bctl_op: - likely = 1; + if (cpu_has_mips_2_3_4_5_r) + likely = 1; + /* Fall through */ case bct_op: break; - default: - /* thats an illegal instruction */ - return SIGILL; } set_delay_slot(xcp); @@ -1121,6 +1213,14 @@ emul: /* * Branch taken: emulate dslot instruction */ + unsigned long bcpc; + + /* + * Remember EPC at the branch to point back + * at so that any delay-slot instruction + * signal is not silently ignored. + */ + bcpc = xcp->cp0_epc; xcp->cp0_epc += dec_insn.pc_inc; contpc = MIPSInst_SIMM(ir); @@ -1146,63 +1246,77 @@ emul: * Single step the non-CP1 * instruction in the dslot. */ - return mips_dsemul(xcp, ir, contpc); + sig = mips_dsemul(xcp, ir, + contpc); + if (sig) + xcp->cp0_epc = bcpc; + /* + * SIGILL forces out of + * the emulation loop. + */ + return sig ? sig : SIGILL; } } else contpc = (xcp->cp0_epc + (contpc << 2)); switch (MIPSInst_OPCODE(ir)) { case lwc1_op: - goto emul; - case swc1_op: goto emul; case ldc1_op: case sdc1_op: - if (cpu_has_mips_2_3_4_5 || - cpu_has_mips64) + if (cpu_has_mips_2_3_4_5_r) goto emul; - return SIGILL; - goto emul; + goto bc_sigill; case cop1_op: goto emul; case cop1x_op: - if (cpu_has_mips_4_5 || cpu_has_mips64 || cpu_has_mips32r2) + if (cpu_has_mips_4_5_64_r2_r6) /* its one of ours */ goto emul; - return SIGILL; + goto bc_sigill; case spec_op: - if (!cpu_has_mips_4_5_r) - return SIGILL; + switch (MIPSInst_FUNC(ir)) { + case movc_op: + if (cpu_has_mips_4_5_r) + goto emul; - if (MIPSInst_FUNC(ir) == movc_op) - goto emul; + goto bc_sigill; + } break; + + bc_sigill: + xcp->cp0_epc = bcpc; + return SIGILL; } /* * Single step the non-cp1 * instruction in the dslot */ - return mips_dsemul(xcp, ir, contpc); + sig = mips_dsemul(xcp, ir, contpc); + if (sig) + xcp->cp0_epc = bcpc; + /* SIGILL forces out of the emulation loop. */ + return sig ? sig : SIGILL; } else if (likely) { /* branch not taken */ - /* - * branch likely nullifies - * dslot if not taken - */ - xcp->cp0_epc += dec_insn.pc_inc; - contpc += dec_insn.pc_inc; - /* - * else continue & execute - * dslot as normal insn - */ - } + /* + * branch likely nullifies + * dslot if not taken + */ + xcp->cp0_epc += dec_insn.pc_inc; + contpc += dec_insn.pc_inc; + /* + * else continue & execute + * dslot as normal insn + */ + } break; default: @@ -1216,7 +1330,7 @@ emul: break; case cop1x_op: - if (!cpu_has_mips_4_5 && !cpu_has_mips64 && !cpu_has_mips32r2) + if (!cpu_has_mips_4_5_64_r2_r6) return SIGILL; sig = fpux_emu(xcp, ctx, ir, fault_addr); @@ -1549,7 +1663,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* unary ops */ case fsqrt_op: - if (!cpu_has_mips_4_5_r) + if (!cpu_has_mips_2_3_4_5_r) return SIGILL; handler.u = ieee754sp_sqrt; @@ -1561,14 +1675,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * achieve full IEEE-754 accuracy - however this emulator does. */ case frsqrt_op: - if (!cpu_has_mips_4_5_r2_r6) + if (!cpu_has_mips_4_5_64_r2_r6) return SIGILL; handler.u = fpemu_sp_rsqrt; goto scopuop; case frecip_op: - if (!cpu_has_mips_4_5_r2_r6) + if (!cpu_has_mips_4_5_64_r2_r6) return SIGILL; handler.u = fpemu_sp_recip; @@ -1670,19 +1784,19 @@ copcsr: case ftrunc_op: case fceil_op: case ffloor_op: - if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_2_3_4_5_r) return SIGILL; oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); + ieee754_csr.rm = MIPSInst_FUNC(ir); rv.w = ieee754sp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; goto copcsr; case fcvtl_op: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; SPFROMREG(fs, MIPSInst_FS(ir)); @@ -1694,12 +1808,12 @@ copcsr: case ftruncl_op: case fceill_op: case ffloorl_op: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); + ieee754_csr.rm = MIPSInst_FUNC(ir); rv.l = ieee754sp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; @@ -1763,13 +1877,13 @@ copcsr: * achieve full IEEE-754 accuracy - however this emulator does. */ case frsqrt_op: - if (!cpu_has_mips_4_5_r2_r6) + if (!cpu_has_mips_4_5_64_r2_r6) return SIGILL; handler.u = fpemu_dp_rsqrt; goto dcopuop; case frecip_op: - if (!cpu_has_mips_4_5_r2_r6) + if (!cpu_has_mips_4_5_64_r2_r6) return SIGILL; handler.u = fpemu_dp_recip; @@ -1852,14 +1966,14 @@ dcopuop: oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); + ieee754_csr.rm = MIPSInst_FUNC(ir); rv.w = ieee754dp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; goto copcsr; case fcvtl_op: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; DPFROMREG(fs, MIPSInst_FS(ir)); @@ -1871,12 +1985,12 @@ dcopuop: case ftruncl_op: case fceill_op: case ffloorl_op: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); + ieee754_csr.rm = MIPSInst_FUNC(ir); rv.l = ieee754dp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; @@ -1930,7 +2044,7 @@ dcopuop: case l_fmt: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; DIFROMREG(bits, MIPSInst_FS(ir)); @@ -1994,7 +2108,7 @@ dcopuop: SITOREG(rv.w, MIPSInst_FD(ir)); break; case l_fmt: - if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + if (!cpu_has_mips_3_4_5_64_r2_r6) return SIGILL; DITOREG(rv.l, MIPSInst_FD(ir)); @@ -2081,10 +2195,8 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, xcp->cp0_epc += dec_insn.pc_inc; /* Skip NOPs */ else { /* - * The 'ieee754_csr' is an alias of - * ctx->fcr31. No need to copy ctx->fcr31 to - * ieee754_csr. But ieee754_csr.rm is ieee - * library modes. (not mips rounding mode) + * The 'ieee754_csr' is an alias of ctx->fcr31. + * No need to copy ctx->fcr31 to ieee754_csr. */ sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr); } diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index 7f64577df984..8954ef031f84 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -37,19 +37,20 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) FLUSHYDP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -150,8 +151,6 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) * leaving result in xm, xs and xe. */ xm = xm + ym; - xe = xe; - xs = xs; if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */ xm = XDPSRS1(xm); @@ -160,11 +159,8 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) } else { if (xm >= ym) { xm = xm - ym; - xe = xe; - xs = xs; } else { xm = ym - xm; - xe = xe; xs = ys; } if (xm == 0) diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index 30f95f6e9ac4..a29880e29ae4 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -35,16 +35,11 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) FLUSHYDP; ieee754_clearcx(); /* Even clear inexact flag here */ - if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { - if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) + if (ieee754_class_nan(xc) || ieee754_class_nan(yc)) { + if (sig || + xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) ieee754_setcx(IEEE754_INVALID_OPERATION); - if (cmp & IEEE754_CUN) - return 1; - if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) - return 0; - } - return 0; + return (cmp & IEEE754_CUN) != 0; } else { vx = x.bits; vy = y.bits; diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index bef0e55e5938..f4746f7c5f63 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -39,19 +39,20 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) FLUSHYDP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index ffb69c5830b0..57d09ca5403a 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -22,6 +22,12 @@ #include "ieee754sp.h" #include "ieee754dp.h" +static inline union ieee754dp ieee754dp_nan_fsp(int xs, u64 xm) +{ + return builddp(xs, DP_EMAX + 1 + DP_EBIAS, + xm << (DP_FBITS - SP_FBITS)); +} + union ieee754dp ieee754dp_fsp(union ieee754sp x) { COMPXSP; @@ -34,15 +40,11 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) switch (xc) { case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_nanxcpt(ieee754dp_nan_fsp(xs, xm)); case IEEE754_CLASS_QNAN: - return ieee754dp_nanxcpt(builddp(xs, - DP_EMAX + 1 + DP_EBIAS, - ((u64) xm - << (DP_FBITS - - SP_FBITS)))); + return ieee754dp_nan_fsp(xs, xm); + case IEEE754_CLASS_INF: return ieee754dp_inf(xs); diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index d3acdedb5b9d..d0901f03fa19 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -47,19 +47,20 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) FLUSHYDP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index bccbe90efceb..926d56bf37f2 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -23,44 +23,27 @@ union ieee754dp ieee754dp_neg(union ieee754dp x) { - COMPXDP; - - EXPLODEXDP; - ieee754_clearcx(); - FLUSHXDP; - - /* - * Invert the sign ALWAYS to prevent an endless recursion on - * pow() in libc. - */ - /* quick fix up */ - DPSIGN(x) ^= 1; - - if (xc == IEEE754_CLASS_SNAN) { - union ieee754dp y = ieee754dp_indef(); - ieee754_setcx(IEEE754_INVALID_OPERATION); - DPSIGN(y) = DPSIGN(x); - return ieee754dp_nanxcpt(y); - } - - return x; + unsigned int oldrm; + union ieee754dp y; + + oldrm = ieee754_csr.rm; + ieee754_csr.rm = FPU_CSR_RD; + y = ieee754dp_sub(ieee754dp_zero(0), x); + ieee754_csr.rm = oldrm; + return y; } union ieee754dp ieee754dp_abs(union ieee754dp x) { - COMPXDP; - - EXPLODEXDP; - ieee754_clearcx(); - FLUSHXDP; - - /* Clear sign ALWAYS, irrespective of NaN */ - DPSIGN(x) = 0; - - if (xc == IEEE754_CLASS_SNAN) { - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); - } - - return x; + unsigned int oldrm; + union ieee754dp y; + + oldrm = ieee754_csr.rm; + ieee754_csr.rm = FPU_CSR_RD; + if (DPSIGN(x)) + y = ieee754dp_sub(ieee754dp_zero(0), x); + else + y = ieee754dp_add(ieee754dp_zero(0), x); + ieee754_csr.rm = oldrm; + return y; } diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 041bbb6124bb..cd5bc083001e 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -42,13 +42,12 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) /* x == INF or NAN? */ switch (xc) { - case IEEE754_CLASS_QNAN: - /* sqrt(Nan) = Nan */ + case IEEE754_CLASS_SNAN: return ieee754dp_nanxcpt(x); - case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + case IEEE754_CLASS_QNAN: + /* sqrt(Nan) = Nan */ + return x; case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ @@ -58,7 +57,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) if (xs) { /* sqrt(-Inf) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_indef(); } /* sqrt(+Inf) = Inf */ return x; @@ -71,7 +70,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) if (xs) { /* sqrt(-x) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_indef(); } break; } diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 7a174029043a..fc17a781b9ae 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -37,19 +37,20 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) FLUSHYDP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754dp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef()); + return ieee754dp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -153,8 +154,6 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) /* generate 28 bit result of adding two 27 bit numbers */ xm = xm + ym; - xe = xe; - xs = xs; if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */ xm = XDPSRS1(xm); /* shift preserving sticky */ @@ -163,11 +162,8 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) } else { if (xm >= ym) { xm = xm - ym; - xe = xe; - xs = xs; } else { xm = ym - xm; - xe = xe; xs = ys; } if (xm == 0) { diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 4f514f3724cb..e0b5cc27d78b 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -94,9 +94,9 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) regs->cp0_epc = ((unsigned long) &fr->emul) | get_isa16_mode(regs->cp0_epc); - flush_cache_sigtramp((unsigned long)&fr->badinst); + flush_cache_sigtramp((unsigned long)&fr->emul); - return SIGILL; /* force out of emulation loop */ + return 0; } int do_dsemulret(struct pt_regs *xcp) @@ -158,6 +158,6 @@ int do_dsemulret(struct pt_regs *xcp) /* Set EPC to return to post-branch instruction */ xcp->cp0_epc = epc; - + MIPS_FPU_EMU_INC_STATS(ds_emul); return 1; } diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 43c4fb522ac2..a5ca108ce467 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -126,84 +126,21 @@ enum { #define IEEE754_CGT 0x04 #define IEEE754_CUN 0x08 -/* "normal" comparisons -*/ -static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); -} - -static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); -} - -static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CLT, 0); -} - -static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); -} - -static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CGT, 0); -} - - -static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); -} - -static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); -} - -static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); -} - -static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CLT, 0); -} - -static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); -} - -static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CGT, 0); -} - -static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); -} - /* * The control status register */ struct _ieee754_csr { - __BITFIELD_FIELD(unsigned pad0:7, - __BITFIELD_FIELD(unsigned nod:1, /* set 1 for no denormalised numbers */ - __BITFIELD_FIELD(unsigned c:1, /* condition */ - __BITFIELD_FIELD(unsigned pad1:5, + __BITFIELD_FIELD(unsigned fcc:7, /* condition[7:1] */ + __BITFIELD_FIELD(unsigned nod:1, /* set 1 for no denormals */ + __BITFIELD_FIELD(unsigned c:1, /* condition[0] */ + __BITFIELD_FIELD(unsigned pad0:3, + __BITFIELD_FIELD(unsigned abs2008:1, /* IEEE 754-2008 ABS/NEG.fmt */ + __BITFIELD_FIELD(unsigned nan2008:1, /* IEEE 754-2008 NaN mode */ __BITFIELD_FIELD(unsigned cx:6, /* exceptions this operation */ __BITFIELD_FIELD(unsigned mx:5, /* exception enable mask */ __BITFIELD_FIELD(unsigned sx:5, /* exceptions total */ __BITFIELD_FIELD(unsigned rm:2, /* current rounding mode */ - ;)))))))) + ;)))))))))) }; #define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31)) @@ -257,23 +194,23 @@ static inline int ieee754_sxtest(unsigned n) union ieee754sp ieee754sp_dump(char *s, union ieee754sp x); union ieee754dp ieee754dp_dump(char *s, union ieee754dp x); -#define IEEE754_SPCVAL_PZERO 0 -#define IEEE754_SPCVAL_NZERO 1 -#define IEEE754_SPCVAL_PONE 2 -#define IEEE754_SPCVAL_NONE 3 -#define IEEE754_SPCVAL_PTEN 4 -#define IEEE754_SPCVAL_NTEN 5 -#define IEEE754_SPCVAL_PINFINITY 6 -#define IEEE754_SPCVAL_NINFINITY 7 -#define IEEE754_SPCVAL_INDEF 8 -#define IEEE754_SPCVAL_PMAX 9 /* +max norm */ -#define IEEE754_SPCVAL_NMAX 10 /* -max norm */ -#define IEEE754_SPCVAL_PMIN 11 /* +min norm */ -#define IEEE754_SPCVAL_NMIN 12 /* +min norm */ -#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ -#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */ -#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ -#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ +#define IEEE754_SPCVAL_PZERO 0 /* +0.0 */ +#define IEEE754_SPCVAL_NZERO 1 /* -0.0 */ +#define IEEE754_SPCVAL_PONE 2 /* +1.0 */ +#define IEEE754_SPCVAL_NONE 3 /* -1.0 */ +#define IEEE754_SPCVAL_PTEN 4 /* +10.0 */ +#define IEEE754_SPCVAL_NTEN 5 /* -10.0 */ +#define IEEE754_SPCVAL_PINFINITY 6 /* +inf */ +#define IEEE754_SPCVAL_NINFINITY 7 /* -inf */ +#define IEEE754_SPCVAL_INDEF 8 /* quiet NaN */ +#define IEEE754_SPCVAL_PMAX 9 /* +max norm */ +#define IEEE754_SPCVAL_NMAX 10 /* -max norm */ +#define IEEE754_SPCVAL_PMIN 11 /* +min norm */ +#define IEEE754_SPCVAL_NMIN 12 /* -min norm */ +#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ +#define IEEE754_SPCVAL_NMIND 14 /* -min denorm */ +#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ +#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ extern const union ieee754dp __ieee754dp_spcvals[]; extern const union ieee754sp __ieee754sp_spcvals[]; diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 068f45a415fc..522d843f2ffd 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -30,9 +30,9 @@ int ieee754dp_class(union ieee754dp x) return xc; } -int ieee754dp_isnan(union ieee754dp x) +static inline int ieee754dp_isnan(union ieee754dp x) { - return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; + return ieee754_class_nan(ieee754dp_class(x)); } static inline int ieee754dp_issnan(union ieee754dp x) @@ -42,23 +42,16 @@ static inline int ieee754dp_issnan(union ieee754dp x) } +/* + * Raise the Invalid Operation IEEE 754 exception + * and convert the signaling NaN supplied to a quiet NaN. + */ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r) { - assert(ieee754dp_isnan(r)); - - if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ - return r; - - if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { - /* not enabled convert to a quiet NaN */ - DPMANT(r) &= (~DP_MBIT(DP_FBITS-1)); - if (ieee754dp_isnan(r)) - return r; - else - return ieee754dp_indef(); - } + assert(ieee754dp_issnan(r)); - return r; + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754dp_indef(); } static u64 ieee754dp_get_rounding(int sn, u64 xm) diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 61fd6fd31350..e2babd98fee3 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -77,6 +77,5 @@ static inline union ieee754dp builddp(int s, int bx, u64 m) return r; } -extern int ieee754dp_isnan(union ieee754dp); extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp); extern union ieee754dp ieee754dp_format(int, int, u64); diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index f0365bb86747..05389d5e3a93 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -44,6 +44,11 @@ static inline int ieee754_setandtestcx(const unsigned int x) return ieee754_csr.mx & x; } +static inline int ieee754_class_nan(int xc) +{ + return xc >= IEEE754_CLASS_SNAN; +} + #define COMPXSP \ unsigned xm; int xe; int xs __maybe_unused; int xc diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index ba88301579c2..ca8e35e33bf7 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -30,9 +30,9 @@ int ieee754sp_class(union ieee754sp x) return xc; } -int ieee754sp_isnan(union ieee754sp x) +static inline int ieee754sp_isnan(union ieee754sp x) { - return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; + return ieee754_class_nan(ieee754sp_class(x)); } static inline int ieee754sp_issnan(union ieee754sp x) @@ -42,23 +42,16 @@ static inline int ieee754sp_issnan(union ieee754sp x) } +/* + * Raise the Invalid Operation IEEE 754 exception + * and convert the signaling NaN supplied to a quiet NaN. + */ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) { - assert(ieee754sp_isnan(r)); - - if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ - return r; - - if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { - /* not enabled convert to a quiet NaN */ - SPMANT(r) &= (~SP_MBIT(SP_FBITS-1)); - if (ieee754sp_isnan(r)) - return r; - else - return ieee754sp_indef(); - } + assert(ieee754sp_issnan(r)); - return r; + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754sp_indef(); } static unsigned ieee754sp_get_rounding(int sn, unsigned xm) diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index ad268e332318..374a3f00a589 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -82,6 +82,5 @@ static inline union ieee754sp buildsp(int s, int bx, unsigned m) return r; } -extern int ieee754sp_isnan(union ieee754sp); extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp); extern union ieee754sp ieee754sp_format(int, int, unsigned); diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c index becdd63e14a9..f308e0f05fc5 100644 --- a/arch/mips/math-emu/me-debugfs.c +++ b/arch/mips/math-emu/me-debugfs.c @@ -61,6 +61,7 @@ do { \ FPU_STAT_CREATE(ieee754_overflow); FPU_STAT_CREATE(ieee754_zerodiv); FPU_STAT_CREATE(ieee754_invalidop); + FPU_STAT_CREATE(ds_emul); return 0; } diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index 2d84d460cb67..f1c87b07d3b4 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -37,19 +37,20 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) FLUSHYSP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -148,8 +149,6 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) * leaving result in xm, xs and xe. */ xm = xm + ym; - xe = xe; - xs = xs; if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */ SPXSRSX1(); @@ -157,11 +156,8 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) } else { if (xm >= ym) { xm = xm - ym; - xe = xe; - xs = xs; } else { xm = ym - xm; - xe = xe; xs = ys; } if (xm == 0) diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index addbccb2f556..67b82f1e2c4a 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -35,16 +35,11 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) FLUSHYSP; ieee754_clearcx(); /* Even clear inexact flag here */ - if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { - if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) + if (ieee754_class_nan(xc) || ieee754_class_nan(yc)) { + if (sig || + xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) ieee754_setcx(IEEE754_INVALID_OPERATION); - if (cmp & IEEE754_CUN) - return 1; - if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) - return 0; - } - return 0; + return (cmp & IEEE754_CUN) != 0; } else { vx = x.bits; vy = y.bits; diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index 721f317aa877..27f6db3a0a4c 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -39,19 +39,20 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) FLUSHYSP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index 1b266fb16973..3797148893ad 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -22,12 +22,19 @@ #include "ieee754sp.h" #include "ieee754dp.h" +static inline union ieee754sp ieee754sp_nan_fdp(int xs, u64 xm) +{ + return buildsp(xs, SP_EMAX + 1 + SP_EBIAS, + xm >> (DP_FBITS - SP_FBITS)); +} + union ieee754sp ieee754sp_fdp(union ieee754dp x) { + union ieee754sp y; u32 rm; COMPXDP; - union ieee754sp nan; + COMPYSP; EXPLODEXDP; @@ -37,15 +44,14 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) switch (xc) { case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_nanxcpt(ieee754sp_nan_fdp(xs, xm)); case IEEE754_CLASS_QNAN: - nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) - (xm >> (DP_FBITS - SP_FBITS))); - if (!ieee754sp_isnan(nan)) - nan = ieee754sp_indef(); - return ieee754sp_nanxcpt(nan); + y = ieee754sp_nan_fdp(xs, xm); + EXPLODEYSP; + if (!ieee754_class_nan(yc)) + y = ieee754sp_indef(); + return y; case IEEE754_CLASS_INF: return ieee754sp_inf(xs); diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index 890c13a2965e..d910c43a6f30 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -47,19 +47,20 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) FLUSHYSP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index f1ffaa9a17e0..c50e9451f2d2 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -23,44 +23,27 @@ union ieee754sp ieee754sp_neg(union ieee754sp x) { - COMPXSP; - - EXPLODEXSP; - ieee754_clearcx(); - FLUSHXSP; - - /* - * Invert the sign ALWAYS to prevent an endless recursion on - * pow() in libc. - */ - /* quick fix up */ - SPSIGN(x) ^= 1; - - if (xc == IEEE754_CLASS_SNAN) { - union ieee754sp y = ieee754sp_indef(); - ieee754_setcx(IEEE754_INVALID_OPERATION); - SPSIGN(y) = SPSIGN(x); - return ieee754sp_nanxcpt(y); - } - - return x; + unsigned int oldrm; + union ieee754sp y; + + oldrm = ieee754_csr.rm; + ieee754_csr.rm = FPU_CSR_RD; + y = ieee754sp_sub(ieee754sp_zero(0), x); + ieee754_csr.rm = oldrm; + return y; } union ieee754sp ieee754sp_abs(union ieee754sp x) { - COMPXSP; - - EXPLODEXSP; - ieee754_clearcx(); - FLUSHXSP; - - /* Clear sign ALWAYS, irrespective of NaN */ - SPSIGN(x) = 0; - - if (xc == IEEE754_CLASS_SNAN) { - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); - } - - return x; + unsigned int oldrm; + union ieee754sp y; + + oldrm = ieee754_csr.rm; + ieee754_csr.rm = FPU_CSR_RD; + if (SPSIGN(x)) + y = ieee754sp_sub(ieee754sp_zero(0), x); + else + y = ieee754sp_add(ieee754sp_zero(0), x); + ieee754_csr.rm = oldrm; + return y; } diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index b7c098a86f95..67059c33a250 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -35,13 +35,12 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) /* x == INF or NAN? */ switch (xc) { - case IEEE754_CLASS_QNAN: - /* sqrt(Nan) = Nan */ + case IEEE754_CLASS_SNAN: return ieee754sp_nanxcpt(x); - case IEEE754_CLASS_SNAN: - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + case IEEE754_CLASS_QNAN: + /* sqrt(Nan) = Nan */ + return x; case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ @@ -51,7 +50,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (xs) { /* sqrt(-Inf) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_indef(); } /* sqrt(+Inf) = Inf */ return x; @@ -61,7 +60,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (xs) { /* sqrt(-x) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_indef(); } break; } diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index 8592e49032b8..ec5f937a8b3e 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -37,19 +37,20 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) FLUSHYSP; switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): + return ieee754sp_nanxcpt(y); + + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef()); + return ieee754sp_nanxcpt(x); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -148,8 +149,6 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) /* generate 28 bit result of adding two 27 bit numbers */ xm = xm + ym; - xe = xe; - xs = xs; if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */ SPXSRSX1(); /* shift preserving sticky */ @@ -157,11 +156,8 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) } else { if (xm >= ym) { xm = xm - ym; - xe = xe; - xs = xs; } else { xm = ym - xm; - xe = xe; xs = ys; } if (xm == 0) { diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 3f8059602765..0dbb65a51ce5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -430,6 +430,7 @@ static inline void local_r4k___flush_cache_all(void * args) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: /* * These caches are inclusive caches, that is, if something * is not cached in the S-cache, we know it also won't be @@ -506,7 +507,7 @@ static inline void local_r4k_flush_cache_mm(void * args) /* * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we - * only flush the primary caches but R10000 and R12000 behave sane ... + * only flush the primary caches but R1x000 behave sane ... * R4000SC and R4400SC indexed S-cache ops also invalidate primary * caches, so we can bail out early. */ @@ -888,33 +889,39 @@ static inline void rm7k_erratum31(void) } } -static inline void alias_74k_erratum(struct cpuinfo_mips *c) +static inline int alias_74k_erratum(struct cpuinfo_mips *c) { unsigned int imp = c->processor_id & PRID_IMP_MASK; unsigned int rev = c->processor_id & PRID_REV_MASK; + int present = 0; /* * Early versions of the 74K do not update the cache tags on a * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG - * aliases. In this case it is better to treat the cache as always - * having aliases. + * aliases. In this case it is better to treat the cache as always + * having aliases. Also disable the synonym tag update feature + * where available. In this case no opportunistic tag update will + * happen where a load causes a virtual address miss but a physical + * address hit during a D-cache look-up. */ switch (imp) { case PRID_IMP_74K: if (rev <= PRID_REV_ENCODE_332(2, 4, 0)) - c->dcache.flags |= MIPS_CACHE_VTAG; + present = 1; if (rev == PRID_REV_ENCODE_332(2, 4, 0)) write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); break; case PRID_IMP_1074K: if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) { - c->dcache.flags |= MIPS_CACHE_VTAG; + present = 1; write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND); } break; default: BUG(); } + + return present; } static void b5k_instruction_hazard(void) @@ -938,6 +945,7 @@ static void probe_pcache(void) struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); unsigned int prid = read_c0_prid(); + int has_74k_erratum = 0; unsigned long config1; unsigned int lsize; @@ -1012,6 +1020,7 @@ static void probe_pcache(void) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29)); c->icache.linesz = 64; c->icache.ways = 2; @@ -1223,8 +1232,8 @@ static void probe_pcache(void) dcache_size / (c->dcache.linesz * c->dcache.ways) : 0; /* - * R10000 and R12000 P-caches are odd in a positive way. They're 32kB - * 2-way virtually indexed so normally would suffer from aliases. So + * R1x000 P-caches are odd in a positive way. They're 32kB 2-way + * virtually indexed so normally would suffer from aliases. So * normally they'd suffer from aliases but magic in the hardware deals * with that for us so we don't need to take care ourselves. */ @@ -1240,11 +1249,12 @@ static void probe_pcache(void) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: break; case CPU_74K: case CPU_1074K: - alias_74k_erratum(c); + has_74k_erratum = alias_74k_erratum(c); /* Fall through. */ case CPU_M14KC: case CPU_M14KEC: @@ -1259,7 +1269,7 @@ static void probe_pcache(void) if (!(read_c0_config7() & MIPS_CONF7_IAR) && (c->icache.waysize > PAGE_SIZE)) c->icache.flags |= MIPS_CACHE_ALIASES; - if (read_c0_config7() & MIPS_CONF7_AR) { + if (!has_74k_erratum && (read_c0_config7() & MIPS_CONF7_AR)) { /* * Effectively physically indexed dcache, * thus no virtual aliases. @@ -1268,7 +1278,7 @@ static void probe_pcache(void) break; } default: - if (c->dcache.waysize > PAGE_SIZE) + if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE) c->dcache.flags |= MIPS_CACHE_ALIASES; } @@ -1438,6 +1448,7 @@ static void setup_scache(void) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16); c->scache.linesz = 64 << ((config >> 13) & 1); c->scache.ways = 2; diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 7e3ea7766822..77d96db8253c 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -119,36 +119,37 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr) EXPORT_SYMBOL(__flush_anon_page); -static void mips_flush_dcache_from_pte(pte_t pteval, unsigned long address) +void __flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + unsigned long addr; + + if (PageHighMem(page)) + return; + + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); +} +EXPORT_SYMBOL_GPL(__flush_icache_page); + +void __update_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) { struct page *page; - unsigned long pfn = pte_pfn(pteval); + unsigned long pfn, addr; + int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; + pfn = pte_pfn(pte); if (unlikely(!pfn_valid(pfn))) return; - page = pfn_to_page(pfn); if (page_mapping(page) && Page_dcache_dirty(page)) { - unsigned long page_addr = (unsigned long) page_address(page); - - if (!cpu_has_ic_fills_f_dc || - pages_do_alias(page_addr, address & PAGE_MASK)) - flush_data_cache_page(page_addr); + addr = (unsigned long) page_address(page); + if (exec || pages_do_alias(addr, address & PAGE_MASK)) + flush_data_cache_page(addr); ClearPageDcacheDirty(page); } } -void set_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t pteval) -{ - if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) { - if (pte_present(pteval)) - mips_flush_dcache_from_pte(pteval, addr); - } - - set_pte(ptep, pteval); -} - unsigned long _page_cachable_default; EXPORT_SYMBOL(_page_cachable_default); diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index af5f046e627e..609d1241b0c4 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -258,7 +258,7 @@ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_addr), dma_addr & ~PAGE_MASK, size, direction); - + plat_post_dma_flush(dev); plat_unmap_dma_mem(dev, dma_addr, size, direction); } @@ -312,6 +312,7 @@ static void mips_dma_sync_single_for_cpu(struct device *dev, if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_handle), dma_handle & ~PAGE_MASK, size, direction); + plat_post_dma_flush(dev); } static void mips_dma_sync_single_for_device(struct device *dev, @@ -331,6 +332,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, for (i = 0; i < nelems; i++, sg++) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); + plat_post_dma_flush(dev); } static void mips_dma_sync_sg_for_device(struct device *dev, diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 448cde372af0..faa5c9822ecc 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -96,7 +96,7 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) vaddr = __fix_to_virt(FIX_CMAP_END - idx); pte = mk_pte(page, prot); #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) - entrylo = pte.pte_high; + entrylo = pte_to_entrylo(pte.pte_high); #else entrylo = pte_to_entrylo(pte_val(pte)); #endif @@ -106,6 +106,11 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) write_c0_entryhi(vaddr & (PAGE_MASK << 1)); write_c0_entrylo0(entrylo); write_c0_entrylo1(entrylo); +#ifdef CONFIG_XPA + entrylo = (pte.pte_low & _PFNX_MASK); + writex_c0_entrylo0(entrylo); + writex_c0_entrylo1(entrylo); +#endif tlbidx = read_c0_wired(); write_c0_wired(tlbidx + 1); write_c0_index(tlbidx); diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index f1baadd56e82..5c81fdd032c3 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -142,18 +142,26 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp, addr0, len, pgoff, flags, DOWN); } +unsigned long arch_mmap_rnd(void) +{ + unsigned long rnd; + + rnd = (unsigned long)get_random_int(); + rnd <<= PAGE_SHIFT; + if (TASK_IS_32BIT_ADDR) + rnd &= 0xfffffful; + else + rnd &= 0xffffffful; + + return rnd; +} + void arch_pick_mmap_layout(struct mm_struct *mm) { unsigned long random_factor = 0UL; - if (current->flags & PF_RANDOMIZE) { - random_factor = get_random_int(); - random_factor = random_factor << PAGE_SHIFT; - if (TASK_IS_32BIT_ADDR) - random_factor &= 0xfffffful; - else - random_factor &= 0xffffffful; - } + if (current->flags & PF_RANDOMIZE) + random_factor = arch_mmap_rnd(); if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 3f85f921801b..885d73ffd6fb 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -157,6 +157,7 @@ static void set_prefetch_parameters(void) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: /* * Those values have been experimentally tuned for an * Origin 200. diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index b2afa49beab0..a27a088e6f9f 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -333,9 +333,17 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) ptep = pte_offset_map(pmdp, address); #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) +#ifdef CONFIG_XPA + write_c0_entrylo0(pte_to_entrylo(ptep->pte_high)); + writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK); + ptep++; + write_c0_entrylo1(pte_to_entrylo(ptep->pte_high)); + writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK); +#else write_c0_entrylo0(ptep->pte_high); ptep++; write_c0_entrylo1(ptep->pte_high); +#endif #else write_c0_entrylo0(pte_to_entrylo(pte_val(*ptep++))); write_c0_entrylo1(pte_to_entrylo(pte_val(*ptep))); @@ -355,6 +363,9 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { +#ifdef CONFIG_XPA + panic("Broken for XPA kernels"); +#else unsigned long flags; unsigned long wired; unsigned long old_pagemask; @@ -383,6 +394,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, write_c0_pagemask(old_pagemask); local_flush_tlb_all(); local_irq_restore(flags); +#endif } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -477,7 +489,8 @@ static void r4k_tlb_configure(void) write_c0_wired(0); if (current_cpu_type() == CPU_R10000 || current_cpu_type() == CPU_R12000 || - current_cpu_type() == CPU_R14000) + current_cpu_type() == CPU_R14000 || + current_cpu_type() == CPU_R16000) write_c0_framemask(0); if (cpu_has_rixi) { diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index d75ff73a2012..97c87027c17f 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -35,6 +35,17 @@ #include <asm/uasm.h> #include <asm/setup.h> +static int __cpuinitdata mips_xpa_disabled; + +static int __init xpa_disable(char *s) +{ + mips_xpa_disabled = 1; + + return 1; +} + +__setup("noxpa", xpa_disable); + /* * TLB load/store/modify handlers. * @@ -231,14 +242,14 @@ static void output_pgtable_bits_defines(void) pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT); pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT); #endif +#ifdef CONFIG_CPU_MIPSR2 if (cpu_has_rixi) { #ifdef _PAGE_NO_EXEC_SHIFT pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT); -#endif -#ifdef _PAGE_NO_READ_SHIFT pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); #endif } +#endif pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT); pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT); pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT); @@ -501,26 +512,9 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l, case tlb_indexed: tlbw = uasm_i_tlbwi; break; } - if (cpu_has_mips_r2_exec_hazard) { - /* - * The architecture spec says an ehb is required here, - * but a number of cores do not have the hazard and - * using an ehb causes an expensive pipeline stall. - */ - switch (current_cpu_type()) { - case CPU_M14KC: - case CPU_74K: - case CPU_1074K: - case CPU_PROAPTIV: - case CPU_P5600: - case CPU_M5150: - case CPU_QEMU_GENERIC: - break; - - default: + if (cpu_has_mips_r2_r6) { + if (cpu_has_mips_r2_exec_hazard) uasm_i_ehb(p); - break; - } tlbw(p); return; } @@ -569,6 +563,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l, case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: case CPU_4KC: case CPU_4KEC: case CPU_M14KC: @@ -1027,12 +1022,27 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) } else { int pte_off_even = sizeof(pte_t) / 2; int pte_off_odd = pte_off_even + sizeof(pte_t); +#ifdef CONFIG_XPA + const int scratch = 1; /* Our extra working register */ - /* The pte entries are pre-shifted */ - uasm_i_lw(p, tmp, pte_off_even, ptep); /* get even pte */ - UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */ - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* get odd pte */ - UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */ + uasm_i_addu(p, scratch, 0, ptep); +#endif + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ + UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); + UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); + UASM_i_MTC0(p, ptep, C0_ENTRYLO1); +#ifdef CONFIG_XPA + uasm_i_lw(p, tmp, 0, scratch); + uasm_i_lw(p, ptep, sizeof(pte_t), scratch); + uasm_i_lui(p, scratch, 0xff); + uasm_i_ori(p, scratch, scratch, 0xffff); + uasm_i_and(p, tmp, scratch, tmp); + uasm_i_and(p, ptep, scratch, ptep); + uasm_i_mthc0(p, tmp, C0_ENTRYLO0); + uasm_i_mthc0(p, ptep, C0_ENTRYLO1); +#endif } #else UASM_i_LW(p, tmp, 0, ptep); /* get even pte */ @@ -1533,8 +1543,14 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, { #ifdef CONFIG_PHYS_ADDR_T_64BIT unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); -#endif + if (!cpu_has_64bits) { + const int scratch = 1; /* Our extra working register */ + + uasm_i_lui(p, scratch, (mode >> 16)); + uasm_i_or(p, pte, pte, scratch); + } else +#endif uasm_i_ori(p, pte, pte, mode); #ifdef CONFIG_SMP # ifdef CONFIG_PHYS_ADDR_T_64BIT @@ -1598,15 +1614,17 @@ build_pte_present(u32 **p, struct uasm_reloc **r, uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid); uasm_i_nop(p); } else { - uasm_i_andi(p, t, pte, _PAGE_PRESENT); + uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); + uasm_i_andi(p, t, t, 1); uasm_il_beqz(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ iPTE_LW(p, pte, ptr); } } else { - uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_READ); - uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_READ); + uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); + uasm_i_andi(p, t, t, 3); + uasm_i_xori(p, t, t, 3); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -1635,8 +1653,9 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, { int t = scratch >= 0 ? scratch : pte; - uasm_i_andi(p, t, pte, _PAGE_PRESENT | _PAGE_WRITE); - uasm_i_xori(p, t, t, _PAGE_PRESENT | _PAGE_WRITE); + uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT); + uasm_i_andi(p, t, t, 5); + uasm_i_xori(p, t, t, 5); uasm_il_bnez(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -1672,7 +1691,8 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r, uasm_i_nop(p); } else { int t = scratch >= 0 ? scratch : pte; - uasm_i_andi(p, t, pte, _PAGE_WRITE); + uasm_i_srl(p, t, pte, _PAGE_WRITE_SHIFT); + uasm_i_andi(p, t, t, 1); uasm_il_beqz(p, r, t, lid); if (pte == t) /* You lose the SMP race :-(*/ @@ -2285,6 +2305,11 @@ static void config_htw_params(void) pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT; pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT; + + /* If XPA has been enabled, PTEs are 64-bit in size. */ + if (read_c0_pagegrain() & PG_ELPA) + pwsize |= 1; + write_c0_pwsize(pwsize); /* Make sure everything is set before we enable the HTW */ @@ -2298,6 +2323,28 @@ static void config_htw_params(void) print_htw_config(); } +static void config_xpa_params(void) +{ +#ifdef CONFIG_XPA + unsigned int pagegrain; + + if (mips_xpa_disabled) { + pr_info("Extended Physical Addressing (XPA) disabled\n"); + return; + } + + pagegrain = read_c0_pagegrain(); + write_c0_pagegrain(pagegrain | PG_ELPA); + back_to_back_c0_hazard(); + pagegrain = read_c0_pagegrain(); + + if (pagegrain & PG_ELPA) + pr_info("Extended Physical Addressing (XPA) enabled\n"); + else + panic("Extended Physical Addressing (XPA) disabled"); +#endif +} + void build_tlb_refill_handler(void) { /* @@ -2362,8 +2409,9 @@ void build_tlb_refill_handler(void) } if (cpu_has_local_ebase) build_r4000_tlb_refill_handler(); + if (cpu_has_xpa) + config_xpa_params(); if (cpu_has_htw) config_htw_params(); - } } diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index 8fddd2cdbff7..b769657be4d4 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -16,6 +16,7 @@ #include <linux/string.h> #include <asm/bootinfo.h> +#include <asm/cdmm.h> #include <asm/maar.h> #include <asm/sections.h> #include <asm/fw/fw.h> @@ -53,6 +54,12 @@ fw_memblock_t * __init fw_getmdesc(int eva) pr_warn("memsize not set in YAMON, set to default (32Mb)\n"); physical_memsize = 0x02000000; } else { + if (memsize > (256 << 20)) { /* memsize should be capped to 256M */ + pr_warn("Unsupported memsize value (0x%lx) detected! " + "Using 0x10000000 (256M) instead\n", + memsize); + memsize = 256 << 20; + } /* If ememsize is set, then set physical_memsize to that */ physical_memsize = ememsize ? : memsize; } @@ -196,3 +203,9 @@ unsigned platform_maar_init(unsigned num_pairs) return maar_config(cfg, num_cfg, num_pairs); } + +phys_addr_t mips_cdmm_phys_base(void) +{ + /* This address is "typically unused" */ + return 0x1fc10000; +} diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index ce02dbdedc62..185e68261f45 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -87,8 +87,10 @@ static void __init estimate_frequencies(void) /* Initialize counters. */ start = read_c0_count(); - if (gic_present) + if (gic_present) { + gic_start_count(); gicstart = gic_read_count(); + } /* Read counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); @@ -115,6 +117,22 @@ void read_persistent_clock(struct timespec *ts) ts->tv_nsec = 0; } +int get_c0_fdc_int(void) +{ + int mips_cpu_fdc_irq; + + if (cpu_has_veic) + mips_cpu_fdc_irq = -1; + else if (gic_present) + mips_cpu_fdc_irq = gic_get_c0_fdc_int(); + else if (cp0_fdc_irq >= 0) + mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq; + else + mips_cpu_fdc_irq = -1; + + return mips_cpu_fdc_irq; +} + int get_c0_perfcount_int(void) { if (cpu_has_veic) { diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index 2ae49e99eb67..ecd71db6258b 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -9,14 +9,11 @@ # Steven J. Hill <sjhill@mips.com> # obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ - sead3-int.o sead3-mtd.o sead3-net.o \ - sead3-platform.o sead3-reset.o \ + sead3-int.o sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += sead3-i2c-dev.o sead3-i2c.o \ - leds-sead3.o sead3-leds.o +obj-y += leds-sead3.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o -obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c index 3abe47b316aa..c938ceeb8848 100644 --- a/arch/mips/mti-sead3/leds-sead3.c +++ b/arch/mips/mti-sead3/leds-sead3.c @@ -4,6 +4,7 @@ * for more details. * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2015 Imagination Technologies, Inc. */ #include <linux/kernel.h> #include <linux/module.h> @@ -13,22 +14,18 @@ #include <linux/err.h> #include <linux/io.h> -#define DRVNAME "sead3-led" - -static struct platform_device *pdev; +#include <asm/mips-boards/sead3-addr.h> static void sead3_pled_set(struct led_classdev *led_cdev, enum led_brightness value) { - pr_debug("sead3_pled_set\n"); - writel(value, (void __iomem *)0xBF000210); /* FIXME */ + writel(value, (void __iomem *)SEAD3_CPLD_P_LED); } static void sead3_fled_set(struct led_classdev *led_cdev, enum led_brightness value) { - pr_debug("sead3_fled_set\n"); - writel(value, (void __iomem *)0xBF000218); /* FIXME */ + writel(value, (void __iomem *)SEAD3_CPLD_F_LED); } static struct led_classdev sead3_pled = { @@ -69,37 +66,11 @@ static struct platform_driver sead3_led_driver = { .probe = sead3_led_probe, .remove = sead3_led_remove, .driver = { - .name = DRVNAME, + .name = "sead3-led", }, }; -static int __init sead3_led_init(void) -{ - int ret; - - ret = platform_driver_register(&sead3_led_driver); - if (ret < 0) - goto out; - - pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); - platform_driver_unregister(&sead3_led_driver); - goto out; - } - -out: - return ret; -} - -static void __exit sead3_led_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&sead3_led_driver); -} - -module_init(sead3_led_init); -module_exit(sead3_led_exit); +module_platform_driver(sead3_led_driver); MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); MODULE_DESCRIPTION("SEAD3 LED driver"); diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c deleted file mode 100644 index 014dd7ba4d68..000000000000 --- a/arch/mips/mti-sead3/sead3-ehci.c +++ /dev/null @@ -1,53 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/module.h> -#include <linux/irq.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/irqchip/mips-gic.h> - -#include <asm/mips-boards/sead3int.h> - -struct resource ehci_resources[] = { - { - .start = 0x1b200000, - .end = 0x1b200fff, - .flags = IORESOURCE_MEM - }, - { - .flags = IORESOURCE_IRQ - } -}; - -u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ehci_device = { - .name = "sead3-ehci", - .id = 0, - .dev = { - .dma_mask = &sead3_usbdev_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32) - }, - .num_resources = ARRAY_SIZE(ehci_resources), - .resource = ehci_resources -}; - -static int __init ehci_init(void) -{ - if (gic_present) - ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI; - else - ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI; - return platform_device_register(&ehci_device); -} - -module_init(ehci_init); - -MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("EHCI probe driver for SEAD3"); diff --git a/arch/mips/mti-sead3/sead3-i2c-dev.c b/arch/mips/mti-sead3/sead3-i2c-dev.c deleted file mode 100644 index eca0b53a71dd..000000000000 --- a/arch/mips/mti-sead3/sead3-i2c-dev.c +++ /dev/null @@ -1,33 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/i2c.h> - -static struct i2c_board_info __initdata sead3_i2c_devices[] = { - { - I2C_BOARD_INFO("adt7476", 0x2c), - .irq = 0, - }, - { - I2C_BOARD_INFO("m41t80", 0x68), - .irq = 0, - }, -}; - -static int __init sead3_i2c_init(void) -{ - int err; - - err = i2c_register_board_info(0, sead3_i2c_devices, - ARRAY_SIZE(sead3_i2c_devices)); - if (err < 0) - pr_err("sead3-i2c-dev: cannot register board I2C devices\n"); - return err; -} - -arch_initcall(sead3_i2c_init); diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c deleted file mode 100644 index 2bebf0974e39..000000000000 --- a/arch/mips/mti-sead3/sead3-i2c-drv.c +++ /dev/null @@ -1,404 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> - -#define PIC32_I2CxCON 0x0000 -#define PIC32_I2CCON_ON (1<<15) -#define PIC32_I2CCON_ACKDT (1<<5) -#define PIC32_I2CCON_ACKEN (1<<4) -#define PIC32_I2CCON_RCEN (1<<3) -#define PIC32_I2CCON_PEN (1<<2) -#define PIC32_I2CCON_RSEN (1<<1) -#define PIC32_I2CCON_SEN (1<<0) -#define PIC32_I2CxCONCLR 0x0004 -#define PIC32_I2CxCONSET 0x0008 -#define PIC32_I2CxSTAT 0x0010 -#define PIC32_I2CxSTATCLR 0x0014 -#define PIC32_I2CSTAT_ACKSTAT (1<<15) -#define PIC32_I2CSTAT_TRSTAT (1<<14) -#define PIC32_I2CSTAT_BCL (1<<10) -#define PIC32_I2CSTAT_IWCOL (1<<7) -#define PIC32_I2CSTAT_I2COV (1<<6) -#define PIC32_I2CxBRG 0x0040 -#define PIC32_I2CxTRN 0x0050 -#define PIC32_I2CxRCV 0x0060 - -static DEFINE_SPINLOCK(pic32_bus_lock); - -static void __iomem *bus_xfer = (void __iomem *)0xbf000600; -static void __iomem *bus_status = (void __iomem *)0xbf000060; - -#define DELAY() udelay(100) - -static inline unsigned int ioready(void) -{ - return readl(bus_status) & 1; -} - -static inline void wait_ioready(void) -{ - do { } while (!ioready()); -} - -static inline void wait_ioclear(void) -{ - do { } while (ioready()); -} - -static inline void check_ioclear(void) -{ - if (ioready()) { - do { - (void) readl(bus_xfer); - DELAY(); - } while (ioready()); - } -} - -static u32 pic32_bus_readl(u32 reg) -{ - unsigned long flags; - u32 status, val; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - DELAY(); - val = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); - - return val; -} - -static void pic32_bus_writel(u32 val, u32 reg) -{ - unsigned long flags; - u32 status; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - writel(val, bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); -} - -struct pic32_i2c_platform_data { - u32 base; - struct i2c_adapter adap; - u32 xfer_timeout; - u32 ack_timeout; - u32 ctl_timeout; -}; - -static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) -{ - int i; - - for (i = 0; i < adap->ctl_timeout; i++) { - if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & - (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | - PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | - PIC32_I2CCON_SEN)) == 0) && - ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - (PIC32_I2CSTAT_TRSTAT)) == 0)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, - u32 byte) -{ - pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); - return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_IWCOL; -} - -static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); - while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) - ; - pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); - return pic32_bus_readl(adap->base + PIC32_I2CxRCV); -} - -static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, - unsigned int addr, int rd) -{ - pic32_i2c_idle(adap); - pic32_i2c_start(adap); - pic32_i2c_idle(adap); - - addr <<= 1; - if (rd) - addr |= 1; - - if (pic32_i2c_master_write(adap, addr)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - return 0; -} - -static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - u32 data; - int i; - - i = 0; - while (i < len) { - data = pic32_i2c_master_read(adap); - buf[i++] = data; - if (i < len) - pic32_i2c_ack(adap); - else - pic32_i2c_nack(adap); - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - int i; - u32 data; - - i = 0; - while (i < len) { - data = buf[i]; - if (pic32_i2c_master_write(adap, data)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - i++; - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; - struct i2c_msg *p; - int i, err = 0; - - for (i = 0; i < num; i++) { -#define __BUFSIZE 80 - int ii; - static char buf[__BUFSIZE]; - char *b = buf; - - p = &msgs[i]; - b += sprintf(buf, " [%d bytes]", p->len); - if ((p->flags & I2C_M_RD) == 0) { - for (ii = 0; ii < p->len; ii++) { - if (b < &buf[__BUFSIZE-4]) { - b += sprintf(b, " %02x", p->buf[ii]); - } else { - strcat(b, "..."); - break; - } - } - } - } - - for (i = 0; !err && i < num; i++) { - p = &msgs[i]; - err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); - if (err || !p->len) - continue; - if (p->flags & I2C_M_RD) - err = sead3_i2c_read(adap, p->buf, p->len); - else - err = sead3_i2c_write(adap, p->buf, p->len); - } - - /* Return the number of messages processed, or the error code. */ - if (err == 0) - err = num; - - return err; -} - -static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm sead3_platform_algo = { - .master_xfer = sead3_pic32_platform_xfer, - .functionality = sead3_pic32_platform_func, -}; - -static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) -{ - pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, - priv->base + PIC32_I2CxSTATCLR); -} - -static int sead3_i2c_platform_probe(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv; - struct resource *r; - int ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } - - priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } - - priv->base = r->start; - if (!priv->base) { - ret = -EBUSY; - goto out_mem; - } - - priv->xfer_timeout = 200; - priv->ack_timeout = 200; - priv->ctl_timeout = 200; - - priv->adap.nr = pdev->id; - priv->adap.algo = &sead3_platform_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); - - sead3_i2c_platform_setup(priv); - - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; - } - -out_mem: - kfree(priv); -out: - return ret; -} - -static int sead3_i2c_platform_remove(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - kfree(priv); - return 0; -} - -#ifdef CONFIG_PM -static int sead3_i2c_platform_suspend(struct platform_device *pdev, - pm_message_t state) -{ - dev_dbg(&pdev->dev, "i2c_platform_disable\n"); - return 0; -} - -static int sead3_i2c_platform_resume(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); - sead3_i2c_platform_setup(priv); - - return 0; -} -#else -#define sead3_i2c_platform_suspend NULL -#define sead3_i2c_platform_resume NULL -#endif - -static struct platform_driver sead3_i2c_platform_driver = { - .driver = { - .name = "sead3-i2c", - }, - .probe = sead3_i2c_platform_probe, - .remove = sead3_i2c_platform_remove, - .suspend = sead3_i2c_platform_suspend, - .resume = sead3_i2c_platform_resume, -}; - -static int __init sead3_i2c_platform_init(void) -{ - return platform_driver_register(&sead3_i2c_platform_driver); -} -module_init(sead3_i2c_platform_init); - -static void __exit sead3_i2c_platform_exit(void) -{ - platform_driver_unregister(&sead3_i2c_platform_driver); -} -module_exit(sead3_i2c_platform_exit); - -MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); -MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); -MODULE_LICENSE("GPL"); diff --git a/arch/mips/mti-sead3/sead3-i2c.c b/arch/mips/mti-sead3/sead3-i2c.c deleted file mode 100644 index 795ae83894e0..000000000000 --- a/arch/mips/mti-sead3/sead3-i2c.c +++ /dev/null @@ -1,31 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/platform_device.h> - -struct resource sead3_i2c_resources[] = { - { - .start = 0x805200, - .end = 0x8053ff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device sead3_i2c_device = { - .name = "sead3-i2c", - .id = 0, - .num_resources = ARRAY_SIZE(sead3_i2c_resources), - .resource = sead3_i2c_resources, -}; - -static int __init sead3_i2c_init(void) -{ - return platform_device_register(&sead3_i2c_device); -} - -device_initcall(sead3_i2c_init); diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c index bfbd17b120a2..3572ea30173e 100644 --- a/arch/mips/mti-sead3/sead3-init.c +++ b/arch/mips/mti-sead3/sead3-init.c @@ -147,6 +147,6 @@ void __init prom_init(void) #endif } -void prom_free_prom_memory(void) +void __init prom_free_prom_memory(void) { } diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c deleted file mode 100644 index c427c5778186..000000000000 --- a/arch/mips/mti-sead3/sead3-leds.c +++ /dev/null @@ -1,79 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/leds.h> -#include <linux/platform_device.h> - -#define LEDFLAGS(bits, shift) \ - ((bits << 8) | (shift << 8)) - -#define LEDBITS(id, shift, bits) \ - .name = id #shift, \ - .flags = LEDFLAGS(bits, shift) - -struct led_info led_data_info[] = { - { LEDBITS("bit", 0, 1) }, - { LEDBITS("bit", 1, 1) }, - { LEDBITS("bit", 2, 1) }, - { LEDBITS("bit", 3, 1) }, - { LEDBITS("bit", 4, 1) }, - { LEDBITS("bit", 5, 1) }, - { LEDBITS("bit", 6, 1) }, - { LEDBITS("bit", 7, 1) }, - { LEDBITS("all", 0, 8) }, -}; - -static struct led_platform_data led_data = { - .num_leds = ARRAY_SIZE(led_data_info), - .leds = led_data_info -}; - -static struct resource pled_resources[] = { - { - .start = 0x1f000210, - .end = 0x1f000217, - .flags = IORESOURCE_MEM - } -}; - -static struct platform_device pled_device = { - .name = "sead3::pled", - .id = 0, - .dev = { - .platform_data = &led_data, - }, - .num_resources = ARRAY_SIZE(pled_resources), - .resource = pled_resources -}; - - -static struct resource fled_resources[] = { - { - .start = 0x1f000218, - .end = 0x1f00021f, - .flags = IORESOURCE_MEM - } -}; - -static struct platform_device fled_device = { - .name = "sead3::fled", - .id = 0, - .dev = { - .platform_data = &led_data, - }, - .num_resources = ARRAY_SIZE(fled_resources), - .resource = fled_resources -}; - -static int __init led_init(void) -{ - platform_device_register(&pled_device); - return platform_device_register(&fled_device); -} - -device_initcall(led_init); diff --git a/arch/mips/mti-sead3/sead3-mtd.c b/arch/mips/mti-sead3/sead3-mtd.c deleted file mode 100644 index f9c890d72677..000000000000 --- a/arch/mips/mti-sead3/sead3-mtd.c +++ /dev/null @@ -1,53 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/physmap.h> - -static struct mtd_partition sead3_mtd_partitions[] = { - { - .name = "User FS", - .offset = 0x00000000, - .size = 0x01fc0000, - }, { - .name = "Board Config", - .offset = 0x01fc0000, - .size = 0x00040000, - .mask_flags = MTD_WRITEABLE - }, -}; - -static struct physmap_flash_data sead3_flash_data = { - .width = 4, - .nr_parts = ARRAY_SIZE(sead3_mtd_partitions), - .parts = sead3_mtd_partitions -}; - -static struct resource sead3_flash_resource = { - .start = 0x1c000000, - .end = 0x1dffffff, - .flags = IORESOURCE_MEM -}; - -static struct platform_device sead3_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &sead3_flash_data, - }, - .num_resources = 1, - .resource = &sead3_flash_resource, -}; - -static int __init sead3_mtd_init(void) -{ - platform_device_register(&sead3_flash); - - return 0; -} -device_initcall(sead3_mtd_init); diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c deleted file mode 100644 index 46176b804576..000000000000 --- a/arch/mips/mti-sead3/sead3-net.c +++ /dev/null @@ -1,57 +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) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/module.h> -#include <linux/irq.h> -#include <linux/irqchip/mips-gic.h> -#include <linux/platform_device.h> -#include <linux/smsc911x.h> - -#include <asm/mips-boards/sead3int.h> - -static struct smsc911x_platform_config sead3_smsc911x_data = { - .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, - .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, - .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, - .phy_interface = PHY_INTERFACE_MODE_MII, -}; - -struct resource sead3_net_resources[] = { - { - .start = 0x1f010000, - .end = 0x1f01ffff, - .flags = IORESOURCE_MEM - }, - { - .flags = IORESOURCE_IRQ - } -}; - -static struct platform_device sead3_net_device = { - .name = "smsc911x", - .id = 0, - .dev = { - .platform_data = &sead3_smsc911x_data, - }, - .num_resources = ARRAY_SIZE(sead3_net_resources), - .resource = sead3_net_resources -}; - -static int __init sead3_net_init(void) -{ - if (gic_present) - sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET; - else - sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET; - return platform_device_register(&sead3_net_device); -} - -module_init(sead3_net_init); - -MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Network probe driver for SEAD-3"); diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c index 53ee6f1f018d..73b73efbfb05 100644 --- a/arch/mips/mti-sead3/sead3-platform.c +++ b/arch/mips/mti-sead3/sead3-platform.c @@ -5,10 +5,15 @@ * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. */ -#include <linux/module.h> +#include <linux/dma-mapping.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/irqchip/mips-gic.h> +#include <linux/leds.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> #include <linux/serial_8250.h> +#include <linux/smsc911x.h> #include <asm/mips-boards/sead3int.h> @@ -36,20 +41,183 @@ static struct platform_device uart8250_device = { }, }; -static int __init uart8250_init(void) +static struct smsc911x_platform_config sead3_smsc911x_data = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct resource sead3_net_resources[] = { + { + .start = 0x1f010000, + .end = 0x1f01ffff, + .flags = IORESOURCE_MEM + }, { + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device sead3_net_device = { + .name = "smsc911x", + .id = 0, + .dev = { + .platform_data = &sead3_smsc911x_data, + }, + .num_resources = ARRAY_SIZE(sead3_net_resources), + .resource = sead3_net_resources +}; + +static struct mtd_partition sead3_mtd_partitions[] = { + { + .name = "User FS", + .offset = 0x00000000, + .size = 0x01fc0000, + }, { + .name = "Board Config", + .offset = 0x01fc0000, + .size = 0x00040000, + .mask_flags = MTD_WRITEABLE + }, +}; + +static struct physmap_flash_data sead3_flash_data = { + .width = 4, + .nr_parts = ARRAY_SIZE(sead3_mtd_partitions), + .parts = sead3_mtd_partitions +}; + +static struct resource sead3_flash_resource = { + .start = 0x1c000000, + .end = 0x1dffffff, + .flags = IORESOURCE_MEM +}; + +static struct platform_device sead3_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &sead3_flash_data, + }, + .num_resources = 1, + .resource = &sead3_flash_resource, +}; + +#define LEDFLAGS(bits, shift) \ + ((bits << 8) | (shift << 8)) + +#define LEDBITS(id, shift, bits) \ + .name = id #shift, \ + .flags = LEDFLAGS(bits, shift) + +static struct led_info led_data_info[] = { + { LEDBITS("bit", 0, 1) }, + { LEDBITS("bit", 1, 1) }, + { LEDBITS("bit", 2, 1) }, + { LEDBITS("bit", 3, 1) }, + { LEDBITS("bit", 4, 1) }, + { LEDBITS("bit", 5, 1) }, + { LEDBITS("bit", 6, 1) }, + { LEDBITS("bit", 7, 1) }, + { LEDBITS("all", 0, 8) }, +}; + +static struct led_platform_data led_data = { + .num_leds = ARRAY_SIZE(led_data_info), + .leds = led_data_info +}; + +static struct resource pled_resources[] = { + { + .start = 0x1f000210, + .end = 0x1f000217, + .flags = IORESOURCE_MEM + } +}; + +static struct platform_device pled_device = { + .name = "sead3::pled", + .id = 0, + .dev = { + .platform_data = &led_data, + }, + .num_resources = ARRAY_SIZE(pled_resources), + .resource = pled_resources +}; + + +static struct resource fled_resources[] = { + { + .start = 0x1f000218, + .end = 0x1f00021f, + .flags = IORESOURCE_MEM + } +}; + +static struct platform_device fled_device = { + .name = "sead3::fled", + .id = 0, + .dev = { + .platform_data = &led_data, + }, + .num_resources = ARRAY_SIZE(fled_resources), + .resource = fled_resources +}; + +static struct platform_device sead3_led_device = { + .name = "sead3-led", + .id = -1, +}; + +static struct resource ehci_resources[] = { + { + .start = 0x1b200000, + .end = 0x1b200fff, + .flags = IORESOURCE_MEM + }, { + .flags = IORESOURCE_IRQ + } +}; + +static u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device ehci_device = { + .name = "sead3-ehci", + .id = 0, + .dev = { + .dma_mask = &sead3_usbdev_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32) + }, + .num_resources = ARRAY_SIZE(ehci_resources), + .resource = ehci_resources +}; + +static struct platform_device *sead3_platform_devices[] __initdata = { + &uart8250_device, + &sead3_flash, + &pled_device, + &fled_device, + &sead3_led_device, + &ehci_device, + &sead3_net_device, +}; + +static int __init sead3_platforms_device_init(void) { if (gic_present) { uart8250_data[0].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART0; uart8250_data[1].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART1; + ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI; + sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET; } else { uart8250_data[0].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART0; uart8250_data[1].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART1; + ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI; + sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET; } - return platform_device_register(&uart8250_device); -} -module_init(uart8250_init); + return platform_add_devices(sead3_platform_devices, + ARRAY_SIZE(sead3_platform_devices)); +} -MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for SEAD3"); +device_initcall(sead3_platforms_device_init); diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index 0823321c10e0..fb00606e352d 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -41,6 +41,15 @@ config DT_XLP_GVP pointer to the kernel. The corresponding DTS file is at arch/mips/netlogic/dts/xlp_gvp.dts +config DT_XLP_RVP + bool "Built-in device tree for XLP RVP boards" + default y + help + Add an FDT blob for XLP RVP board into the kernel. + This DTB will be used if the firmware does not pass in a DTB + pointer to the kernel. The corresponding DTS file is at + arch/mips/netlogic/dts/xlp_rvp.dts + config NLM_MULTINODE bool "Support for multi-chip boards" depends on NLM_XLP_BOARD diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index c100b9afa0ab..5f5d18b0e94d 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -230,16 +230,16 @@ static void nlm_init_node_irqs(int node) } } -void nlm_smp_irq_init(int hwcpuid) +void nlm_smp_irq_init(int hwtid) { - int node, cpu; + int cpu, node; - node = nlm_cpuid_to_node(hwcpuid); - cpu = hwcpuid % nlm_threads_per_node(); + cpu = hwtid % nlm_threads_per_node(); + node = hwtid / nlm_threads_per_node(); if (cpu == 0 && node != 0) nlm_init_node_irqs(node); - write_c0_eimr(nlm_current_node()->irqmask); + write_c0_eimr(nlm_get_node(node)->irqmask); } asmlinkage void plat_irq_dispatch(void) diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index 701c4bcb9e47..edbab9b8691f 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -60,7 +60,7 @@ li t0, LSU_DEFEATURE mfcr t1, t0 - lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */ + lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ or t1, t1, t2 mtcr t1, t0 @@ -235,6 +235,26 @@ EXPORT(nlm_boot_siblings) mfc0 v0, CP0_EBASE, 1 andi v0, 0x3ff /* v0 <- node/core */ + /* + * Errata: to avoid potential live lock, setup IFU_BRUB_RESERVE + * when running 4 threads per core + */ + andi v1, v0, 0x3 /* v1 <- thread id */ + bnez v1, 2f + nop + + /* thread 0 of each core. */ + li t0, CKSEG1ADDR(RESET_DATA_PHYS) + lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ + subu t1, 0x3 /* 4-thread per core mode? */ + bnez t1, 2f + nop + + li t0, IFU_BRUB_RESERVE + li t1, 0x55 + mtcr t1, t0 + _ehb +2: beqz v0, 4f /* boot cpu (cpuid == 0)? */ nop diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index e743bdd6e20c..dc3e327fbbac 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -59,17 +59,17 @@ void nlm_send_ipi_single(int logical_cpu, unsigned int action) { - int cpu, node; + unsigned int hwtid; uint64_t picbase; - cpu = cpu_logical_map(logical_cpu); - node = nlm_cpuid_to_node(cpu); - picbase = nlm_get_node(node)->picbase; + /* node id is part of hwtid, and needed for send_ipi */ + hwtid = cpu_logical_map(logical_cpu); + picbase = nlm_get_node(nlm_hwtid_to_node(hwtid))->picbase; if (action & SMP_CALL_FUNCTION) - nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_FUNCTION, 0); + nlm_pic_send_ipi(picbase, hwtid, IRQ_IPI_SMP_FUNCTION, 0); if (action & SMP_RESCHEDULE_YOURSELF) - nlm_pic_send_ipi(picbase, cpu, IRQ_IPI_SMP_RESCHEDULE, 0); + nlm_pic_send_ipi(picbase, hwtid, IRQ_IPI_SMP_RESCHEDULE, 0); } void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action) @@ -120,6 +120,7 @@ static void nlm_init_secondary(void) hwtid = hard_smp_processor_id(); current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE; + current_cpu_data.package = nlm_nodeid(); nlm_percpu_init(hwtid); nlm_smp_irq_init(hwtid); } @@ -145,16 +146,18 @@ static cpumask_t phys_cpu_present_mask; void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) { - int cpu, node; + uint64_t picbase; + int hwtid; + + hwtid = cpu_logical_map(logical_cpu); + picbase = nlm_get_node(nlm_hwtid_to_node(hwtid))->picbase; - cpu = cpu_logical_map(logical_cpu); - node = nlm_cpuid_to_node(logical_cpu); nlm_next_sp = (unsigned long)__KSTK_TOS(idle); nlm_next_gp = (unsigned long)task_thread_info(idle); /* barrier for sp/gp store above */ __sync(); - nlm_pic_send_ipi(nlm_get_node(node)->picbase, cpu, 1, 1); /* NMI */ + nlm_pic_send_ipi(picbase, hwtid, 1, 1); /* NMI */ } void __init nlm_smp_setup(void) @@ -182,7 +185,7 @@ void __init nlm_smp_setup(void) __cpu_number_map[i] = num_cpus; __cpu_logical_map[num_cpus] = i; set_cpu_possible(num_cpus, true); - node = nlm_cpuid_to_node(i); + node = nlm_hwtid_to_node(i); cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask); ++num_cpus; } diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index 0c0a1a606f73..5873c83e65be 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -40,7 +40,6 @@ #include <asm/netlogic/interrupt.h> #include <asm/netlogic/common.h> #include <asm/netlogic/haldefs.h> -#include <asm/netlogic/common.h> #if defined(CONFIG_CPU_XLP) #include <asm/netlogic/xlp-hal/iomap.h> diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c index c83dbf3689e2..7b066a44e679 100644 --- a/arch/mips/netlogic/xlp/ahci-init-xlp2.c +++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c @@ -203,6 +203,7 @@ static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel) static void config_sata_phy(u64 regbase) { u32 port, i, reg; + u8 val; for (port = 0; port < 2; port++) { for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++) @@ -210,6 +211,18 @@ static void config_sata_phy(u64 regbase) for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++) write_phy_reg(regbase, reg, port, sata_phy_config2[i]); + + /* Fix for PHY link up failures at lower temperatures */ + write_phy_reg(regbase, 0x800F, port, 0x1f); + + val = read_phy_reg(regbase, 0x0029, port); + write_phy_reg(regbase, 0x0029, port, val | (0x7 << 1)); + + val = read_phy_reg(regbase, 0x0056, port); + write_phy_reg(regbase, 0x0056, port, val & ~(1 << 3)); + + val = read_phy_reg(regbase, 0x0018, port); + write_phy_reg(regbase, 0x0018, port, val & ~(0x7 << 0)); } } diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c index a9d0fae02103..92be1a3258b1 100644 --- a/arch/mips/netlogic/xlp/ahci-init.c +++ b/arch/mips/netlogic/xlp/ahci-init.c @@ -151,7 +151,7 @@ static void nlm_sata_firmware_init(int node) static int __init nlm_ahci_init(void) { int node = 0; - int chip = read_c0_prid() & PRID_REV_MASK; + int chip = read_c0_prid() & PRID_IMP_MASK; if (chip == PRID_IMP_NETLOGIC_XLP3XX) nlm_sata_firmware_init(node); diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index 7cc46032b28e..a625bdb6d6aa 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -41,17 +41,21 @@ #include <asm/prom.h> -extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], - __dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[]; +extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_xlp_fvp_begin[], + __dtb_xlp_gvp_begin[], __dtb_xlp_rvp_begin[]; static void *xlp_fdt_blob; void __init *xlp_dt_init(void *fdtp) { if (!fdtp) { switch (current_cpu_data.processor_id & PRID_IMP_MASK) { +#ifdef CONFIG_DT_XLP_RVP + case PRID_IMP_NETLOGIC_XLP5XX: + fdtp = __dtb_xlp_rvp_begin; + break; +#endif #ifdef CONFIG_DT_XLP_GVP case PRID_IMP_NETLOGIC_XLP9XX: - case PRID_IMP_NETLOGIC_XLP5XX: fdtp = __dtb_xlp_gvp_begin; break; #endif diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index bc24beb3a426..a8f4144a0297 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -71,10 +71,20 @@ static int xlp9xx_irq_to_irt(int irq) switch (irq) { case PIC_GPIO_IRQ: return 12; + case PIC_I2C_0_IRQ: + return 125; + case PIC_I2C_1_IRQ: + return 126; + case PIC_I2C_2_IRQ: + return 127; + case PIC_I2C_3_IRQ: + return 128; case PIC_9XX_XHCI_0_IRQ: return 114; case PIC_9XX_XHCI_1_IRQ: return 115; + case PIC_9XX_XHCI_2_IRQ: + return 116; case PIC_UART_0_IRQ: return 133; case PIC_UART_1_IRQ: @@ -170,16 +180,23 @@ static int xlp_irq_to_irt(int irq) } if (devoff != 0) { + uint32_t val; + pcibase = nlm_pcicfg_base(devoff); - irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff; - /* HW weirdness, I2C IRT entry has to be fixed up */ - switch (irq) { - case PIC_I2C_1_IRQ: - irt = irt + 1; break; - case PIC_I2C_2_IRQ: - irt = irt + 2; break; - case PIC_I2C_3_IRQ: - irt = irt + 3; break; + val = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG); + if (val == 0xffffffff) { + irt = -1; + } else { + irt = val & 0xffff; + /* HW weirdness, I2C IRT entry has to be fixed up */ + switch (irq) { + case PIC_I2C_1_IRQ: + irt = irt + 1; break; + case PIC_I2C_2_IRQ: + irt = irt + 2; break; + case PIC_I2C_3_IRQ: + irt = irt + 3; break; + } } } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) && irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) { @@ -325,7 +342,7 @@ static unsigned int nlm_xlp2_get_pic_frequency(int node) /* Find the clock source PLL device for PIC */ if (cpu_xlp9xx) { reg_select = nlm_read_sys_reg(clockbase, - SYS_9XX_CLK_DEV_SEL) & 0x3; + SYS_9XX_CLK_DEV_SEL_REG) & 0x3; switch (reg_select) { case 0: ctrl_val0 = nlm_read_sys_reg(clockbase, @@ -354,7 +371,7 @@ static unsigned int nlm_xlp2_get_pic_frequency(int node) } } else { reg_select = (nlm_read_sys_reg(sysbase, - SYS_CLK_DEV_SEL) >> 22) & 0x3; + SYS_CLK_DEV_SEL_REG) >> 22) & 0x3; switch (reg_select) { case 0: ctrl_val0 = nlm_read_sys_reg(sysbase, @@ -410,7 +427,7 @@ static unsigned int nlm_xlp2_get_pic_frequency(int node) fdiv = fdiv/(1 << 13); pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv; - pll_out_freq_den = (1 << vco_post_div) * pll_post_div * 3; + pll_out_freq_den = (1 << vco_post_div) * pll_post_div * ref_div; if (pll_out_freq_den > 0) do_div(pll_out_freq_num, pll_out_freq_den); @@ -418,10 +435,10 @@ static unsigned int nlm_xlp2_get_pic_frequency(int node) /* PIC post divider, which happens after PLL */ if (cpu_xlp9xx) pic_div = nlm_read_sys_reg(clockbase, - SYS_9XX_CLK_DEV_DIV) & 0x3; + SYS_9XX_CLK_DEV_DIV_REG) & 0x3; else pic_div = (nlm_read_sys_reg(sysbase, - SYS_CLK_DEV_DIV) >> 22) & 0x3; + SYS_CLK_DEV_DIV_REG) >> 22) & 0x3; do_div(pll_out_freq_num, 1 << pic_div); return pll_out_freq_num; @@ -442,19 +459,21 @@ unsigned int nlm_get_cpu_frequency(void) /* * Fills upto 8 pairs of entries containing the DRAM map of a node - * if n < 0, get dram map for all nodes + * if node < 0, get dram map for all nodes */ -int xlp_get_dram_map(int n, uint64_t *dram_map) +int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries) { uint64_t bridgebase, base, lim; uint32_t val; unsigned int barreg, limreg, xlatreg; - int i, node, rv; + int i, n, rv; /* Look only at mapping on Node 0, we don't handle crazy configs */ bridgebase = nlm_get_bridge_regbase(0); rv = 0; for (i = 0; i < 8; i++) { + if (rv + 1 >= nentries) + break; if (cpu_is_xlp9xx()) { barreg = BRIDGE_9XX_DRAM_BAR(i); limreg = BRIDGE_9XX_DRAM_LIMIT(i); @@ -464,10 +483,10 @@ int xlp_get_dram_map(int n, uint64_t *dram_map) limreg = BRIDGE_DRAM_LIMIT(i); xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i); } - if (n >= 0) { + if (node >= 0) { /* node specified, get node mapping of BAR */ val = nlm_read_bridge_reg(bridgebase, xlatreg); - node = (val >> 1) & 0x3; + n = (val >> 1) & 0x3; if (n != node) continue; } diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 4fdd9fd29d1d..f743fd9da323 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -51,7 +51,6 @@ uint64_t nlm_io_base; struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; cpumask_t nlm_cpumask = CPU_MASK_CPU0; unsigned int nlm_threads_per_core; -unsigned int xlp_cores_per_node; static void nlm_linux_exit(void) { @@ -82,7 +81,7 @@ static void __init xlp_init_mem_from_bars(void) uint64_t map[16]; int i, n; - n = xlp_get_dram_map(-1, map); /* -1: info for all nodes */ + n = nlm_get_dram_map(-1, map, ARRAY_SIZE(map)); /* -1 : all nodes */ for (i = 0; i < n; i += 2) { /* exclude 0x1000_0000-0x2000_0000, u-boot device */ if (map[i] <= 0x10000000 && map[i+1] > 0x10000000) @@ -163,10 +162,6 @@ void __init prom_init(void) void *reset_vec; nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); - if (cpu_is_xlp9xx()) - xlp_cores_per_node = 32; - else - xlp_cores_per_node = 8; nlm_init_boot_cpu(); xlp_mmu_init(); nlm_node_init(0); diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c index 17ade1ce5dfd..2524939a5e3a 100644 --- a/arch/mips/netlogic/xlp/usb-init-xlp2.c +++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c @@ -128,6 +128,9 @@ static void xlp9xx_usb_ack(struct irq_data *data) case PIC_9XX_XHCI_1_IRQ: port_addr = nlm_xlpii_get_usb_regbase(node, 2); break; + case PIC_9XX_XHCI_2_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(node, 3); + break; default: pr_err("No matching USB irq %d node %d!\n", irq, node); return; @@ -222,14 +225,16 @@ static int __init nlm_platform_xlpii_usb_init(void) } /* XLP 9XX, multi-node */ - pr_info("Initializing 9XX USB Interface\n"); + pr_info("Initializing 9XX/5XX USB Interface\n"); for (node = 0; node < NLM_NR_NODES; node++) { if (!nlm_node_present(node)) continue; nlm_xlpii_usb_hw_reset(node, 1); nlm_xlpii_usb_hw_reset(node, 2); + nlm_xlpii_usb_hw_reset(node, 3); nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack); nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack); + nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_2_IRQ, xlp9xx_usb_ack); } return 0; } @@ -253,6 +258,9 @@ static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev) case 0x22: dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ); break; + case 0x23: + dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_2_IRQ); + break; } } diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index e5f44d2605a8..87d7846af2d0 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -99,7 +99,7 @@ static int wait_for_cpus(int cpu, int bootcpu) do { notready = nlm_threads_per_core; for (i = 0; i < nlm_threads_per_core; i++) - if (cpu_ready[cpu + i] || cpu == bootcpu) + if (cpu_ready[cpu + i] || (cpu + i) == bootcpu) --notready; } while (notready != 0 && --count > 0); @@ -111,7 +111,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) struct nlm_soc_info *nodep; uint64_t syspcibase, fusebase; uint32_t syscoremask, mask, fusemask; - int core, n, cpu; + int core, n, cpu, ncores; for (n = 0; n < NLM_NR_NODES; n++) { if (n != 0) { @@ -168,7 +168,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) syscoremask = (1 << hweight32(~fusemask & mask)) - 1; pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask); - for (core = 0; core < nlm_cores_per_node(); core++) { + ncores = nlm_cores_per_node(); + for (core = 0; core < ncores; core++) { /* we will be on node 0 core 0 */ if (n == 0 && core == 0) continue; @@ -178,8 +179,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) continue; /* see if at least the first hw thread is enabled */ - cpu = (n * nlm_cores_per_node() + core) - * NLM_THREADS_PER_CORE; + cpu = (n * ncores + core) * NLM_THREADS_PER_CORE; if (!cpumask_test_cpu(cpu, wakeup_mask)) continue; diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index a26cbe372e06..81f58958cf08 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -98,6 +98,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_R10000: case CPU_R12000: case CPU_R14000: + case CPU_R16000: case CPU_XLR: lmodel = &op_model_mipsxx_ops; break; diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 01f721a85c5b..6a6e2cc55b89 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -246,7 +246,7 @@ static int mipsxx_perfcount_handler(void) unsigned int counter; int handled = IRQ_NONE; - if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26))) + if (cpu_has_mips_r2 && !(read_c0_cause() & CAUSEF_PCI)) return handled; switch (counters) { @@ -296,6 +296,7 @@ static inline int n_counters(void) case CPU_R12000: case CPU_R14000: + case CPU_R16000: counters = 4; break; @@ -411,6 +412,10 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/r12000"; break; + case CPU_R16000: + op_model_mipsxx_ops.cpu_type = "mips/r16000"; + break; + case CPU_SB1: case CPU_SB1A: op_model_mipsxx_ops.cpu_type = "mips/sb1"; @@ -435,15 +440,17 @@ static int __init mipsxx_init(void) if (get_c0_perfcount_int) perfcount_irq = get_c0_perfcount_int(); - else if ((cp0_perfcount_irq >= 0) && - (cp0_compare_irq != cp0_perfcount_irq)) + else if (cp0_perfcount_irq >= 0) perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; else perfcount_irq = -1; if (perfcount_irq >= 0) return request_irq(perfcount_irq, mipsxx_perfcount_int, - 0, "Perfcounter", save_perf_irq); + IRQF_PERCPU | IRQF_NOBALANCING | + IRQF_NO_THREAD | IRQF_NO_SUSPEND | + IRQF_SHARED, + "Perfcounter", save_perf_irq); return 0; } diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 300591c6278d..2eda01e6e08f 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -43,7 +43,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o obj-$(CONFIG_LANTIQ) += fixup-lantiq.o obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o -obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o +obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index 6a40f24c91b4..3407495fcbe2 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c @@ -178,13 +178,6 @@ static void xlp_msi_mask_ack(struct irq_data *d) else nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); - /* Ack at eirr and PIC */ - ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); - if (cpu_is_xlp9xx()) - nlm_pic_ack(md->node->picbase, - PIC_9XX_IRT_PCIE_LINK_INDEX(link)); - else - nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); } static struct irq_chip xlp_msi_chip = { @@ -230,8 +223,6 @@ static void xlp_msix_mask_ack(struct irq_data *d) } nlm_write_reg(md->lnkbase, status_reg, 1u << bit); - /* Ack at eirr and PIC */ - ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); if (!cpu_is_xlp9xx()) nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); @@ -541,6 +532,14 @@ void nlm_dispatch_msi(int node, int lirq) do_IRQ(irqbase + i); status &= status - 1; } + + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); + if (cpu_is_xlp9xx()) + nlm_pic_ack(md->node->picbase, + PIC_9XX_IRT_PCIE_LINK_INDEX(link)); + else + nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); } void nlm_dispatch_msix(int node, int lirq) @@ -567,4 +566,6 @@ void nlm_dispatch_msix(int node, int lirq) do_IRQ(irqbase + i); status &= status - 1; } + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); } diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c index bd2b3b60da83..07a18228e63a 100644 --- a/arch/mips/pci/pci-ar2315.c +++ b/arch/mips/pci/pci-ar2315.c @@ -488,7 +488,6 @@ static struct platform_driver ar2315_pci_driver = { .probe = ar2315_pci_probe, .driver = { .name = "ar2315-pci", - .owner = THIS_MODULE, }, }; diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index a04af55d89f1..c258cd406fbb 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -214,6 +214,8 @@ const char *octeon_get_pci_interrupts(void) return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; case CVMX_BOARD_TYPE_BBGW_REF: return "AABCD"; + case CVMX_BOARD_TYPE_CUST_DSR1000N: + return "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"; case CVMX_BOARD_TYPE_THUNDER: case CVMX_BOARD_TYPE_EBH3000: default: @@ -271,9 +273,6 @@ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, pci_addr.s.func = devfn & 0x7; pci_addr.s.reg = reg; -#if PCI_CONFIG_SPACE_DELAY - udelay(PCI_CONFIG_SPACE_DELAY); -#endif switch (size) { case 4: *val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64)); @@ -308,9 +307,6 @@ static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, pci_addr.s.func = devfn & 0x7; pci_addr.s.reg = reg; -#if PCI_CONFIG_SPACE_DELAY - udelay(PCI_CONFIG_SPACE_DELAY); -#endif switch (size) { case 4: cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val)); diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c index a4574947e698..8a978022630b 100644 --- a/arch/mips/pci/pci-rt2880.c +++ b/arch/mips/pci/pci-rt2880.c @@ -267,7 +267,6 @@ static struct platform_driver rt288x_pci_driver = { .probe = rt288x_pci_probe, .driver = { .name = "rt288x-pci", - .owner = THIS_MODULE, .of_match_table = rt288x_pci_match, }, }; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 1bf60b127377..b8a0bf5766f2 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -91,30 +91,35 @@ static void pcibios_scanbus(struct pci_controller *hose) pci_add_resource_offset(&resources, hose->mem_resource, hose->mem_offset); - pci_add_resource_offset(&resources, hose->io_resource, hose->io_offset); + pci_add_resource_offset(&resources, + hose->io_resource, hose->io_offset); + pci_add_resource_offset(&resources, + hose->busn_resource, hose->busn_offset); bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose, &resources); - if (!bus) - pci_free_resource_list(&resources); - hose->bus = bus; need_domain_info = need_domain_info || hose->index; hose->need_domain_info = need_domain_info; - if (bus) { - next_busno = bus->busn_res.end + 1; - /* Don't allow 8-bit bus number overflow inside the hose - - reserve some space for bridges. */ - if (next_busno > 224) { - next_busno = 0; - need_domain_info = 1; - } - if (!pci_has_flag(PCI_PROBE_ONLY)) { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); - } + if (!bus) { + pci_free_resource_list(&resources); + return; + } + + next_busno = bus->busn_res.end + 1; + /* Don't allow 8-bit bus number overflow inside the hose - + reserve some space for bridges. */ + if (next_busno > 224) { + next_busno = 0; + need_domain_info = 1; + } + + if (!pci_has_flag(PCI_PROBE_ONLY)) { + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); } + pci_bus_add_devices(bus); } #ifdef CONFIG_OF diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index 1bb0b2bf8d6e..99f3db4f0a9b 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -1762,14 +1762,6 @@ static int octeon_pcie_write_config(unsigned int pcie_port, struct pci_bus *bus, default: return PCIBIOS_FUNC_NOT_SUPPORTED; } -#if PCI_CONFIG_SPACE_DELAY - /* - * Delay on writes so that devices have time to come up. Some - * bridges need this to allow time for the secondary busses to - * work - */ - udelay(PCI_CONFIG_SPACE_DELAY); -#endif return PCIBIOS_SUCCESSFUL; } diff --git a/arch/mips/pistachio/Makefile b/arch/mips/pistachio/Makefile new file mode 100644 index 000000000000..32189c6ebea5 --- /dev/null +++ b/arch/mips/pistachio/Makefile @@ -0,0 +1 @@ +obj-y += init.o irq.o time.o diff --git a/arch/mips/pistachio/Platform b/arch/mips/pistachio/Platform new file mode 100644 index 000000000000..d80cd612df1f --- /dev/null +++ b/arch/mips/pistachio/Platform @@ -0,0 +1,8 @@ +# +# IMG Pistachio SoC +# +platform-$(CONFIG_MACH_PISTACHIO) += pistachio/ +cflags-$(CONFIG_MACH_PISTACHIO) += \ + -I$(srctree)/arch/mips/include/asm/mach-pistachio +load-$(CONFIG_MACH_PISTACHIO) += 0xffffffff80400000 +zload-$(CONFIG_MACH_PISTACHIO) += 0xffffffff81000000 diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c new file mode 100644 index 000000000000..d2dc836523a3 --- /dev/null +++ b/arch/mips/pistachio/init.c @@ -0,0 +1,131 @@ +/* + * Pistachio platform setup + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> + +#include <asm/cacheflush.h> +#include <asm/dma-coherence.h> +#include <asm/fw/fw.h> +#include <asm/mips-boards/generic.h> +#include <asm/mips-cm.h> +#include <asm/mips-cpc.h> +#include <asm/prom.h> +#include <asm/smp-ops.h> +#include <asm/traps.h> + +const char *get_system_type(void) +{ + return "IMG Pistachio SoC"; +} + +static void __init plat_setup_iocoherency(void) +{ + /* + * Kernel has been configured with software coherency + * but we might choose to turn it off and use hardware + * coherency instead. + */ + if (mips_cm_numiocu() != 0) { + /* Nothing special needs to be done to enable coherency */ + pr_info("CMP IOCU detected\n"); + hw_coherentio = 1; + if (coherentio == 0) + pr_info("Hardware DMA cache coherency disabled\n"); + else + pr_info("Hardware DMA cache coherency enabled\n"); + } else { + if (coherentio == 1) + pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n"); + else + pr_info("Software DMA cache coherency enabled\n"); + } +} + +void __init plat_mem_setup(void) +{ + if (fw_arg0 != -2) + panic("Device-tree not present"); + + __dt_setup_arch((void *)fw_arg1); + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + + plat_setup_iocoherency(); +} + +#define DEFAULT_CPC_BASE_ADDR 0x1bde0000 + +phys_addr_t mips_cpc_default_phys_base(void) +{ + return DEFAULT_CPC_BASE_ADDR; +} + +static void __init mips_nmi_setup(void) +{ + void *base; + extern char except_vec_nmi; + + base = cpu_has_veic ? + (void *)(CAC_BASE + 0xa80) : + (void *)(CAC_BASE + 0x380); + memcpy(base, &except_vec_nmi, 0x80); + flush_icache_range((unsigned long)base, + (unsigned long)base + 0x80); +} + +static void __init mips_ejtag_setup(void) +{ + void *base; + extern char except_vec_ejtag_debug; + + base = cpu_has_veic ? + (void *)(CAC_BASE + 0xa00) : + (void *)(CAC_BASE + 0x300); + memcpy(base, &except_vec_ejtag_debug, 0x80); + flush_icache_range((unsigned long)base, + (unsigned long)base + 0x80); +} + +void __init prom_init(void) +{ + board_nmi_handler_setup = mips_nmi_setup; + board_ejtag_handler_setup = mips_ejtag_setup; + + mips_cm_probe(); + mips_cpc_probe(); + register_cps_smp_ops(); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init device_tree_init(void) +{ + if (!initial_boot_params) + return; + + unflatten_and_copy_device_tree(); +} + +static int __init plat_of_setup(void) +{ + if (!of_have_populated_dt()) + panic("Device tree not present"); + + if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)) + panic("Failed to populate DT"); + + return 0; +} +arch_initcall(plat_of_setup); diff --git a/arch/mips/pistachio/irq.c b/arch/mips/pistachio/irq.c new file mode 100644 index 000000000000..0a6b24c24652 --- /dev/null +++ b/arch/mips/pistachio/irq.c @@ -0,0 +1,28 @@ +/* + * Pistachio IRQ setup + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/irqchip.h> +#include <linux/irqchip/mips-gic.h> +#include <linux/kernel.h> + +#include <asm/cpu-features.h> +#include <asm/irq_cpu.h> + +void __init arch_init_irq(void) +{ + pr_info("EIC is %s\n", cpu_has_veic ? "on" : "off"); + pr_info("VINT is %s\n", cpu_has_vint ? "on" : "off"); + + if (!cpu_has_veic) + mips_cpu_irq_init(); + + irqchip_init(); +} diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c new file mode 100644 index 000000000000..67889fcea8aa --- /dev/null +++ b/arch/mips/pistachio/time.c @@ -0,0 +1,52 @@ +/* + * Pistachio clocksource/timer setup + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clocksource.h> +#include <linux/init.h> +#include <linux/irqchip/mips-gic.h> +#include <linux/of.h> + +#include <asm/time.h> + +unsigned int get_c0_compare_int(void) +{ + return gic_get_c0_compare_int(); +} + +int get_c0_perfcount_int(void) +{ + return gic_get_c0_perfcount_int(); +} + +void __init plat_time_init(void) +{ + struct device_node *np; + struct clk *clk; + + of_clk_init(NULL); + clocksource_of_init(); + + np = of_get_cpu_node(0, NULL); + if (!np) { + pr_err("Failed to get CPU node\n"); + return; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk)); + return; + } + + mips_hpt_frequency = clk_get_rate(clk) / 2; + clk_put(clk); +} diff --git a/arch/mips/power/Makefile b/arch/mips/power/Makefile index 73d56b87cb9b..70bd7883bc1b 100644 --- a/arch/mips/power/Makefile +++ b/arch/mips/power/Makefile @@ -1 +1 @@ -obj-$(CONFIG_HIBERNATION) += cpu.o hibernate.o +obj-$(CONFIG_HIBERNATION) += cpu.o hibernate.o hibernate_asm.o diff --git a/arch/mips/power/hibernate.c b/arch/mips/power/hibernate.c new file mode 100644 index 000000000000..19a9af68bcdb --- /dev/null +++ b/arch/mips/power/hibernate.c @@ -0,0 +1,10 @@ +#include <asm/tlbflush.h> + +extern int restore_image(void); + +int swsusp_arch_resume(void) +{ + /* Avoid TLB mismatch during and after kernel resume */ + local_flush_tlb_all(); + return restore_image(); +} diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate_asm.S index 32a7c828f073..b1fab951100f 100644 --- a/arch/mips/power/hibernate.S +++ b/arch/mips/power/hibernate_asm.S @@ -29,7 +29,7 @@ LEAF(swsusp_arch_suspend) j swsusp_save END(swsusp_arch_suspend) -LEAF(swsusp_arch_resume) +LEAF(restore_image) PTR_L t0, restore_pblist 0: PTR_L t1, PBE_ADDRESS(t0) /* source */ @@ -43,7 +43,6 @@ LEAF(swsusp_arch_resume) bne t1, t3, 1b PTR_L t0, PBE_NEXT(t0) bnez t0, 0b - jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */ PTR_LA t0, saved_regs PTR_L ra, PT_R31(t0) PTR_L sp, PT_R29(t0) @@ -59,4 +58,4 @@ LEAF(swsusp_arch_resume) PTR_L s7, PT_R23(t0) PTR_LI v0, 0x0 jr ra -END(swsusp_arch_resume) +END(restore_image) diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index b1c52ca580f9..e9bc8c96174e 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -7,6 +7,11 @@ config CLKEVT_RT3352 select CLKSRC_OF select CLKSRC_MMIO +config RALINK_ILL_ACC + bool + depends on SOC_RT305X + default y + choice prompt "Ralink SoC selection" default SOC_RT305X diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 1d97eaba0c5f..a6d10f607f34 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -7,6 +7,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/sched_clock.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> #include <linux/param.h> @@ -159,11 +160,18 @@ struct clocksource hub_rt_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 notrace hub_rt_read_sched_clock(void) +{ + return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); +} + static void __init hub_rt_clocksource_init(void) { struct clocksource *cs = &hub_rt_clocksource; clocksource_register_hz(cs, CYCLES_PER_SEC); + + sched_clock_register(hub_rt_read_sched_clock, 52, CYCLES_PER_SEC); } void __init plat_time_init(void) diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c index 511e9ff2acfd..0134db2ad0a8 100644 --- a/arch/mips/sgi-ip32/ip32-platform.c +++ b/arch/mips/sgi-ip32/ip32-platform.c @@ -5,14 +5,16 @@ * * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) */ -#include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/serial_8250.h> +#include <linux/rtc/ds1685.h> #include <asm/ip32/mace.h> #include <asm/ip32/ip32_ints.h> +extern void ip32_prepare_poweroff(void); + #define MACEISA_SERIAL1_OFFS offsetof(struct sgi_mace, isa.serial1) #define MACEISA_SERIAL2_OFFS offsetof(struct sgi_mace, isa.serial2) @@ -90,22 +92,47 @@ static __init int sgio2btns_devinit(void) device_initcall(sgio2btns_devinit); -static struct resource sgio2_cmos_rsrc[] = { +#define MACE_RTC_RES_START (MACE_BASE + offsetof(struct sgi_mace, isa.rtc)) +#define MACE_RTC_RES_END (MACE_RTC_RES_START + 32767) + +static struct resource ip32_rtc_resources[] = { { - .start = 0x70, - .end = 0x71, - .flags = IORESOURCE_IO + .start = MACEISA_RTC_IRQ, + .end = MACEISA_RTC_IRQ, + .flags = IORESOURCE_IRQ + }, { + .start = MACE_RTC_RES_START, + .end = MACE_RTC_RES_END, + .flags = IORESOURCE_MEM, } }; -static __init int sgio2_cmos_devinit(void) +/* RTC registers on IP32 are each padded by 256 bytes (0x100). */ +static struct ds1685_rtc_platform_data +ip32_rtc_platform_data[] = { + { + .regstep = 0x100, + .bcd_mode = true, + .no_irq = false, + .uie_unsupported = false, + .alloc_io_resources = true, + .plat_prepare_poweroff = ip32_prepare_poweroff, + }, +}; + +struct platform_device ip32_rtc_device = { + .name = "rtc-ds1685", + .id = -1, + .dev = { + .platform_data = ip32_rtc_platform_data, + }, + .num_resources = ARRAY_SIZE(ip32_rtc_resources), + .resource = ip32_rtc_resources, +}; + ++static int __init sgio2_rtc_devinit(void) { - return IS_ERR(platform_device_register_simple("rtc_cmos", -1, - sgio2_cmos_rsrc, 1)); + return platform_device_register(&ip32_rtc_device); } device_initcall(sgio2_cmos_devinit); - -MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2"); diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 44b3470a0bbb..8bd415c8729f 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -11,10 +11,11 @@ #include <linux/compiler.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/notifier.h> #include <linux/delay.h> -#include <linux/ds17287rtc.h> +#include <linux/rtc/ds1685.h> #include <linux/interrupt.h> #include <linux/pm.h> @@ -33,53 +34,40 @@ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) -static struct timer_list power_timer, blink_timer, debounce_timer; -static int has_panicked, shuting_down; +extern struct platform_device ip32_rtc_device; -static void ip32_machine_restart(char *command) __noreturn; -static void ip32_machine_halt(void) __noreturn; -static void ip32_machine_power_off(void) __noreturn; +static struct timer_list power_timer, blink_timer; +static int has_panicked, shutting_down; -static void ip32_machine_restart(char *cmd) +static __noreturn void ip32_poweroff(void *data) { - crime->control = CRIME_CONTROL_HARD_RESET; - while (1); -} + void (*poweroff_func)(struct platform_device *) = + symbol_get(ds1685_rtc_poweroff); + +#ifdef CONFIG_MODULES + /* If the first __symbol_get failed, our module wasn't loaded. */ + if (!poweroff_func) { + request_module("rtc-ds1685"); + poweroff_func = symbol_get(ds1685_rtc_poweroff); + } +#endif -static inline void ip32_machine_halt(void) -{ - ip32_machine_power_off(); -} + if (!poweroff_func) + pr_emerg("RTC not available for power-off. Spinning forever ...\n"); + else { + (*poweroff_func)((struct platform_device *)data); + symbol_put(ds1685_rtc_poweroff); + } -static void ip32_machine_power_off(void) -{ - unsigned char reg_a, xctrl_a, xctrl_b; - - disable_irq(MACEISA_RTC_IRQ); - reg_a = CMOS_READ(RTC_REG_A); - - /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */ - reg_a &= ~DS_REGA_DV2; - reg_a |= DS_REGA_DV1; - - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_b = CMOS_READ(DS_B1_XCTRL4B) - | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE; - CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS; - CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A); - wbflush(); - /* adios amigos... */ - CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a, RTC_REG_A); - wbflush(); - while (1); + unreachable(); } -static void power_timeout(unsigned long data) +static void ip32_machine_restart(char *cmd) __noreturn; +static void ip32_machine_restart(char *cmd) { - ip32_machine_power_off(); + msleep(20); + crime->control = CRIME_CONTROL_HARD_RESET; + unreachable(); } static void blink_timeout(unsigned long data) @@ -89,44 +77,27 @@ static void blink_timeout(unsigned long data) mod_timer(&blink_timer, jiffies + data); } -static void debounce(unsigned long data) +static void ip32_machine_halt(void) { - unsigned char reg_a, reg_c, xctrl_a; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - reg_a = CMOS_READ(RTC_REG_A); - CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); - wbflush(); - xctrl_a = CMOS_READ(DS_B1_XCTRL4A); - if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) { - /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - /* clear interrupt source */ - CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - return; - } - CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - - if (has_panicked) - ip32_machine_restart(NULL); + ip32_poweroff(&ip32_rtc_device); +} - enable_irq(MACEISA_RTC_IRQ); +static void power_timeout(unsigned long data) +{ + ip32_poweroff(&ip32_rtc_device); } -static inline void ip32_power_button(void) +void ip32_prepare_poweroff(void) { if (has_panicked) return; - if (shuting_down || kill_cad_pid(SIGINT, 1)) { + if (shutting_down || kill_cad_pid(SIGINT, 1)) { /* No init process or button pressed twice. */ - ip32_machine_power_off(); + ip32_poweroff(&ip32_rtc_device); } - shuting_down = 1; + shutting_down = 1; blink_timer.data = POWERDOWN_FREQ; blink_timeout(POWERDOWN_FREQ); @@ -136,27 +107,6 @@ static inline void ip32_power_button(void) add_timer(&power_timer); } -static irqreturn_t ip32_rtc_int(int irq, void *dev_id) -{ - unsigned char reg_c; - - reg_c = CMOS_READ(RTC_INTR_FLAGS); - if (!(reg_c & RTC_IRQF)) { - printk(KERN_WARNING - "%s: RTC IRQ without RTC_IRQF\n", __func__); - } - /* Wait until interrupt goes away */ - disable_irq_nosync(MACEISA_RTC_IRQ); - init_timer(&debounce_timer); - debounce_timer.function = debounce; - debounce_timer.expires = jiffies + 50; - add_timer(&debounce_timer); - - printk(KERN_DEBUG "Power button pressed\n"); - ip32_power_button(); - return IRQ_HANDLED; -} - static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -190,15 +140,12 @@ static __init int ip32_reboot_setup(void) _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; - pm_power_off = ip32_machine_power_off; + pm_power_off = ip32_machine_halt; init_timer(&blink_timer); blink_timer.function = blink_timeout; atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) - panic("Can't allocate MACEISA RTC IRQ"); - return 0; } |