diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
commit | cdfc83075fb76369a31e6c187d0cebcab9f8b9c8 (patch) | |
tree | 33d1cdca3e2cb610451ed30943189f55652bac4c | |
parent | 04a24ae45d018e177db7e4ae2d03a70f79149782 (diff) | |
parent | b26a21c1eacdb7daf22a304fa857413df2650cfe (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"The most notable new addition inside this pull request is the support
for MIPS's latest and greatest core called "inter/proAptiv". The
patch series describes this core as follows.
"The interAptiv is a power-efficient multi-core microprocessor
for use in system-on-chip (SoC) applications. The interAptiv combines
a multi-threading pipeline with a coherence manager to deliver improved
computational throughput and power efficiency. The interAptiv can
contain one to four MIPS32R3 interAptiv cores, system level
coherence manager with L2 cache, optional coherent I/O port,
and optional floating point unit."
The platform specific patches touch all 3 Broadcom families. It adds
support for the new Broadcom/Netlogix XLP9xx Soc, building a common
BCM63XX SMP kernel for all BCM63XX SoCs regardless of core type/count
and full gpio button/led descriptions for BCM47xx.
The rest of the series are cleanups and bug fixes that are MIPS
generic and consist largely of changes that Imgtec/MIPS had published
in their linux-mti-3.10.git stable tree. Random other cleanups and
patches preparing code to be merged in 3.15"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (139 commits)
mips: select ARCH_MIGHT_HAVE_PC_SERIO
mips: delete non-required instances of include <linux/init.h>
MIPS: KVM: remove shadow_tlb code
MIPS: KVM: use common EHINV aware UNIQUE_ENTRYHI
mips/ide: flush dcache also if icache does not snoop dcache
MIPS: BCM47XX: fix position of cpu_wait disabling
MIPS: BCM63XX: select correct MIPS_L1_CACHE_SHIFT value
MIPS: update MIPS_L1_CACHE_SHIFT based on MIPS_L1_CACHE_SHIFT_<N>
MIPS: introduce MIPS_L1_CACHE_SHIFT_<N>
MIPS: ZBOOT: gather string functions into string.c
arch/mips/pci: don't check resource with devm_ioremap_resource
arch/mips/lantiq/xway: don't check resource with devm_ioremap_resource
bcma: gpio: don't cast u32 to unsigned long
ssb: gpio: add own IRQ domain
MIPS: BCM47XX: fix sparse warnings in board.c
MIPS: BCM47XX: add board detection for Linksys WRT54GS V1
MIPS: BCM47XX: fix detection for some boards
MIPS: BCM47XX: Enable buttons support on SSB
MIPS: BCM47XX: Convert WNDR4500 to new syntax
MIPS: BCM47XX: Use "timer" trigger for status LEDs
...
224 files changed, 6635 insertions, 3316 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c02f1c03a22e..dcae3a7035db 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -116,7 +116,6 @@ config BCM47XX select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT - select FW_CFE select HW_HAS_PCI select IRQ_CPU select SYS_HAS_CPU_MIPS32_R1 @@ -124,6 +123,7 @@ config BCM47XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK + select EARLY_PRINTK_8250 if EARLY_PRINTK help Support for BCM47XX based boards @@ -134,14 +134,13 @@ config BCM63XX select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU - select SYS_HAS_CPU_MIPS32_R1 - select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK select SWAP_IO_SPACE select ARCH_REQUIRE_GPIOLIB select HAVE_CLK + select MIPS_L1_CACHE_SHIFT_4 help Support for BCM63XX based boards @@ -186,6 +185,7 @@ config MACH_DECSTATION select SYS_SUPPORTS_128HZ select SYS_SUPPORTS_256HZ select SYS_SUPPORTS_1024HZ + select MIPS_L1_CACHE_SHIFT_4 help This enables support for DEC's MIPS based workstations. For details see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the @@ -305,7 +305,7 @@ config MIPS_MALTA select CEVT_R4K select CSRC_R4K select CSRC_GIC - select DMA_NONCOHERENT + select DMA_MAYBE_COHERENT select GENERIC_ISA_DMA select HAVE_PCSPKR_PLATFORM select IRQ_CPU @@ -324,7 +324,6 @@ config MIPS_MALTA select SYS_HAS_CPU_MIPS64_R2 select SYS_HAS_CPU_NEVADA select SYS_HAS_CPU_RM7000 - select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN @@ -349,6 +348,7 @@ config MIPS_SEAD3 select DMA_NONCOHERENT select IRQ_CPU select IRQ_GIC + select LIBFDT select MIPS_MSC select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 @@ -471,6 +471,7 @@ config SGI_IP22 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select MIPS_L1_CACHE_SHIFT_7 help This are the SGI Indy, Challenge S and Indigo2, as well as certain OEM variants like the Tandem CMN B006S. To compile a Linux kernel @@ -491,6 +492,7 @@ config SGI_IP27 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_SMP + select MIPS_L1_CACHE_SHIFT_7 help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -697,6 +699,7 @@ config MIKROTIK_RB532 select SWAP_IO_SPACE select BOOT_RAW select ARCH_REQUIRE_GPIOLIB + select MIPS_L1_CACHE_SHIFT_4 help Support the Mikrotik(tm) RouterBoard 532 series, based on the IDT RC32434 SoC. @@ -779,6 +782,7 @@ config NLM_XLP_BOARD select CEVT_R4K select CSRC_R4K select IRQ_CPU + select ARCH_SUPPORTS_MSI select ZONE_DMA32 if 64BIT select SYNC_R4K select SYS_HAS_EARLY_PRINTK @@ -897,6 +901,10 @@ config FW_CFE config ARCH_DMA_ADDR_T_64BIT def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT +config DMA_MAYBE_COHERENT + select DMA_NONCOHERENT + bool + config DMA_COHERENT bool @@ -1091,11 +1099,24 @@ config FW_SNIPROM config BOOT_ELF32 bool +config MIPS_L1_CACHE_SHIFT_4 + bool + +config MIPS_L1_CACHE_SHIFT_5 + bool + +config MIPS_L1_CACHE_SHIFT_6 + bool + +config MIPS_L1_CACHE_SHIFT_7 + bool + config MIPS_L1_CACHE_SHIFT int - default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X - default "6" if MIPS_CPU_SCACHE - default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON + 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 "5" config HAVE_STD_PC_SERIAL_PORT @@ -1375,47 +1396,31 @@ config CPU_CAVIUM_OCTEON select LIBFDT select USE_OF select USB_EHCI_BIG_ENDIAN_MMIO + select SYS_HAS_DMA_OPS + select MIPS_L1_CACHE_SHIFT_7 help The Cavium Octeon processor is a highly integrated chip containing many ethernet hardware widgets for networking tasks. The processor can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets. Full details can be found at http://www.caviumnetworks.com. -config CPU_BMIPS3300 - bool "BMIPS3300" - depends on SYS_HAS_CPU_BMIPS3300 - select CPU_BMIPS - help - Broadcom BMIPS3300 processors. - -config CPU_BMIPS4350 - bool "BMIPS4350" - depends on SYS_HAS_CPU_BMIPS4350 - select CPU_BMIPS - select SYS_SUPPORTS_SMP - select SYS_SUPPORTS_HOTPLUG_CPU - help - Broadcom BMIPS4350 ("VIPER") processors. - -config CPU_BMIPS4380 - bool "BMIPS4380" - depends on SYS_HAS_CPU_BMIPS4380 - select CPU_BMIPS - select SYS_SUPPORTS_SMP - select SYS_SUPPORTS_HOTPLUG_CPU - help - Broadcom BMIPS4380 processors. - -config CPU_BMIPS5000 - bool "BMIPS5000" - depends on SYS_HAS_CPU_BMIPS5000 - select CPU_BMIPS +config CPU_BMIPS + bool "Broadcom BMIPS" + depends on SYS_HAS_CPU_BMIPS + select CPU_MIPS32 + select CPU_BMIPS32_3300 if SYS_HAS_CPU_BMIPS32_3300 + select CPU_BMIPS4350 if SYS_HAS_CPU_BMIPS4350 + select CPU_BMIPS4380 if SYS_HAS_CPU_BMIPS4380 + select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000 + select CPU_SUPPORTS_32BIT_KERNEL + select DMA_NONCOHERENT + select IRQ_CPU + select SWAP_IO_SPACE + select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM - select MIPS_CPU_SCACHE - select SYS_SUPPORTS_SMP - select SYS_SUPPORTS_HOTPLUG_CPU + select CPU_HAS_PREFETCH help - Broadcom BMIPS5000 processors. + Support for BMIPS32/3300/4350/4380 and BMIPS5000 processors. config CPU_XLR bool "Netlogic XLR SoC" @@ -1498,14 +1503,25 @@ config CPU_LOONGSON1 select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM -config CPU_BMIPS +config CPU_BMIPS32_3300 + select SMP_UP if SMP bool - select CPU_MIPS32 - select CPU_SUPPORTS_32BIT_KERNEL - select DMA_NONCOHERENT - select IRQ_CPU - select SWAP_IO_SPACE - select WEAK_ORDERING + +config CPU_BMIPS4350 + bool + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU + +config CPU_BMIPS4380 + bool + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU + +config CPU_BMIPS5000 + bool + select MIPS_CPU_SCACHE + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU config SYS_HAS_CPU_LOONGSON2E bool @@ -1579,17 +1595,24 @@ config SYS_HAS_CPU_SB1 config SYS_HAS_CPU_CAVIUM_OCTEON bool -config SYS_HAS_CPU_BMIPS3300 +config SYS_HAS_CPU_BMIPS + bool + +config SYS_HAS_CPU_BMIPS32_3300 bool + select SYS_HAS_CPU_BMIPS config SYS_HAS_CPU_BMIPS4350 bool + select SYS_HAS_CPU_BMIPS config SYS_HAS_CPU_BMIPS4380 bool + select SYS_HAS_CPU_BMIPS config SYS_HAS_CPU_BMIPS5000 bool + select SYS_HAS_CPU_BMIPS config SYS_HAS_CPU_XLR bool @@ -1797,6 +1820,7 @@ config IP22_CPU_SCACHE config MIPS_CPU_SCACHE bool select BOARD_SCACHE + select MIPS_L1_CACHE_SHIFT_6 config R5000_CPU_SCACHE bool @@ -1833,59 +1857,48 @@ choice prompt "MIPS MT options" config MIPS_MT_DISABLED - bool "Disable multithreading support." + bool "Disable multithreading support" help - Use this option if your workload can't take advantage of - MIPS hardware multithreading support. On systems that don't have - the option of an MT-enabled processor this option will be the only - option in this menu. + Use this option if your platform does not support the MT ASE + which is hardware multithreading support. On systems without + an MT-enabled processor, this will be the only option that is + available in this menu. config MIPS_MT_SMP bool "Use 1 TC on each available VPE for SMP" depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI + select SYNC_R4K select MIPS_MT select SMP - select SYS_SUPPORTS_SCHED_SMT if SMP - select SYS_SUPPORTS_SMP select SMP_UP + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_SCHED_SMT select MIPS_PERF_SHARED_TC_COUNTERS help - This is a kernel model which is known a VSMP but lately has been - marketesed into SMVP. - Virtual SMP uses the processor's VPEs to implement virtual - processors. In currently available configuration of the 34K processor - this allows for a dual processor. Both processors will share the same - primary caches; each will obtain the half of the TLB for it's own - exclusive use. For a layman this model can be described as similar to - what Intel calls Hyperthreading. - - For further information see http://www.linux-mips.org/wiki/34K#VSMP + This is a kernel model which is known as SMVP. This is supported + on cores with the MT ASE and uses the available VPEs to implement + virtual processors which supports SMP. This is equivalent to the + Intel Hyperthreading feature. For further information go to + <http://www.imgtec.com/mips/mips-multithreading.asp>. config MIPS_MT_SMTC - bool "SMTC: Use all TCs on all VPEs for SMP" + bool "Use all TCs on all VPEs for SMP (DEPRECATED)" depends on CPU_MIPS32_R2 - #depends on CPU_MIPS64_R2 # once there is hardware ... depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI select MIPS_MT - select NR_CPUS_DEFAULT_8 select SMP - select SYS_SUPPORTS_SMP select SMP_UP + select SYS_SUPPORTS_SMP + select NR_CPUS_DEFAULT_8 help - This is a kernel model which is known a SMTC or lately has been - marketesed into SMVP. - is presenting the available TC's of the core as processors to Linux. - On currently available 34K processors this means a Linux system will - see up to 5 processors. The implementation of the SMTC kernel differs - significantly from VSMP and cannot efficiently coexist in the same - kernel binary so the choice between VSMP and SMTC is a compile time - decision. - - For further information see http://www.linux-mips.org/wiki/34K#SMTC + This is a kernel model which is known as SMTC. This is + supported on cores with the MT ASE and presents all TCs + available on all VPEs to support SMP. For further + information see <http://www.linux-mips.org/wiki/34K#SMTC>. endchoice @@ -1922,6 +1935,16 @@ config MIPS_VPE_LOADER Includes a loader for loading an elf relocatable object onto another VPE and running it. +config MIPS_VPE_LOADER_CMP + bool + default "y" + depends on MIPS_VPE_LOADER && MIPS_CMP + +config MIPS_VPE_LOADER_MT + bool + default "y" + depends on MIPS_VPE_LOADER && !MIPS_CMP + config MIPS_MT_SMTC_IM_BACKSTOP bool "Use per-TC register bits as backstop for inhibited IM bits" depends on MIPS_MT_SMTC @@ -1955,24 +1978,29 @@ config MIPS_VPE_LOADER_TOM you to ensure the amount you put in the option and the space your program requires is less or equal to the amount physically present. -# this should possibly be in drivers/char, but it is rather cpu related. Hmmm config MIPS_VPE_APSP_API bool "Enable support for AP/SP API (RTLX)" depends on MIPS_VPE_LOADER help +config MIPS_VPE_APSP_API_CMP + bool + default "y" + depends on MIPS_VPE_APSP_API && MIPS_CMP + +config MIPS_VPE_APSP_API_MT + bool + default "y" + depends on MIPS_VPE_APSP_API && !MIPS_CMP + config MIPS_CMP - bool "MIPS CMP framework support" - depends on SYS_SUPPORTS_MIPS_CMP - select SMP + bool "MIPS CMP support" + depends on SYS_SUPPORTS_MIPS_CMP && MIPS_MT_SMP select SYNC_R4K - select SYS_SUPPORTS_SMP - select SYS_SUPPORTS_SCHED_SMT if SMP select WEAK_ORDERING default n help - This is a placeholder option for the GCMP work. It will need to - be handled differently... + Enable Coherency Manager processor (CMP) support. config SB1_PASS_1_WORKAROUNDS bool @@ -2324,6 +2352,23 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config MIPS_O32_FP64_SUPPORT + bool "Support for O32 binaries using 64-bit FP" + depends on 32BIT || MIPS32_O32 + default y + help + When this is enabled, the kernel will support use of 64-bit floating + point registers with binaries using the O32 ABI along with the + EF_MIPS_FP64 ELF header flag (typically built with -mfp64). On + 32-bit MIPS systems this support is at the cost of increasing the + size and complexity of the compiled FPU emulator. Thus if you are + running a MIPS32 system and know that none of your userland binaries + will require 64-bit floating point, you may wish to reduce the size + of your kernel & potentially improve FP emulation performance by + saying N here. + + If unsure, say Y. + config USE_OF bool select OF diff --git a/arch/mips/Makefile b/arch/mips/Makefile index efe50787cd89..9b8556de9993 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -114,7 +114,7 @@ cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*e cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le)) cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,-msmartmips) -cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips -mno-jals) +cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips) cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \ -fno-omit-frame-pointer diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c index 0c7fce2a3c12..bdb28dee8fdd 100644 --- a/arch/mips/alchemy/common/power.c +++ b/arch/mips/alchemy/common/power.c @@ -29,7 +29,6 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/init.h> #include <linux/pm.h> #include <linux/sysctl.h> #include <linux/jiffies.h> diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c index 22c93213b233..1dc6c3b37f91 100644 --- a/arch/mips/ar7/time.c +++ b/arch/mips/ar7/time.c @@ -18,7 +18,6 @@ * Setting up the clock on the MIPS boards. */ -#include <linux/init.h> #include <linux/time.h> #include <linux/err.h> #include <linux/clk.h> diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h index 648d2dafbc56..a3120714f0b7 100644 --- a/arch/mips/ath79/common.h +++ b/arch/mips/ath79/common.h @@ -15,7 +15,6 @@ #define __ATH79_COMMON_H #include <linux/types.h> -#include <linux/init.h> #define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) #define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index 2b8b118398c4..09cb6f7aa3db 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig @@ -2,6 +2,7 @@ if BCM47XX config BCM47XX_SSB bool "SSB Support for Broadcom BCM47XX" + select SYS_HAS_CPU_BMIPS32_3300 select SSB select SSB_DRIVER_MIPS select SSB_DRIVER_EXTIF @@ -11,6 +12,7 @@ config BCM47XX_SSB select SSB_PCICORE_HOSTMODE if PCI select SSB_DRIVER_GPIO select GPIOLIB + select LEDS_GPIO_REGISTER default y help Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support. @@ -20,6 +22,7 @@ config BCM47XX_SSB config BCM47XX_BCMA bool "BCMA Support for Broadcom BCM47XX" select SYS_HAS_CPU_MIPS32_R2 + select CPU_MIPSR2_IRQ_VI select BCMA select BCMA_HOST_SOC select BCMA_DRIVER_MIPS @@ -27,6 +30,7 @@ config BCM47XX_BCMA select BCMA_DRIVER_PCI_HOSTMODE if PCI select BCMA_DRIVER_GPIO select GPIOLIB + select LEDS_GPIO_REGISTER default y help Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index c52daf9b05c6..4688b6a6211b 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile @@ -4,5 +4,4 @@ # obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o -obj-y += board.o -obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o +obj-y += board.o buttons.o leds.o diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h new file mode 100644 index 000000000000..5c94acebf76a --- /dev/null +++ b/arch/mips/bcm47xx/bcm47xx_private.h @@ -0,0 +1,12 @@ +#ifndef LINUX_BCM47XX_PRIVATE_H_ +#define LINUX_BCM47XX_PRIVATE_H_ + +#include <linux/kernel.h> + +/* buttons.c */ +int __init bcm47xx_buttons_register(void); + +/* leds.c */ +void __init bcm47xx_leds_register(void); + +#endif diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c index f3f6bfe68a2a..6d612e2b949b 100644 --- a/arch/mips/bcm47xx/board.c +++ b/arch/mips/bcm47xx/board.c @@ -36,26 +36,32 @@ static const struct bcm47xx_board_type_list1 bcm47xx_board_list_model_name[] __initconst = { {{BCM47XX_BOARD_DLINK_DIR130, "D-Link DIR-130"}, "DIR-130"}, {{BCM47XX_BOARD_DLINK_DIR330, "D-Link DIR-330"}, "DIR-330"}, - { {0}, 0}, + { {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}, 0}, + { {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}, 0}, + { {0}, NULL}, }; /* hardware_version */ static const struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = { + {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"}, + {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"}, + {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"}, + {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"}, + {{BCM47XX_BOARD_ASUS_RTN12D1, "Asus RT-N12D1"}, "RTN12D1"}, + {{BCM47XX_BOARD_ASUS_RTN12HP, "Asus RT-N12HP"}, "RTN12HP"}, {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16-"}, {{BCM47XX_BOARD_ASUS_WL320GE, "Asus WL320GE"}, "WL320G-"}, {{BCM47XX_BOARD_ASUS_WL330GE, "Asus WL330GE"}, "WL330GE-"}, @@ -66,7 +72,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initcons {{BCM47XX_BOARD_ASUS_WL520GC, "Asus WL520GC"}, "WL520GC-"}, {{BCM47XX_BOARD_ASUS_WL520GU, "Asus WL520GU"}, "WL520GU-"}, {{BCM47XX_BOARD_BELKIN_F7D4301, "Belkin F7D4301"}, "F7D4301"}, - { {0}, 0}, + { {0}, NULL}, }; /* productid */ @@ -75,19 +81,13 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = { {{BCM47XX_BOARD_ASUS_RTAC66U, "Asus RT-AC66U"}, "RT-AC66U"}, {{BCM47XX_BOARD_ASUS_RTN10, "Asus RT-N10"}, "RT-N10"}, {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RT-N10D"}, - {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RT-N10U"}, - {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"}, - {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RT-N12B1"}, - {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RT-N12C1"}, - {{BCM47XX_BOARD_ASUS_RTN12D1, "Asus RT-N12D1"}, "RT-N12D1"}, - {{BCM47XX_BOARD_ASUS_RTN12HP, "Asus RT-N12HP"}, "RT-N12HP"}, {{BCM47XX_BOARD_ASUS_RTN15U, "Asus RT-N15U"}, "RT-N15U"}, {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16"}, {{BCM47XX_BOARD_ASUS_RTN53, "Asus RT-N53"}, "RT-N53"}, {{BCM47XX_BOARD_ASUS_RTN66U, "Asus RT-N66U"}, "RT-N66U"}, {{BCM47XX_BOARD_ASUS_WL300G, "Asus WL300G"}, "WL300g"}, {{BCM47XX_BOARD_ASUS_WLHDD, "Asus WLHDD"}, "WLHDD"}, - { {0}, 0}, + { {0}, NULL}, }; /* ModelId */ @@ -97,7 +97,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = { {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"}, {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"}, {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"}, - { {0}, 0}, + { {0}, NULL}, }; /* melco_id or buf1falo_id */ @@ -112,7 +112,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_melco_id[] __initconst = { {{BCM47XX_BOARD_BUFFALO_WZR_G300N, "Buffalo WZR-G300N"}, "31120"}, {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54, "Buffalo WZR-RS-G54"}, "30083"}, {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP, "Buffalo WZR-RS-G54HP"}, "30103"}, - { {0}, 0}, + { {0}, NULL}, }; /* boot_hw_model, boot_hw_ver */ @@ -143,7 +143,7 @@ struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = { {{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"}, {{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"}, {{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"}, - { {0}, 0}, + { {0}, NULL}, }; /* board_id */ @@ -165,7 +165,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = { {{BCM47XX_BOARD_NETGEAR_WNR3500V2, "Netgear WNR3500 V2"}, "U12H127T00_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNR3500V2VC, "Netgear WNR3500 V2vc"}, "U12H127T70_NETGEAR"}, {{BCM47XX_BOARD_NETGEAR_WNR834BV2, "Netgear WNR834B V2"}, "U12H081T00_NETGEAR"}, - { {0}, 0}, + { {0}, NULL}, }; /* boardtype, boardnum, boardrev */ @@ -174,7 +174,9 @@ struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = { {{BCM47XX_BOARD_HUAWEI_E970, "Huawei E970"}, "0x048e", "0x5347", "0x11"}, {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"}, {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"}, - { {0}, 0}, + {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"}, + {{BCM47XX_BOARD_LINKSYS_WRT54GSV1, "Linksys WRT54GS V1"}, "0x0101", "42", "0x10"}, + { {0}, NULL}, }; static const diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c new file mode 100644 index 000000000000..872c62e93e0e --- /dev/null +++ b/arch/mips/bcm47xx/buttons.c @@ -0,0 +1,531 @@ +#include "bcm47xx_private.h" + +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/interrupt.h> +#include <bcm47xx_board.h> +#include <bcm47xx.h> + +/************************************************** + * Database + **************************************************/ + +#define BCM47XX_GPIO_KEY(_gpio, _code) \ + { \ + .code = _code, \ + .gpio = _gpio, \ + .active_low = 1, \ + } + +/* Asus */ + +static const struct gpio_keys_button +bcm47xx_buttons_asus_rtn12[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(1, KEY_RESTART), + BCM47XX_GPIO_KEY(4, BTN_0), /* Router mode */ + BCM47XX_GPIO_KEY(5, BTN_1), /* Repeater mode */ + BCM47XX_GPIO_KEY(6, BTN_2), /* AP mode */ +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_rtn16[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(8, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_rtn66u[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(9, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl300g[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl320ge[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl330ge[] __initconst = { + BCM47XX_GPIO_KEY(2, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl500gd[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl500gpv1[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_RESTART), + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl500gpv2[] __initconst = { + BCM47XX_GPIO_KEY(2, KEY_RESTART), + BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl500w[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), + BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl520gc[] __initconst = { + BCM47XX_GPIO_KEY(2, KEY_RESTART), + BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl520gu[] __initconst = { + BCM47XX_GPIO_KEY(2, KEY_RESTART), + BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wl700ge[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_POWER), /* Hard disk power switch */ + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), /* EZSetup */ + BCM47XX_GPIO_KEY(6, KEY_COPY), /* Copy data from USB to internal disk */ + BCM47XX_GPIO_KEY(7, KEY_RESTART), /* Hard reset */ +}; + +static const struct gpio_keys_button +bcm47xx_buttons_asus_wlhdd[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +/* Huawei */ + +static const struct gpio_keys_button +bcm47xx_buttons_huawei_e970[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +/* Belkin */ + +static const struct gpio_keys_button +bcm47xx_buttons_belkin_f7d4301[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), + BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON), +}; + +/* Buffalo */ + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_whr2_a54g54[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_whr_g125[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */ +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_whr_g54s[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */ +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_whr_hp_g54[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode swtich */ +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_wzr_g300n[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_wzr_rs_g54[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(4, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_buffalo_wzr_rs_g54hp[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(4, KEY_RESTART), +}; + +/* Dell */ + +static const struct gpio_keys_button +bcm47xx_buttons_dell_tm2300[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_RESTART), +}; + +/* D-Link */ + +static const struct gpio_keys_button +bcm47xx_buttons_dlink_dir130[] __initconst = { + BCM47XX_GPIO_KEY(3, KEY_RESTART), + BCM47XX_GPIO_KEY(7, KEY_UNKNOWN), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_dlink_dir330[] __initconst = { + BCM47XX_GPIO_KEY(3, KEY_RESTART), + BCM47XX_GPIO_KEY(7, KEY_UNKNOWN), +}; + +/* Linksys */ + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e1000v1[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e1000v21[] __initconst = { + BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(10, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e2000v1[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(8, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e3000v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e3200v1[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_RESTART), + BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_e4200v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt150nv1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt150nv11[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt160nv1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt160nv3[] __initconst = { + BCM47XX_GPIO_KEY(5, 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), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt310nv1[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), + BCM47XX_GPIO_KEY(8, KEY_UNKNOWN), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt610nv1[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), + BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_linksys_wrt610nv2[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +/* Motorola */ + +static const struct gpio_keys_button +bcm47xx_buttons_motorola_we800g[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_motorola_wr850gp[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_motorola_wr850gv2v3[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_RESTART), +}; + +/* Netgear */ + +static const struct gpio_keys_button +bcm47xx_buttons_netgear_wndr3400v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(8, KEY_RFKILL), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_netgear_wndr3700v3[] __initconst = { + BCM47XX_GPIO_KEY(2, KEY_RFKILL), + BCM47XX_GPIO_KEY(3, KEY_RESTART), + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_netgear_wndr4500v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(5, KEY_RFKILL), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +static const struct gpio_keys_button +bcm47xx_buttons_netgear_wnr834bv2[] __initconst = { + BCM47XX_GPIO_KEY(6, KEY_RESTART), +}; + +/* SimpleTech */ + +static const struct gpio_keys_button +bcm47xx_buttons_simpletech_simpleshare[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_RESTART), +}; + +/************************************************** + * Init + **************************************************/ + +static struct gpio_keys_platform_data bcm47xx_button_pdata; + +static struct platform_device bcm47xx_buttons_gpio_keys = { + .name = "gpio-keys", + .dev = { + .platform_data = &bcm47xx_button_pdata, + } +}; + +/* Copy data from __initconst */ +static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons, + size_t nbuttons) +{ + size_t size = nbuttons * sizeof(*buttons); + + bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL); + if (!bcm47xx_button_pdata.buttons) + return -ENOMEM; + memcpy(bcm47xx_button_pdata.buttons, buttons, size); + bcm47xx_button_pdata.nbuttons = nbuttons; + + return 0; +} + +#define bcm47xx_copy_bdata(dev_buttons) \ + bcm47xx_buttons_copy(dev_buttons, ARRAY_SIZE(dev_buttons)); + +int __init bcm47xx_buttons_register(void) +{ + enum bcm47xx_board board = bcm47xx_board_get(); + int err; + + switch (board) { + case BCM47XX_BOARD_ASUS_RTN12: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn12); + break; + case BCM47XX_BOARD_ASUS_RTN16: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn16); + break; + case BCM47XX_BOARD_ASUS_RTN66U: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn66u); + break; + case BCM47XX_BOARD_ASUS_WL300G: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl300g); + break; + case BCM47XX_BOARD_ASUS_WL320GE: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl320ge); + break; + case BCM47XX_BOARD_ASUS_WL330GE: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge); + break; + case BCM47XX_BOARD_ASUS_WL500GD: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd); + break; + case BCM47XX_BOARD_ASUS_WL500GPV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv1); + break; + case BCM47XX_BOARD_ASUS_WL500GPV2: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv2); + break; + case BCM47XX_BOARD_ASUS_WL500W: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500w); + break; + case BCM47XX_BOARD_ASUS_WL520GC: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gc); + break; + case BCM47XX_BOARD_ASUS_WL520GU: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gu); + break; + case BCM47XX_BOARD_ASUS_WL700GE: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl700ge); + break; + case BCM47XX_BOARD_ASUS_WLHDD: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wlhdd); + break; + + case BCM47XX_BOARD_BELKIN_F7D4301: + err = bcm47xx_copy_bdata(bcm47xx_buttons_belkin_f7d4301); + break; + + case BCM47XX_BOARD_BUFFALO_WHR2_A54G54: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr2_a54g54); + break; + case BCM47XX_BOARD_BUFFALO_WHR_G125: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g125); + break; + case BCM47XX_BOARD_BUFFALO_WHR_G54S: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g54s); + break; + case BCM47XX_BOARD_BUFFALO_WHR_HP_G54: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_hp_g54); + break; + case BCM47XX_BOARD_BUFFALO_WZR_G300N: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_g300n); + break; + case BCM47XX_BOARD_BUFFALO_WZR_RS_G54: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54); + break; + case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP: + err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54hp); + break; + + case BCM47XX_BOARD_DELL_TM2300: + err = bcm47xx_copy_bdata(bcm47xx_buttons_dell_tm2300); + break; + + case BCM47XX_BOARD_DLINK_DIR130: + err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir130); + break; + case BCM47XX_BOARD_DLINK_DIR330: + err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir330); + break; + + case BCM47XX_BOARD_HUAWEI_E970: + err = bcm47xx_copy_bdata(bcm47xx_buttons_huawei_e970); + break; + + case BCM47XX_BOARD_LINKSYS_E1000V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v1); + break; + case BCM47XX_BOARD_LINKSYS_E1000V21: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v21); + break; + case BCM47XX_BOARD_LINKSYS_E2000V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e2000v1); + break; + case BCM47XX_BOARD_LINKSYS_E3000V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3000v1); + break; + case BCM47XX_BOARD_LINKSYS_E3200V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3200v1); + break; + case BCM47XX_BOARD_LINKSYS_E4200V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e4200v1); + break; + case BCM47XX_BOARD_LINKSYS_WRT150NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT150NV11: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv11); + break; + case BCM47XX_BOARD_LINKSYS_WRT160NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT160NV3: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv3); + break; + case BCM47XX_BOARD_LINKSYS_WRT300NV11: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300nv11); + break; + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT610NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT610NV2: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv2); + break; + + case BCM47XX_BOARD_MOTOROLA_WE800G: + err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g); + break; + case BCM47XX_BOARD_MOTOROLA_WR850GP: + err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gp); + break; + case BCM47XX_BOARD_MOTOROLA_WR850GV2V3: + err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gv2v3); + break; + + case BCM47XX_BOARD_NETGEAR_WNDR3400V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1); + break; + case BCM47XX_BOARD_NETGEAR_WNDR3700V3: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3700v3); + break; + case BCM47XX_BOARD_NETGEAR_WNDR4500V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1); + break; + case BCM47XX_BOARD_NETGEAR_WNR834BV2: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2); + break; + + case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE: + err = bcm47xx_copy_bdata(bcm47xx_buttons_simpletech_simpleshare); + break; + + default: + pr_debug("No buttons configuration found for this device\n"); + return -ENOTSUPP; + } + + if (err) + return -ENOMEM; + + err = platform_device_register(&bcm47xx_buttons_gpio_keys); + if (err) { + pr_err("Failed to register platform device: %d\n", err); + return err; + } + + return 0; +} diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c index 8cf3833b2d29..e0585b76ec19 100644 --- a/arch/mips/bcm47xx/irq.c +++ b/arch/mips/bcm47xx/irq.c @@ -25,10 +25,11 @@ #include <linux/types.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <asm/setup.h> #include <asm/irq_cpu.h> #include <bcm47xx.h> -void plat_irq_dispatch(void) +asmlinkage void plat_irq_dispatch(void) { u32 cause; @@ -50,6 +51,18 @@ void plat_irq_dispatch(void) do_IRQ(6); } +#define DEFINE_HWx_IRQDISPATCH(x) \ + static void bcm47xx_hw ## x ## _irqdispatch(void) \ + { \ + do_IRQ(x); \ + } +DEFINE_HWx_IRQDISPATCH(2) +DEFINE_HWx_IRQDISPATCH(3) +DEFINE_HWx_IRQDISPATCH(4) +DEFINE_HWx_IRQDISPATCH(5) +DEFINE_HWx_IRQDISPATCH(6) +DEFINE_HWx_IRQDISPATCH(7) + void __init arch_init_irq(void) { #ifdef CONFIG_BCM47XX_BCMA @@ -64,4 +77,14 @@ void __init arch_init_irq(void) } #endif mips_cpu_irq_init(); + + if (cpu_has_vint) { + pr_info("Setting up vectored interrupts\n"); + set_vi_handler(2, bcm47xx_hw2_irqdispatch); + set_vi_handler(3, bcm47xx_hw3_irqdispatch); + set_vi_handler(4, bcm47xx_hw4_irqdispatch); + set_vi_handler(5, bcm47xx_hw5_irqdispatch); + set_vi_handler(6, bcm47xx_hw6_irqdispatch); + set_vi_handler(7, bcm47xx_hw7_irqdispatch); + } } diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c new file mode 100644 index 000000000000..647d15527066 --- /dev/null +++ b/arch/mips/bcm47xx/leds.c @@ -0,0 +1,542 @@ +#include "bcm47xx_private.h" + +#include <linux/leds.h> +#include <bcm47xx_board.h> + +/************************************************** + * Database + **************************************************/ + +#define BCM47XX_GPIO_LED(_gpio, _color, _function, _active_low, \ + _default_state) \ + { \ + .name = "bcm47xx:" _color ":" _function, \ + .gpio = _gpio, \ + .active_low = _active_low, \ + .default_state = _default_state, \ + } + +#define BCM47XX_GPIO_LED_TRIGGER(_gpio, _color, _function, _active_low, \ + _default_trigger) \ + { \ + .name = "bcm47xx:" _color ":" _function, \ + .gpio = _gpio, \ + .active_low = _active_low, \ + .default_state = LEDS_GPIO_DEFSTATE_OFF, \ + .default_trigger = _default_trigger, \ + } + +/* Asus */ + +static const struct gpio_led +bcm47xx_leds_asus_rtn12[] __initconst = { + BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_rtn16[] __initconst = { + BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_rtn66u[] __initconst = { + BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl300g[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl320ge[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(11, "unk", "link", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl330ge[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl500gd[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl500gpv1[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl500gpv2[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl500w[] __initconst = { + BCM47XX_GPIO_LED(5, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl520gc[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl520gu[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(1, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_asus_wl700ge[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), /* Labeled "READY" (there is no "power" LED). Originally ON, flashing on USB activity. */ +}; + +static const struct gpio_led +bcm47xx_leds_asus_wlhdd[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(2, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Belkin */ + +static const struct gpio_led +bcm47xx_leds_belkin_f7d4301[] __initconst = { + BCM47XX_GPIO_LED(10, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(11, "amber", "power", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(12, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(13, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(14, "unk", "usb0", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(15, "unk", "usb1", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Buffalo */ + +static const struct gpio_led +bcm47xx_leds_buffalo_whr2_a54g54[] __initconst = { + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_whr_g125[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_whr_g54s[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_whr_hp_g54[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "unk", "internal", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_wzr_g300n[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "bridge", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_wzr_rs_g54[] __initconst = { + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "vpn", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_buffalo_wzr_rs_g54hp[] __initconst = { + BCM47XX_GPIO_LED(6, "unk", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "vpn", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Dell */ + +static const struct gpio_led +bcm47xx_leds_dell_tm2300[] __initconst = { + BCM47XX_GPIO_LED(6, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +/* D-Link */ + +static const struct gpio_led +bcm47xx_leds_dlink_dir130[] __initconst = { + BCM47XX_GPIO_LED_TRIGGER(0, "green", "status", 1, "timer"), /* Originally blinking when device is ready, separated from "power" LED */ + BCM47XX_GPIO_LED(6, "blue", "unk", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_dlink_dir330[] __initconst = { + BCM47XX_GPIO_LED_TRIGGER(0, "green", "status", 1, "timer"), /* Originally blinking when device is ready, separated from "power" LED */ + BCM47XX_GPIO_LED(4, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "blue", "unk", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Huawei */ + +static const struct gpio_led +bcm47xx_leds_huawei_e970[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Linksys */ + +static const struct gpio_led +bcm47xx_leds_linksys_e1000v1[] __initconst = { + BCM47XX_GPIO_LED(0, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(2, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(4, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_e1000v21[] __initconst = { + BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_e2000v1[] __initconst = { + BCM47XX_GPIO_LED(1, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(4, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_e3000v1[] __initconst = { + BCM47XX_GPIO_LED(0, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(5, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_e3200v1[] __initconst = { + BCM47XX_GPIO_LED(3, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_e4200v1[] __initconst = { + BCM47XX_GPIO_LED(5, "white", "power", 1, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_wrt150nv1[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "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_wrt150nv11[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "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_wrt160nv1[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(5, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_wrt160nv3[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(2, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(4, "blue", "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), + BCM47XX_GPIO_LED(5, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_wrt310nv1[] __initconst = { + BCM47XX_GPIO_LED(1, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(9, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_wrt610nv1[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(9, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_linksys_wrt610nv2[] __initconst = { + BCM47XX_GPIO_LED(0, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "blue", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(5, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Motorola */ + +static const struct gpio_led +bcm47xx_leds_motorola_we800g[] __initconst = { + BCM47XX_GPIO_LED(1, "amber", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "unk", "unk", 1, LEDS_GPIO_DEFSTATE_OFF), /* There are only 3 LEDs: Power, Wireless and Device (ethernet) */ + BCM47XX_GPIO_LED(4, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON), +}; + +static const struct gpio_led +bcm47xx_leds_motorola_wr850gp[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(6, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_motorola_wr850gv2v3[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "diag", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* Netgear */ + +static const struct gpio_led +bcm47xx_leds_netgear_wndr3400v1[] __initconst = { + BCM47XX_GPIO_LED(2, "green", "usb", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_netgear_wndr4500v1[] __initconst = { + BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(2, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "amber", "power", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(8, "green", "usb1", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(9, "green", "2ghz", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(11, "blue", "5ghz", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(14, "green", "usb2", 1, LEDS_GPIO_DEFSTATE_OFF), +}; + +static const struct gpio_led +bcm47xx_leds_netgear_wnr834bv2[] __initconst = { + BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(7, "unk", "connected", 0, LEDS_GPIO_DEFSTATE_OFF), +}; + +/* SimpleTech */ + +static const struct gpio_led +bcm47xx_leds_simpletech_simpleshare[] __initconst = { + BCM47XX_GPIO_LED(1, "unk", "status", 1, LEDS_GPIO_DEFSTATE_OFF), /* "Ready" LED */ +}; + +/************************************************** + * Init + **************************************************/ + +static struct gpio_led_platform_data bcm47xx_leds_pdata; + +#define bcm47xx_set_pdata(dev_leds) do { \ + bcm47xx_leds_pdata.leds = dev_leds; \ + bcm47xx_leds_pdata.num_leds = ARRAY_SIZE(dev_leds); \ +} while (0) + +void __init bcm47xx_leds_register(void) +{ + enum bcm47xx_board board = bcm47xx_board_get(); + + switch (board) { + case BCM47XX_BOARD_ASUS_RTN12: + bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12); + break; + case BCM47XX_BOARD_ASUS_RTN16: + bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16); + break; + case BCM47XX_BOARD_ASUS_RTN66U: + bcm47xx_set_pdata(bcm47xx_leds_asus_rtn66u); + break; + case BCM47XX_BOARD_ASUS_WL300G: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl300g); + break; + case BCM47XX_BOARD_ASUS_WL320GE: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl320ge); + break; + case BCM47XX_BOARD_ASUS_WL330GE: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge); + break; + case BCM47XX_BOARD_ASUS_WL500GD: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd); + break; + case BCM47XX_BOARD_ASUS_WL500GPV1: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gpv1); + break; + case BCM47XX_BOARD_ASUS_WL500GPV2: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gpv2); + break; + case BCM47XX_BOARD_ASUS_WL500W: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl500w); + break; + case BCM47XX_BOARD_ASUS_WL520GC: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl520gc); + break; + case BCM47XX_BOARD_ASUS_WL520GU: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl520gu); + break; + case BCM47XX_BOARD_ASUS_WL700GE: + bcm47xx_set_pdata(bcm47xx_leds_asus_wl700ge); + break; + case BCM47XX_BOARD_ASUS_WLHDD: + bcm47xx_set_pdata(bcm47xx_leds_asus_wlhdd); + break; + + case BCM47XX_BOARD_BELKIN_F7D4301: + bcm47xx_set_pdata(bcm47xx_leds_belkin_f7d4301); + break; + + case BCM47XX_BOARD_BUFFALO_WHR2_A54G54: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr2_a54g54); + break; + case BCM47XX_BOARD_BUFFALO_WHR_G125: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_g125); + break; + case BCM47XX_BOARD_BUFFALO_WHR_G54S: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_g54s); + break; + case BCM47XX_BOARD_BUFFALO_WHR_HP_G54: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_whr_hp_g54); + break; + case BCM47XX_BOARD_BUFFALO_WZR_G300N: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_g300n); + break; + case BCM47XX_BOARD_BUFFALO_WZR_RS_G54: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_rs_g54); + break; + case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP: + bcm47xx_set_pdata(bcm47xx_leds_buffalo_wzr_rs_g54hp); + break; + + case BCM47XX_BOARD_DELL_TM2300: + bcm47xx_set_pdata(bcm47xx_leds_dell_tm2300); + break; + + case BCM47XX_BOARD_DLINK_DIR130: + bcm47xx_set_pdata(bcm47xx_leds_dlink_dir130); + break; + case BCM47XX_BOARD_DLINK_DIR330: + bcm47xx_set_pdata(bcm47xx_leds_dlink_dir330); + break; + + case BCM47XX_BOARD_HUAWEI_E970: + bcm47xx_set_pdata(bcm47xx_leds_huawei_e970); + break; + + case BCM47XX_BOARD_LINKSYS_E1000V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e1000v1); + break; + case BCM47XX_BOARD_LINKSYS_E1000V21: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e1000v21); + break; + case BCM47XX_BOARD_LINKSYS_E2000V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e2000v1); + break; + case BCM47XX_BOARD_LINKSYS_E3000V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e3000v1); + break; + case BCM47XX_BOARD_LINKSYS_E3200V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e3200v1); + break; + case BCM47XX_BOARD_LINKSYS_E4200V1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_e4200v1); + break; + case BCM47XX_BOARD_LINKSYS_WRT150NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt150nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT150NV11: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt150nv11); + break; + case BCM47XX_BOARD_LINKSYS_WRT160NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt160nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT160NV3: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt160nv3); + break; + case BCM47XX_BOARD_LINKSYS_WRT300NV11: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt300nv11); + break; + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT610NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1); + break; + case BCM47XX_BOARD_LINKSYS_WRT610NV2: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv2); + break; + + case BCM47XX_BOARD_MOTOROLA_WE800G: + bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g); + break; + case BCM47XX_BOARD_MOTOROLA_WR850GP: + bcm47xx_set_pdata(bcm47xx_leds_motorola_wr850gp); + break; + case BCM47XX_BOARD_MOTOROLA_WR850GV2V3: + bcm47xx_set_pdata(bcm47xx_leds_motorola_wr850gv2v3); + break; + + case BCM47XX_BOARD_NETGEAR_WNDR3400V1: + bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr3400v1); + break; + case BCM47XX_BOARD_NETGEAR_WNDR4500V1: + bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1); + break; + case BCM47XX_BOARD_NETGEAR_WNR834BV2: + bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2); + break; + + case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE: + bcm47xx_set_pdata(bcm47xx_leds_simpletech_simpleshare); + break; + + default: + pr_debug("No LEDs configuration found for this device\n"); + return; + } + + gpio_led_register_device(-1, &bcm47xx_leds_pdata); +} diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index b4c585b1c62e..6decb27cf48b 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -11,7 +11,6 @@ * option) any later version. */ -#include <linux/init.h> #include <linux/types.h> #include <linux/module.h> #include <linux/ssb/ssb.h> @@ -22,11 +21,11 @@ #include <asm/mach-bcm47xx/bcm47xx.h> static char nvram_buf[NVRAM_SPACE]; +static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; static u32 find_nvram_size(u32 end) { struct nvram_header *header; - u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; int i; for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 5cba318bc1cd..0af808dfd1ca 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -28,126 +28,27 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/spinlock.h> +#include <linux/ssb/ssb_driver_chipcommon.h> +#include <linux/ssb/ssb_regs.h> #include <linux/smp.h> #include <asm/bootinfo.h> -#include <asm/fw/cfe/cfe_api.h> -#include <asm/fw/cfe/cfe_error.h> #include <bcm47xx.h> #include <bcm47xx_board.h> -static int cfe_cons_handle; -static u16 get_chip_id(void) -{ - switch (bcm47xx_bus_type) { -#ifdef CONFIG_BCM47XX_SSB - case BCM47XX_BUS_TYPE_SSB: - return bcm47xx_bus.ssb.chip_id; -#endif -#ifdef CONFIG_BCM47XX_BCMA - case BCM47XX_BUS_TYPE_BCMA: - return bcm47xx_bus.bcma.bus.chipinfo.id; -#endif - } - return 0; -} +static char bcm47xx_system_type[20] = "Broadcom BCM47XX"; const char *get_system_type(void) { - static char buf[50]; - u16 chip_id = get_chip_id(); - - snprintf(buf, sizeof(buf), - (chip_id > 0x9999) ? "Broadcom BCM%d (%s)" : - "Broadcom BCM%04X (%s)", - chip_id, bcm47xx_board_get_name()); - - return buf; -} - -void prom_putchar(char c) -{ - while (cfe_write(cfe_cons_handle, &c, 1) == 0) - ; + return bcm47xx_system_type; } -static __init void prom_init_cfe(void) +__init void bcm47xx_set_system_type(u16 chip_id) { - uint32_t cfe_ept; - uint32_t cfe_handle; - uint32_t cfe_eptseal; - int argc = fw_arg0; - char **envp = (char **) fw_arg2; - int *prom_vec = (int *) fw_arg3; - - /* - * Check if a loader was used; if NOT, the 4 arguments are - * what CFE gives us (handle, 0, EPT and EPTSEAL) - */ - if (argc < 0) { - cfe_handle = (uint32_t)argc; - cfe_ept = (uint32_t)envp; - cfe_eptseal = (uint32_t)prom_vec; - } else { - if ((int)prom_vec < 0) { - /* - * Old loader; all it gives us is the handle, - * so use the "known" entrypoint and assume - * the seal. - */ - cfe_handle = (uint32_t)prom_vec; - cfe_ept = 0xBFC00500; - cfe_eptseal = CFE_EPTSEAL; - } else { - /* - * Newer loaders bundle the handle/ept/eptseal - * Note: prom_vec is in the loader's useg - * which is still alive in the TLB. - */ - cfe_handle = prom_vec[0]; - cfe_ept = prom_vec[2]; - cfe_eptseal = prom_vec[3]; - } - } - - if (cfe_eptseal != CFE_EPTSEAL) { - /* too early for panic to do any good */ - printk(KERN_ERR "CFE's entrypoint seal doesn't match."); - while (1) ; - } - - cfe_init(cfe_handle, cfe_ept); -} - -static __init void prom_init_console(void) -{ - /* Initialize CFE console */ - cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); -} - -static __init void prom_init_cmdline(void) -{ - static char buf[COMMAND_LINE_SIZE] __initdata; - - /* Get the kernel command line from CFE */ - if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) { - buf[COMMAND_LINE_SIZE - 1] = 0; - strcpy(arcs_cmdline, buf); - } - - /* Force a console handover by adding a console= argument if needed, - * as CFE is not available anymore later in the boot process. */ - if ((strstr(arcs_cmdline, "console=")) == NULL) { - /* Try to read the default serial port used by CFE */ - if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0) - || (strncmp("uart", buf, 4))) - /* Default to uart0 */ - strcpy(buf, "uart0"); - - /* Compute the new command line */ - snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200", - arcs_cmdline, buf[4]); - } + snprintf(bcm47xx_system_type, sizeof(bcm47xx_system_type), + (chip_id > 0x9999) ? "Broadcom BCM%d" : + "Broadcom BCM%04X", + chip_id); } static __init void prom_init_mem(void) @@ -195,12 +96,16 @@ static __init void prom_init_mem(void) add_memory_region(0, mem, BOOT_MEM_RAM); } +/* + * This is the first serial on the chip common core, it is at this position + * for sb (ssb) and ai (bcma) bus. + */ +#define BCM47XX_SERIAL_ADDR (SSB_ENUM_BASE + SSB_CHIPCO_UART0_DATA) + void __init prom_init(void) { - prom_init_cfe(); - prom_init_console(); - prom_init_cmdline(); prom_init_mem(); + setup_8250_early_printk_port(CKSEG1ADDR(BCM47XX_SERIAL_ADDR), 0, 0); } void __init prom_free_prom_memory(void) diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index b8ef965705cf..2f5bbd68e9a0 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c @@ -31,7 +31,8 @@ static int __init uart8250_init_ssb(void) memset(&uart8250_data, 0, sizeof(uart8250_data)); - for (i = 0; i < mcore->nr_serial_ports; i++) { + for (i = 0; i < mcore->nr_serial_ports && + i < ARRAY_SIZE(uart8250_data) - 1; i++) { struct plat_serial8250_port *p = &(uart8250_data[i]); struct ssb_serial_port *ssb_port = &(mcore->serial_ports[i]); @@ -55,7 +56,8 @@ static int __init uart8250_init_bcma(void) memset(&uart8250_data, 0, sizeof(uart8250_data)); - for (i = 0; i < cc->nr_serial_ports; i++) { + for (i = 0; i < cc->nr_serial_ports && + i < ARRAY_SIZE(uart8250_data) - 1; i++) { struct plat_serial8250_port *p = &(uart8250_data[i]); struct bcma_serial_port *bcma_port; bcma_port = &(cc->serial_ports[i]); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 9057728ac56b..025be218ea15 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -26,6 +26,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "bcm47xx_private.h" + #include <linux/export.h> #include <linux/types.h> #include <linux/ethtool.h> @@ -35,6 +37,8 @@ #include <linux/ssb/ssb_embedded.h> #include <linux/bcma/bcma_soc.h> #include <asm/bootinfo.h> +#include <asm/idle.h> +#include <asm/prom.h> #include <asm/reboot.h> #include <asm/time.h> #include <bcm47xx.h> @@ -213,12 +217,14 @@ void __init plat_mem_setup(void) #ifdef CONFIG_BCM47XX_BCMA bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; bcm47xx_register_bcma(); + bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); #endif } else { printk(KERN_INFO "bcm47xx: using ssb bus\n"); #ifdef CONFIG_BCM47XX_SSB bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; bcm47xx_register_ssb(); + bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id); #endif } @@ -226,8 +232,34 @@ void __init plat_mem_setup(void) _machine_halt = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt; bcm47xx_board_detect(); + mips_set_machine_name(bcm47xx_board_get_name()); } +static int __init bcm47xx_cpu_fixes(void) +{ + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + /* Nothing to do */ + break; +#endif +#ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + /* The BCM4706 has a problem with the CPU wait instruction. + * When r4k_wait or r4k_wait_irqoff is used will just hang and + * not return from a msleep(). Removing the cpu_wait + * functionality is a workaround for this problem. The BCM4716 + * does not have this problem. + */ + if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) + cpu_wait = NULL; + break; +#endif + } + return 0; +} +arch_initcall(bcm47xx_cpu_fixes); + static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = { .link = 1, .speed = SPEED_100, @@ -248,6 +280,9 @@ static int __init bcm47xx_register_bus_complete(void) break; #endif } + bcm47xx_buttons_register(); + bcm47xx_leds_register(); + fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status); return 0; } diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index ad03c931b905..a8b5408dd349 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c @@ -135,7 +135,7 @@ static void nvram_read_leddc(const char *prefix, const char *name, } static void nvram_read_macaddr(const char *prefix, const char *name, - u8 (*val)[6], bool fallback) + u8 val[6], bool fallback) { char buf[100]; int err; @@ -144,11 +144,11 @@ static void nvram_read_macaddr(const char *prefix, const char *name, if (err < 0) return; - bcm47xx_nvram_parse_macaddr(buf, *val); + bcm47xx_nvram_parse_macaddr(buf, val); } static void nvram_read_alpha2(const char *prefix, const char *name, - char (*val)[2], bool fallback) + char val[2], bool fallback) { char buf[10]; int err; @@ -162,7 +162,7 @@ static void nvram_read_alpha2(const char *prefix, const char *name, pr_warn("alpha2 is too long %s\n", buf); return; } - memcpy(val, buf, sizeof(val)); + memcpy(val, buf, 2); } static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, @@ -180,7 +180,7 @@ static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, fallback); nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0, fallback); - nvram_read_alpha2(prefix, "ccode", &sprom->alpha2, fallback); + nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback); } static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom, @@ -633,20 +633,20 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom, static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac, fallback); + nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback); nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0, fallback); nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0, fallback); - nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac, fallback); + nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback); nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0, fallback); nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0, fallback); - nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac, fallback); - nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac, fallback); + nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback); + nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback); } static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c deleted file mode 100644 index c63a4c287b5c..000000000000 --- a/arch/mips/bcm47xx/wgt634u.c +++ /dev/null @@ -1,174 +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) 2007 Aurelien Jarno <aurelien@aurel32.net> - */ - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/leds.h> -#include <linux/mtd/physmap.h> -#include <linux/ssb/ssb.h> -#include <linux/ssb/ssb_embedded.h> -#include <linux/interrupt.h> -#include <linux/reboot.h> -#include <linux/gpio.h> -#include <asm/mach-bcm47xx/bcm47xx.h> - -/* GPIO definitions for the WGT634U */ -#define WGT634U_GPIO_LED 3 -#define WGT634U_GPIO_RESET 2 -#define WGT634U_GPIO_TP1 7 -#define WGT634U_GPIO_TP2 6 -#define WGT634U_GPIO_TP3 5 -#define WGT634U_GPIO_TP4 4 -#define WGT634U_GPIO_TP5 1 - -static struct gpio_led wgt634u_leds[] = { - { - .name = "power", - .gpio = WGT634U_GPIO_LED, - .active_low = 1, - .default_trigger = "heartbeat", - }, -}; - -static struct gpio_led_platform_data wgt634u_led_data = { - .num_leds = ARRAY_SIZE(wgt634u_leds), - .leds = wgt634u_leds, -}; - -static struct platform_device wgt634u_gpio_leds = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &wgt634u_led_data, - } -}; - - -/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U - firmware. */ -static struct mtd_partition wgt634u_partitions[] = { - { - .name = "cfe", - .offset = 0, - .size = 0x60000, /* 384k */ - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "config", - .offset = 0x60000, - .size = 0x20000 /* 128k */ - }, - { - .name = "linux", - .offset = 0x80000, - .size = 0x140000 /* 1280k */ - }, - { - .name = "jffs", - .offset = 0x1c0000, - .size = 0x620000 /* 6272k */ - }, - { - .name = "nvram", - .offset = 0x7e0000, - .size = 0x20000 /* 128k */ - }, -}; - -static struct physmap_flash_data wgt634u_flash_data = { - .parts = wgt634u_partitions, - .nr_parts = ARRAY_SIZE(wgt634u_partitions) -}; - -static struct resource wgt634u_flash_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device wgt634u_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { .platform_data = &wgt634u_flash_data, }, - .resource = &wgt634u_flash_resource, - .num_resources = 1, -}; - -/* Platform devices */ -static struct platform_device *wgt634u_devices[] __initdata = { - &wgt634u_flash, - &wgt634u_gpio_leds, -}; - -static irqreturn_t gpio_interrupt(int irq, void *ignored) -{ - int state; - - /* Interrupts are shared, check if the current one is - a GPIO interrupt. */ - if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco, - SSB_CHIPCO_IRQ_GPIO)) - return IRQ_NONE; - - state = gpio_get_value(WGT634U_GPIO_RESET); - - /* Interrupt are level triggered, revert the interrupt polarity - to clear the interrupt. */ - ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << WGT634U_GPIO_RESET, - state ? 1 << WGT634U_GPIO_RESET : 0); - - if (!state) { - printk(KERN_INFO "Reset button pressed"); - ctrl_alt_del(); - } - - return IRQ_HANDLED; -} - -static int __init wgt634u_init(void) -{ - /* There is no easy way to detect that we are running on a WGT634U - * machine. Use the MAC address as an heuristic. Netgear Inc. has - * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. - */ - u8 *et0mac; - - if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) - return -ENODEV; - - et0mac = bcm47xx_bus.ssb.sprom.et0mac; - - if (et0mac[0] == 0x00 && - ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || - (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { - struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; - - printk(KERN_INFO "WGT634U machine detected.\n"); - - if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET), - gpio_interrupt, IRQF_SHARED, - "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) { - gpio_direction_input(WGT634U_GPIO_RESET); - ssb_gpio_intmask(&bcm47xx_bus.ssb, - 1 << WGT634U_GPIO_RESET, - 1 << WGT634U_GPIO_RESET); - ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco, - SSB_CHIPCO_IRQ_GPIO, - SSB_CHIPCO_IRQ_GPIO); - } - - wgt634u_flash_data.width = mcore->pflash.buswidth; - wgt634u_flash_resource.start = mcore->pflash.window; - wgt634u_flash_resource.end = mcore->pflash.window - + mcore->pflash.window_size - - 1; - return platform_add_devices(wgt634u_devices, - ARRAY_SIZE(wgt634u_devices)); - } else - return -ENODEV; -} - -module_init(wgt634u_init); diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index b78306ce56c7..a057fdf111c6 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -3,33 +3,41 @@ menu "CPU support" config BCM63XX_CPU_3368 bool "support 3368 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6328 bool "support 6328 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6338 bool "support 6338 CPU" + select SYS_HAS_CPU_BMIPS32_3300 select HW_HAS_PCI config BCM63XX_CPU_6345 bool "support 6345 CPU" + select SYS_HAS_CPU_BMIPS32_3300 config BCM63XX_CPU_6348 bool "support 6348 CPU" + select SYS_HAS_CPU_BMIPS32_3300 select HW_HAS_PCI config BCM63XX_CPU_6358 bool "support 6358 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6362 bool "support 6362 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI config BCM63XX_CPU_6368 bool "support 6368 CPU" + select SYS_HAS_CPU_BMIPS4350 select HW_HAS_PCI endmenu diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index ac2807397c1c..9019f54aee69 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -1,7 +1,7 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \ setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \ - dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-wdt.o \ - dev-usb-usbd.o + dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \ + dev-wdt.o dev-usb-usbd.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 5b974eb125fc..33727e7f0c79 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -23,6 +23,7 @@ #include <bcm63xx_dev_enet.h> #include <bcm63xx_dev_dsp.h> #include <bcm63xx_dev_flash.h> +#include <bcm63xx_dev_hsspi.h> #include <bcm63xx_dev_pcmcia.h> #include <bcm63xx_dev_spi.h> #include <bcm63xx_dev_usb_usbd.h> @@ -915,6 +916,8 @@ int __init board_register_devices(void) bcm63xx_spi_register(); + bcm63xx_hsspi_register(); + bcm63xx_flash_register(); bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index 43da4ae04cc2..637565284732 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -226,6 +226,28 @@ static struct clk clk_spi = { }; /* + * HSSPI clock + */ +static void hsspi_set(struct clk *clk, int enable) +{ + u32 mask; + + if (BCMCPU_IS_6328()) + mask = CKCTL_6328_HSSPI_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_HSSPI_EN; + else + return; + + bcm_hwclock_set(mask, enable); +} + +static struct clk clk_hsspi = { + .set = hsspi_set, +}; + + +/* * XTM clock */ static void xtm_set(struct clk *clk, int enable) @@ -346,6 +368,8 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_usbd; if (!strcmp(id, "spi")) return &clk_spi; + if (!strcmp(id, "hsspi")) + return &clk_hsspi; if (!strcmp(id, "xtm")) return &clk_xtm; if (!strcmp(id, "periph")) @@ -366,3 +390,21 @@ void clk_put(struct clk *clk) } EXPORT_SYMBOL(clk_put); + +#define HSSPI_PLL_HZ_6328 133333333 +#define HSSPI_PLL_HZ_6362 400000000 + +static int __init bcm63xx_clk_init(void) +{ + switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + clk_hsspi.rate = HSSPI_PLL_HZ_6328; + break; + case BCM6362_CPU_ID: + clk_hsspi.rate = HSSPI_PLL_HZ_6362; + break; + } + + return 0; +} +arch_initcall(bcm63xx_clk_init); diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index b713cd64b087..1b1b8a89959b 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -123,7 +123,9 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { - switch (bcm63xx_get_cpu_id()) { + u16 cpu_id = bcm63xx_get_cpu_id(); + + switch (cpu_id) { case BCM3368_CPU_ID: return 300000000; @@ -249,7 +251,7 @@ static unsigned int detect_cpu_clock(void) } default: - BUG(); + panic("Failed to detect clock for CPU with id=%04X\n", cpu_id); } } diff --git a/arch/mips/bcm63xx/dev-hsspi.c b/arch/mips/bcm63xx/dev-hsspi.c new file mode 100644 index 000000000000..696abc48e3c8 --- /dev/null +++ b/arch/mips/bcm63xx/dev-hsspi.c @@ -0,0 +1,47 @@ +/* + * 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 Jonas Gorski <jonas.gorski@gmail.com> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <bcm63xx_cpu.h> +#include <bcm63xx_dev_hsspi.h> +#include <bcm63xx_regs.h> + +static struct resource spi_resources[] = { + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + .start = -1, /* filled at runtime */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bcm63xx_hsspi_device = { + .name = "bcm63xx-hsspi", + .id = 0, + .num_resources = ARRAY_SIZE(spi_resources), + .resource = spi_resources, +}; + +int __init bcm63xx_hsspi_register(void) +{ + if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362()) + return -ENODEV; + + spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI); + spi_resources[0].end = spi_resources[0].start; + spi_resources[0].end += RSET_HSSPI_SIZE - 1; + spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI); + + return platform_device_register(&bcm63xx_hsspi_device); +} diff --git a/arch/mips/bcm63xx/early_printk.c b/arch/mips/bcm63xx/early_printk.c index aa8f7f9cc7a4..6092226a6d76 100644 --- a/arch/mips/bcm63xx/early_printk.c +++ b/arch/mips/bcm63xx/early_printk.c @@ -6,9 +6,8 @@ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> */ -#include <linux/init.h> #include <bcm63xx_io.h> -#include <bcm63xx_regs.h> +#include <linux/serial_bcm63xx.h> static void wait_xfered(void) { diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 8ac4e095e68e..e1f27d653f60 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -59,14 +59,12 @@ void __init prom_init(void) /* do low level board init */ board_prom_init(); - if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) { - /* set up SMP */ - register_smp_ops(&bmips_smp_ops); - + /* set up SMP */ + if (!register_bmips_smp_ops()) { /* - * BCM6328 might not have its second CPU enabled, while BCM6358 - * needs special handling for its shared TLB, so disable SMP - * for now. + * BCM6328 might not have its second CPU enabled, while BCM3368 + * and BCM6358 need special handling for their shared TLB, so + * disable SMP for now. */ if (BCMCPU_IS_6328()) { reg = bcm_readl(BCM_6328_OTP_BASE + @@ -74,7 +72,7 @@ void __init prom_init(void) if (reg & OTP_6328_REG3_TP1_DISABLED) bmips_smp_enabled = 0; - } else if (BCMCPU_IS_6358()) { + } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { bmips_smp_enabled = 0; } diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index ca0c343c9ea5..61af6b6ab13d 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -27,10 +27,10 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ -DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS) -targets := head.o decompress.o dbg.o uart-16550.o uart-alchemy.o +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)/dbg.o +vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/dbg.o ifdef CONFIG_DEBUG_ZBOOT vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c index 134a6162e394..06c6a5bd175d 100644 --- a/arch/mips/boot/compressed/dbg.c +++ b/arch/mips/boot/compressed/dbg.c @@ -6,7 +6,6 @@ * need to implement your own putc(). */ #include <linux/compiler.h> -#include <linux/init.h> #include <linux/types.h> void __weak putc(char c) diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index a8c6fd6a4406..c00c4ddf4514 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -43,33 +43,11 @@ void error(char *x) /* activate the code for pre-boot environment */ #define STATIC static -#if defined(CONFIG_KERNEL_GZIP) || defined(CONFIG_KERNEL_XZ) || \ - defined(CONFIG_KERNEL_LZ4) -void *memcpy(void *dest, const void *src, size_t n) -{ - int i; - const char *s = src; - char *d = dest; - - for (i = 0; i < n; i++) - d[i] = s[i]; - return dest; -} -#endif #ifdef CONFIG_KERNEL_GZIP #include "../../../../lib/decompress_inflate.c" #endif #ifdef CONFIG_KERNEL_BZIP2 -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = s; - - for (i = 0; i < n; i++) - ss[i] = c; - return s; -} #include "../../../../lib/decompress_bunzip2.c" #endif diff --git a/arch/mips/boot/compressed/string.c b/arch/mips/boot/compressed/string.c new file mode 100644 index 000000000000..9de9885acd0d --- /dev/null +++ b/arch/mips/boot/compressed/string.c @@ -0,0 +1,28 @@ +/* + * arch/mips/boot/compressed/string.c + * + * Very small subset of simple string routines + */ + +#include <linux/types.h> + +void *memcpy(void *dest, const void *src, size_t n) +{ + int i; + const char *s = src; + char *d = dest; + + for (i = 0; i < n; i++) + d[i] = s[i]; + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + int i; + char *ss = s; + + for (i = 0; i < n; i++) + ss[i] = c; + return s; +} diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c index c01d343ce6ad..237494b7a21a 100644 --- a/arch/mips/boot/compressed/uart-16550.c +++ b/arch/mips/boot/compressed/uart-16550.c @@ -4,7 +4,6 @@ #include <linux/types.h> #include <linux/serial_reg.h> -#include <linux/init.h> #include <asm/addrspace.h> @@ -19,8 +18,8 @@ #endif #ifdef CONFIG_MACH_JZ4740 -#define UART0_BASE 0xB0030000 -#define PORT(offset) (UART0_BASE + (4 * offset)) +#include <asm/mach-jz4740/base.h> +#define PORT(offset) (CKSEG1ADDR(JZ4740_UART0_BASE_ADDR) + (4 * offset)) #endif #ifdef CONFIG_CPU_XLR diff --git a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c index 132bccc66a93..8241fc6aa17d 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c +++ b/arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c @@ -47,6 +47,7 @@ * state. It points to a bootmem named block. */ __cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr; +EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr); /** * Initialize the Global queue state pointer. diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c index 0a1283ce47f5..b764df64be40 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c @@ -722,3 +722,30 @@ int __cvmx_helper_board_hardware_enable(int interface) } return 0; } + +/** + * Get the clock type used for the USB block based on board type. + * Used by the USB code for auto configuration of clock type. + * + * Return USB clock type enumeration + */ +enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void) +{ + switch (cvmx_sysinfo_get()->board_type) { + case CVMX_BOARD_TYPE_BBGW_REF: + case CVMX_BOARD_TYPE_LANAI2_A: + case CVMX_BOARD_TYPE_LANAI2_U: + case CVMX_BOARD_TYPE_LANAI2_G: + case CVMX_BOARD_TYPE_NIC10E_66: + case CVMX_BOARD_TYPE_UBNT_E100: + return USB_CLOCK_TYPE_CRYSTAL_12; + case CVMX_BOARD_TYPE_NIC10E: + return USB_CLOCK_TYPE_REF_12; + default: + break; + } + /* Most boards except NIC10e use a 12MHz crystal */ + if (OCTEON_IS_MODEL(OCTEON_FAM_2)) + return USB_CLOCK_TYPE_CRYSTAL_12; + return USB_CLOCK_TYPE_REF_48; +} diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c index 65d2bc9a0bde..453d7f66459a 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-util.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-util.c @@ -251,6 +251,7 @@ int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) return 0; } +EXPORT_SYMBOL_GPL(cvmx_helper_setup_red); /** * Setup the common GMX settings that determine the number of @@ -384,6 +385,7 @@ int cvmx_helper_get_ipd_port(int interface, int port) } return -1; } +EXPORT_SYMBOL_GPL(cvmx_helper_get_ipd_port); /** * Returns the interface number for an IPD/PKO port number. @@ -408,6 +410,7 @@ int cvmx_helper_get_interface_num(int ipd_port) return -1; } +EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_num); /** * Returns the interface index number for an IPD/PKO port @@ -431,3 +434,4 @@ int cvmx_helper_get_interface_index_num(int ipd_port) return -1; } +EXPORT_SYMBOL_GPL(cvmx_helper_get_interface_index_num); diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index d63d20dfbfb0..8553ad5c72b6 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -67,7 +67,7 @@ void (*cvmx_override_pko_queue_priority) (int pko_port, void (*cvmx_override_ipd_port_setup) (int ipd_port); /* Port count per interface */ -static int interface_port_count[4] = { 0, 0, 0, 0 }; +static int interface_port_count[5]; /* Port last configured link info index by IPD/PKO port */ static cvmx_helper_link_info_t @@ -88,6 +88,7 @@ int cvmx_helper_get_number_of_interfaces(void) else return 3; } +EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces); /** * Return the number of ports on an interface. Depending on the @@ -102,6 +103,7 @@ int cvmx_helper_ports_on_interface(int interface) { return interface_port_count[interface]; } +EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface); /** * Get the operating mode of an interface. Depending on the Octeon @@ -179,6 +181,7 @@ cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) return CVMX_HELPER_INTERFACE_MODE_RGMII; } } +EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode); /** * Configure the IPD/PIP tagging and QoS options for a specific @@ -825,6 +828,7 @@ int cvmx_helper_ipd_and_packet_input_enable(void) __cvmx_helper_errata_fix_ipd_ptr_alignment(); return 0; } +EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable); /** * Initialize the PIP, IPD, and PKO hardware to support @@ -903,6 +907,7 @@ int cvmx_helper_initialize_packet_io_global(void) #endif return result; } +EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global); /** * Does core local initialization for packet io @@ -947,6 +952,7 @@ cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) */ return port_link_info[ipd_port]; } +EXPORT_SYMBOL_GPL(cvmx_helper_link_autoconf); /** * Return the link state of an IPD/PKO port as returned by @@ -1005,6 +1011,7 @@ cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) } return result; } +EXPORT_SYMBOL_GPL(cvmx_helper_link_get); /** * Configure an IPD/PKO port for the specified link state. This @@ -1060,6 +1067,7 @@ int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) port_link_info[ipd_port].u64 = link_info.u64; return result; } +EXPORT_SYMBOL_GPL(cvmx_helper_link_set); /** * Configure a port for internal and/or external loopback. Internal loopback diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c index f2c877541597..008b881cdf64 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-pko.c +++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c @@ -140,7 +140,7 @@ void cvmx_pko_disable(void) pko_reg_flags.s.ena_pko = 0; cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64); } - +EXPORT_SYMBOL_GPL(cvmx_pko_disable); /** * Reset the packet output. @@ -182,6 +182,7 @@ void cvmx_pko_shutdown(void) } __cvmx_pko_reset(); } +EXPORT_SYMBOL_GPL(cvmx_pko_shutdown); /** * Configure a output port and the associated queues for use. diff --git a/arch/mips/cavium-octeon/executive/cvmx-spi.c b/arch/mips/cavium-octeon/executive/cvmx-spi.c index ef5198d13a0e..459e3b1eb61f 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-spi.c +++ b/arch/mips/cavium-octeon/executive/cvmx-spi.c @@ -177,6 +177,7 @@ int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout) return res; } +EXPORT_SYMBOL_GPL(cvmx_spi_restart_interface); /** * Callback to perform SPI4 reset diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 1830874ff1e2..6df0f4d8f197 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -171,6 +171,7 @@ device_initcall(octeon_ohci_device_init); static struct of_device_id __initdata octeon_ids[] = { { .compatible = "simple-bus", }, { .compatible = "cavium,octeon-6335-uctl", }, + { .compatible = "cavium,octeon-5750-usbn", }, { .compatible = "cavium,octeon-3860-bootbus", }, { .compatible = "cavium,mdio-mux", }, { .compatible = "gpio-leds", }, @@ -336,14 +337,14 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) int p; int count = 0; - if (cvmx_helper_interface_enumerate(idx) == 0) - count = cvmx_helper_ports_on_interface(idx); - snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx); iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer); if (iface < 0) return; + if (cvmx_helper_interface_enumerate(idx) == 0) + count = cvmx_helper_ports_on_interface(idx); + for (p = 0; p < 16; p++) octeon_fdt_pip_port(iface, idx, p, count - 1, pmac); } @@ -682,6 +683,37 @@ end_led: } } + /* DWC2 USB */ + alias_prop = fdt_getprop(initial_boot_params, aliases, + "usbn", NULL); + if (alias_prop) { + int usbn = fdt_path_offset(initial_boot_params, alias_prop); + + if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 || + !octeon_has_feature(OCTEON_FEATURE_USB))) { + pr_debug("Deleting usbn\n"); + fdt_nop_node(initial_boot_params, usbn); + fdt_nop_property(initial_boot_params, aliases, "usbn"); + } else { + __be32 new_f[1]; + enum cvmx_helper_board_usb_clock_types c; + c = __cvmx_helper_board_usb_get_clock_type(); + switch (c) { + case USB_CLOCK_TYPE_REF_48: + new_f[0] = cpu_to_be32(48000000); + fdt_setprop_inplace(initial_boot_params, usbn, + "refclk-frequency", new_f, sizeof(new_f)); + /* Fall through ...*/ + case USB_CLOCK_TYPE_REF_12: + /* Missing "refclk-type" defaults to external. */ + fdt_nop_property(initial_boot_params, usbn, "refclk-type"); + break; + default: + break; + } + } + } + return 0; } diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts index 88cb42d4cc49..fa33115bde33 100644 --- a/arch/mips/cavium-octeon/octeon_3xxx.dts +++ b/arch/mips/cavium-octeon/octeon_3xxx.dts @@ -550,6 +550,24 @@ big-endian-regs; }; }; + + usbn: usbn@1180068000000 { + compatible = "cavium,octeon-5750-usbn"; + reg = <0x11800 0x68000000 0x0 0x1000>; + ranges; /* Direct mapping */ + #address-cells = <2>; + #size-cells = <2>; + /* 12MHz, 24MHz and 48MHz allowed */ + refclk-frequency = <12000000>; + /* Either "crystal" or "external" */ + refclk-type = "crystal"; + + usbc@16f0010000000 { + compatible = "cavium,octeon-5750-usbc"; + reg = <0x16f00 0x10000000 0x0 0x80000>; + interrupts = <0 56>; + }; + }; }; aliases { @@ -566,6 +584,7 @@ flash0 = &flash0; cf0 = &cf0; uctl = &uctl; + usbn = &usbn; led0 = &led0; }; }; diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 24a2167db778..67a078ffc464 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -6,7 +6,6 @@ * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks */ #include <linux/cpu.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/smp.h> #include <linux/interrupt.h> diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig index 80e012fa409c..320772caf054 100644 --- a/arch/mips/configs/ar7_defconfig +++ b/arch/mips/configs/ar7_defconfig @@ -86,7 +86,6 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig index 4ca8e5c99225..0db4eb319e0a 100644 --- a/arch/mips/configs/bcm47xx_defconfig +++ b/arch/mips/configs/bcm47xx_defconfig @@ -1,623 +1,86 @@ CONFIG_BCM47XX=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_KEXEC=y -# CONFIG_SECCOMP is not set -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_AUDIT=y -CONFIG_TINY_RCU=y -CONFIG_CGROUPS=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_RELAY=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_UIDGID_STRICT_TYPE_CHECKS=y CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_LZMA=y -CONFIG_EXPERT=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y CONFIG_PCI=y -CONFIG_BINFMT_MISC=m +# CONFIG_SUSPEND is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y -CONFIG_XFRM_USER=m -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_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=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=m CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=y -CONFIG_TCP_CONG_CUBIC=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_TCP_CONG_LP=m -CONFIG_TCP_CONG_VENO=m -CONFIG_TCP_CONG_YEAH=m -CONFIG_TCP_CONG_ILLINOIS=m CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m -CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y -CONFIG_NETWORK_SECMARK=y +CONFIG_IPV6_MROUTE=y CONFIG_NETFILTER=y -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NF_CONNTRACK=m -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_EVENTS=y -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_NETBIOS_NS=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_CONNSECMARK=m -CONFIG_NETFILTER_XT_TARGET_DSCP=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_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_DSCP=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -CONFIG_NETFILTER_XT_MATCH_HELPER=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_POLICY=m -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_REALM=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_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_IP_VS_FTP=m -CONFIG_NF_CONNTRACK_IPV4=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_ADDRTYPE=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_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_NF_NAT_SNMP_BASIC=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_QUEUE=m -CONFIG_IP6_NF_IPTABLES=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_TARGET_LOG=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_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_ULOG=m -CONFIG_IP_DCCP=m -CONFIG_TIPC=m -CONFIG_TIPC_ADVANCED=y -CONFIG_ATM=m -CONFIG_ATM_CLIP=m -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_ATM=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_CLS_U32_PERF=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_CMP=m -CONFIG_NET_EMATCH_NBYTE=m -CONFIG_NET_EMATCH_U32=m -CONFIG_NET_EMATCH_META=m -CONFIG_NET_EMATCH_TEXT=m -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=m -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_CLS_IND=y -CONFIG_NET_PKTGEN=m -CONFIG_BT=m -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_LL=y -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBPA10X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIVHCI=m -CONFIG_CFG80211=m -CONFIG_MAC80211=m -CONFIG_MAC80211_RC_PID=y -CONFIG_MAC80211_RC_DEFAULT_PID=y -CONFIG_MAC80211_MESH=y -CONFIG_RFKILL=m -CONFIG_RFKILL_INPUT=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_FW_LOADER=m -CONFIG_CONNECTOR=m +CONFIG_NET_SCH_FQ_CODEL=y +CONFIG_HAMRADIO=y +CONFIG_CFG80211=y +CONFIG_MAC80211=y CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_CHAR=y +CONFIG_MTD_BCM47XX_PARTS=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_RAM=y -CONFIG_MTD_ROM=y -CONFIG_MTD_ABSENT=y +CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_PHYSMAP=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_ATA_OVER_ETH=m -CONFIG_RAID_ATTRS=m -CONFIG_SCSI=y -CONFIG_SCSI_TGT=m -CONFIG_BLK_DEV_SD=y -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_CHR_DEV_SCH=m -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_ISCSI_TCP=m +CONFIG_MTD_BCM47XXSFLASH=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BCM47XXNFLASH=y CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_VETH=m -CONFIG_PHYLIB=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_MDIO_BITBANG=m -CONFIG_NET_ETHERNET=y -CONFIG_NET_PCI=y CONFIG_B44=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -CONFIG_ATH_COMMON=m -CONFIG_ATH5K=m -CONFIG_B43=m -CONFIG_B43LEGACY=m -CONFIG_ZD1211RW=m -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_USBNET=m -CONFIG_USB_NET_DM9601=m -CONFIG_USB_NET_GL620A=m -CONFIG_USB_NET_PLUSB=m -CONFIG_USB_NET_MCS7830=m -CONFIG_USB_NET_RNDIS_HOST=m -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_KC2190=y -CONFIG_USB_SIERRA_NET=m -CONFIG_ATM_DUMMY=m -CONFIG_ATM_TCP=m -CONFIG_PPP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set +CONFIG_TIGON3=y +CONFIG_BGMAC=y +CONFIG_ATH_CARDS=y +CONFIG_ATH5K=y +CONFIG_B43=y +CONFIG_B43LEGACY=y +CONFIG_BRCMSMAC=y +CONFIG_ISDN=y CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_SERIAL_8250_PCI is not set CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -# CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set -CONFIG_W1=m -CONFIG_W1_MASTER_MATROX=m -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -CONFIG_W1_SLAVE_DS2433=m -CONFIG_W1_SLAVE_DS2760=m -# CONFIG_HWMON is not set -CONFIG_THERMAL=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_HW_RANDOM=y +CONFIG_GPIO_SYSFS=y CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_BCM47XX_WDT=y +CONFIG_SSB_DEBUG=y CONFIG_SSB_DRIVER_GIGE=y -CONFIG_DISPLAY_SUPPORT=m -CONFIG_SOUND=m -CONFIG_SND=m -CONFIG_SND_SEQUENCER=m -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_SEQUENCER_OSS=y -CONFIG_SND_DUMMY=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_USB_AUDIO=m -CONFIG_HID=m -CONFIG_USB_HID=m -CONFIG_USB_HIDDEV=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y CONFIG_USB=y -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DEVICE_CLASS is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_U132_HCD=m -CONFIG_USB_R8A66597_HCD=m -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_ONETOUCH=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_MDC800=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_SERIAL=m -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_AIRCABLE=m -CONFIG_USB_SERIAL_ARK3116=m -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_CH341=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_FUNSOFT=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_MOS7720=m -CONFIG_USB_SERIAL_MOS7840=m -CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_HP4X=m -CONFIG_USB_SERIAL_SAFE=m -CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OPTION=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_DEBUG=m -CONFIG_USB_ADUTUX=m -CONFIG_USB_RIO500=m -CONFIG_USB_LEGOTOWER=m -CONFIG_USB_LCD=m -CONFIG_USB_LED=m -CONFIG_USB_CYPRESS_CY7C63=m -CONFIG_USB_CYTHERM=m -CONFIG_USB_IDMOUSE=m -CONFIG_USB_FTDI_ELAN=m -CONFIG_USB_SISUSBVGA=m -CONFIG_USB_LD=m -CONFIG_USB_TRANCEVIBRATOR=m -CONFIG_USB_IOWARRIOR=m -CONFIG_USB_TEST=m -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m -CONFIG_USB_CXACRU=m -CONFIG_USB_UEAGLEATM=m -CONFIG_USB_XUSBATM=m -CONFIG_USB_GADGET=m -CONFIG_USB_GADGET_NET2280=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -CONFIG_USB_GADGETFS=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_MIDI_GADGET=m -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y +CONFIG_USB_HCD_BCMA=y +CONFIG_USB_HCD_SSB=y CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_REISERFS_FS=m -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_XFS_RT=y -CONFIG_GFS2_FS=m -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -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_NTFS_FS=m -CONFIG_NTFS_RW=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_ADFS_FS=m -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_CRAMFS=m -CONFIG_VXFS_FS=m -CONFIG_MINIX_FS=m -CONFIG_HPFS_FS=m -CONFIG_QNX4FS_FS=m -CONFIG_ROMFS_FS=m -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFSD=m -CONFIG_NFSD_V3_ACL=y -CONFIG_NFSD_V4=y -CONFIG_RPCSEC_GSS_SPKM3=m -CONFIG_CIFS=m -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -CONFIG_NCP_FS=m -CONFIG_NCPFS_NFS_NS=y -CONFIG_NCPFS_OS2_NS=y -CONFIG_NCPFS_NLS=y -CONFIG_NCPFS_EXTRAS=y -CONFIG_CODA_FS=m -CONFIG_PARTITION_ADVANCED=y -CONFIG_KARMA_PARTITION=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_DLM=m -CONFIG_DLM_DEBUG=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +CONFIG_STRIP_ASM_SYMS=y CONFIG_DEBUG_FS=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_LRW=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XTS=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=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_CAST6=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SEED=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRC16=m -CONFIG_CRC7=m +CONFIG_MAGIC_SYSRQ=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,115200" +CONFIG_CRC32_SARWATE=y diff --git a/arch/mips/configs/bcm63xx_defconfig b/arch/mips/configs/bcm63xx_defconfig index 919005139f5a..3fec26410f34 100644 --- a/arch/mips/configs/bcm63xx_defconfig +++ b/arch/mips/configs/bcm63xx_defconfig @@ -44,7 +44,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index 5419adb219a8..23b66934e18d 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -19,7 +19,6 @@ CONFIG_INET=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLKDEVS=y CONFIG_MTD_JEDECPROBE=y diff --git a/arch/mips/configs/gpr_defconfig b/arch/mips/configs/gpr_defconfig index fb64589015fc..8f219dac9598 100644 --- a/arch/mips/configs/gpr_defconfig +++ b/arch/mips/configs/gpr_defconfig @@ -165,7 +165,6 @@ CONFIG_YAM=m CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index db5705e18b36..9bc08f275120 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig @@ -22,7 +22,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig index d9f3db29ab95..0179c7fa014f 100644 --- a/arch/mips/configs/lasat_defconfig +++ b/arch/mips/configs/lasat_defconfig @@ -31,7 +31,6 @@ CONFIG_INET=y # CONFIG_INET_DIAG is not set # CONFIG_IPV6 is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig index 8a666021b870..d75931850392 100644 --- a/arch/mips/configs/maltasmvp_defconfig +++ b/arch/mips/configs/maltasmvp_defconfig @@ -4,7 +4,7 @@ CONFIG_CPU_MIPS32_R2=y CONFIG_MIPS_MT_SMP=y CONFIG_SCHED_SMT=y CONFIG_MIPS_CMP=y -CONFIG_NR_CPUS=8 +CONFIG_NR_CPUS=2 CONFIG_HZ_100=y CONFIG_LOCALVERSION="cmp" CONFIG_SYSVIPC=y @@ -58,7 +58,6 @@ CONFIG_ATALK=m CONFIG_DEV_APPLETALK=m CONFIG_IPDDP=m CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig index 636f82b89fd3..4c2c0c4b9bb1 100644 --- a/arch/mips/configs/markeins_defconfig +++ b/arch/mips/configs/markeins_defconfig @@ -124,7 +124,6 @@ CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_RAW=m CONFIG_FW_LOADER=m CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index 9fa8f16068d8..593946afc483 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig @@ -246,7 +246,6 @@ CONFIG_BT_HCIBTUART=m CONFIG_BT_HCIVHCI=m CONFIG_CONNECTOR=m CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y diff --git a/arch/mips/configs/pnx8335_stb225_defconfig b/arch/mips/configs/pnx8335_stb225_defconfig index f2925769dfa3..c887066ecc2a 100644 --- a/arch/mips/configs/pnx8335_stb225_defconfig +++ b/arch/mips/configs/pnx8335_stb225_defconfig @@ -31,7 +31,6 @@ CONFIG_INET_AH=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig new file mode 100644 index 000000000000..2b965470c35b --- /dev/null +++ b/arch/mips/configs/qi_lb60_defconfig @@ -0,0 +1,188 @@ +CONFIG_MACH_JZ4740=y +# CONFIG_COMPACTION is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_HZ_100=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_EFI_PARTITION is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=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_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=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_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_CUBIC is not set +CONFIG_TCP_CONG_WESTWOOD=y +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_JZ4740=y +CONFIG_MTD_UBI=y +CONFIG_NETDEVICES=y +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_MATRIX=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +# CONFIG_SERIO is not set +CONFIG_LEGACY_PTY_COUNT=2 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_HW_RANDOM is not set +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_BATTERY_JZ4740=y +CONFIG_CHARGER_GPIO=y +# CONFIG_HWMON is not set +CONFIG_MFD_JZ4740_ADC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_FB=y +CONFIG_FB_JZ4740=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_MIPS is not set +CONFIG_SND_SOC=y +CONFIG_SND_JZ4740_SOC=y +CONFIG_SND_JZ4740_SOC_QI_LB60=y +CONFIG_USB=y +CONFIG_USB_OTG_BLACKLIST_HUB=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_JZ4740=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG=y +CONFIG_USB_ETH=y +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_MMC=y +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_JZ4740=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_JZ4740=y +CONFIG_DMADEVICES=y +CONFIG_DMA_JZ4740=y +CONFIG_PWM=y +CONFIG_PWM_JZ4740=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +# CONFIG_JFFS2_ZLIB is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_READABLE_ASM=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_PANIC_ON_OOPS=y +# CONFIG_FTRACE is not set +CONFIG_KGDB=y +CONFIG_RUNTIME_DEBUG=y +CONFIG_CRYPTO_ZLIB=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_FONTS=y +CONFIG_FONT_SUN8x16=y diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig index b85b121397c8..5d9d708e12e5 100644 --- a/arch/mips/configs/rb532_defconfig +++ b/arch/mips/configs/rb532_defconfig @@ -114,7 +114,6 @@ CONFIG_NET_CLS_IND=y CONFIG_HAMRADIO=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK2MTD=y diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig index 9cba856277ff..f8bf9b4c1343 100644 --- a/arch/mips/configs/rbtx49xx_defconfig +++ b/arch/mips/configs/rbtx49xx_defconfig @@ -35,7 +35,6 @@ CONFIG_IP_PNP=y # CONFIG_IPV6 is not set # CONFIG_WIRELESS is not set CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=m diff --git a/arch/mips/fw/arc/file.c b/arch/mips/fw/arc/file.c index a8b08032348f..49fd3ff13fe5 100644 --- a/arch/mips/fw/arc/file.c +++ b/arch/mips/fw/arc/file.c @@ -8,7 +8,6 @@ * Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ -#include <linux/init.h> #include <asm/fw/arc/types.h> #include <asm/sgialib.h> diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h index c3dc1a68dd8d..3cc03c64a9c7 100644 --- a/arch/mips/include/asm/amon.h +++ b/arch/mips/include/asm/amon.h @@ -1,7 +1,12 @@ /* - * Amon support + * 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 Imagination Technologies Ltd. + * + * Arbitrary Monitor Support (AMON) */ - -int amon_cpu_avail(int); -void amon_cpu_start(int, unsigned long, unsigned long, - unsigned long, unsigned long); +int amon_cpu_avail(int cpu); +int amon_cpu_start(int cpu, unsigned long pc, unsigned long sp, + unsigned long gp, unsigned long a0); diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h index 2413afe21b33..70e1f176f123 100644 --- a/arch/mips/include/asm/asmmacro-32.h +++ b/arch/mips/include/asm/asmmacro-32.h @@ -12,27 +12,6 @@ #include <asm/fpregdef.h> #include <asm/mipsregs.h> - .macro fpu_save_double thread status tmp1=t0 - cfc1 \tmp1, fcr31 - 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 \tmp1, THREAD_FCR31(\thread) - .endm - .macro fpu_save_single thread tmp=t0 cfc1 \tmp, fcr31 swc1 $f0, THREAD_FPR0(\thread) @@ -70,27 +49,6 @@ sw \tmp, THREAD_FCR31(\thread) .endm - .macro fpu_restore_double thread status tmp=t0 - lw \tmp, THREAD_FCR31(\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 - .macro fpu_restore_single thread tmp=t0 lw \tmp, THREAD_FCR31(\thread) lwc1 $f0, THREAD_FPR0(\thread) diff --git a/arch/mips/include/asm/asmmacro-64.h b/arch/mips/include/asm/asmmacro-64.h index 08a527dfe4a3..38ea609465b1 100644 --- a/arch/mips/include/asm/asmmacro-64.h +++ b/arch/mips/include/asm/asmmacro-64.h @@ -13,102 +13,6 @@ #include <asm/fpregdef.h> #include <asm/mipsregs.h> - .macro fpu_save_16even thread tmp=t0 - cfc1 \tmp, fcr31 - 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) - .endm - - .macro fpu_save_16odd 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) - .endm - - .macro fpu_save_double thread status tmp - sll \tmp, \status, 5 - bgez \tmp, 2f - fpu_save_16odd \thread -2: - fpu_save_16even \thread \tmp - .endm - - .macro fpu_restore_16even thread tmp=t0 - lw \tmp, THREAD_FCR31(\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 - - .macro fpu_restore_16odd 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) - .endm - - .macro fpu_restore_double thread status tmp - sll \tmp, \status, 5 - bgez \tmp, 1f # 16 register mode? - - fpu_restore_16odd \thread -1: fpu_restore_16even \thread \tmp - .endm - .macro cpu_save_nonscratch thread LONG_S s0, THREAD_REG16(\thread) LONG_S s1, THREAD_REG17(\thread) diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 6c8342ae74db..3220c93ea981 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -62,6 +62,113 @@ .endm #endif /* CONFIG_MIPS_MT_SMTC */ + .macro fpu_save_16even thread tmp=t0 + cfc1 \tmp, fcr31 + 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) + .endm + + .macro fpu_save_16odd thread + .set push + .set mips64r2 + 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 + + .macro fpu_save_double thread status tmp +#if defined(CONFIG_MIPS64) || defined(CONFIG_CPU_MIPS32_R2) + sll \tmp, \status, 5 + bgez \tmp, 10f + fpu_save_16odd \thread +10: +#endif + fpu_save_16even \thread \tmp + .endm + + .macro fpu_restore_16even thread tmp=t0 + lw \tmp, THREAD_FCR31(\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 + + .macro fpu_restore_16odd thread + .set push + .set mips64r2 + 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 + + .macro fpu_restore_double thread status tmp +#if defined(CONFIG_MIPS64) || defined(CONFIG_CPU_MIPS32_R2) + sll \tmp, \status, 5 + bgez \tmp, 10f # 16 register mode? + + fpu_restore_16odd \thread +10: +#endif + fpu_restore_16even \thread \tmp + .endm + /* * Temporary until all gas have MT ASE support */ diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index 27bd060d716e..cbaccebf5065 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -46,8 +46,35 @@ #include <linux/cpumask.h> #include <asm/r4kcache.h> +#include <asm/smp-ops.h> + +extern struct plat_smp_ops bmips43xx_smp_ops; +extern struct plat_smp_ops bmips5000_smp_ops; + +static inline int register_bmips_smp_ops(void) +{ +#if IS_ENABLED(CONFIG_CPU_BMIPS) && IS_ENABLED(CONFIG_SMP) + switch (current_cpu_type()) { + case CPU_BMIPS32: + case CPU_BMIPS3300: + return register_up_smp_ops(); + case CPU_BMIPS4350: + case CPU_BMIPS4380: + register_smp_ops(&bmips43xx_smp_ops); + break; + case CPU_BMIPS5000: + register_smp_ops(&bmips5000_smp_ops); + break; + default: + return -ENODEV; + } + + return 0; +#else + return -ENODEV; +#endif +} -extern struct plat_smp_ops bmips_smp_ops; extern char bmips_reset_nmi_vec; extern char bmips_reset_nmi_vec_end; extern char bmips_smp_movevec; diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index d445d060e346..6e70b03b6aab 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -20,6 +20,13 @@ #ifndef cpu_has_tlb #define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB) #endif +#ifndef cpu_has_tlbinv +#define cpu_has_tlbinv (cpu_data[0].options & MIPS_CPU_TLBINV) +#endif +#ifndef cpu_has_segments +#define cpu_has_segments (cpu_data[0].options & MIPS_CPU_SEGMENTS) +#endif + /* * For the moment we don't consider R6000 and R8000 so we can assume that diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index 21c8e29c8f91..8f7adf0ac1e3 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -52,6 +52,9 @@ struct cpuinfo_mips { unsigned int cputype; int isa_level; int tlbsize; + int tlbsizevtlb; + int tlbsizeftlbsets; + int tlbsizeftlbways; struct cache_desc icache; /* Primary I-cache */ struct cache_desc dcache; /* Primary D or combined I/D cache */ struct cache_desc scache; /* Secondary cache */ diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 4a402cc60c03..02f591bd95ca 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -27,10 +27,7 @@ static inline int __pure __get_cpu_type(const int cpu_type) #ifdef CONFIG_SYS_HAS_CPU_MIPS32_R1 case CPU_4KC: case CPU_ALCHEMY: - case CPU_BMIPS3300: - case CPU_BMIPS4350: case CPU_PR4450: - case CPU_BMIPS32: case CPU_JZRISC: #endif @@ -47,6 +44,8 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_74K: case CPU_M14KC: case CPU_M14KEC: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: #endif #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1 @@ -163,6 +162,16 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_CAVIUM_OCTEON2: #endif +#if defined(CONFIG_SYS_HAS_CPU_BMIPS32_3300) || \ + defined (CONFIG_SYS_HAS_CPU_MIPS32_R1) + case CPU_BMIPS32: + case CPU_BMIPS3300: +#endif + +#ifdef CONFIG_SYS_HAS_CPU_BMIPS4350 + case CPU_BMIPS4350: +#endif + #ifdef CONFIG_SYS_HAS_CPU_BMIPS4380 case CPU_BMIPS4380: #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index d2035e16502a..76411df3d971 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -111,6 +111,10 @@ #define PRID_IMP_1074K 0x9a00 #define PRID_IMP_M14KC 0x9c00 #define PRID_IMP_M14KEC 0x9e00 +#define PRID_IMP_INTERAPTIV_UP 0xa000 +#define PRID_IMP_INTERAPTIV_MP 0xa100 +#define PRID_IMP_PROAPTIV_UP 0xa200 +#define PRID_IMP_PROAPTIV_MP 0xa300 /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -194,6 +198,7 @@ #define PRID_IMP_NETLOGIC_XLP8XX 0x1000 #define PRID_IMP_NETLOGIC_XLP3XX 0x1100 #define PRID_IMP_NETLOGIC_XLP2XX 0x1200 +#define PRID_IMP_NETLOGIC_XLP9XX 0x1500 /* * Particular Revision values for bits 7:0 of the PRId register. @@ -249,6 +254,8 @@ #define FPIR_IMP_NONE 0x0000 +#if !defined(__ASSEMBLY__) + enum cpu_type_enum { CPU_UNKNOWN, @@ -289,7 +296,7 @@ enum cpu_type_enum { CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, - CPU_M14KEC, + CPU_M14KEC, CPU_INTERAPTIV, CPU_PROAPTIV, /* * MIPS64 class processors @@ -301,6 +308,7 @@ enum cpu_type_enum { CPU_LAST }; +#endif /* !__ASSEMBLY */ /* * ISA Level encodings @@ -348,6 +356,8 @@ enum cpu_type_enum { #define MIPS_CPU_PCI 0x00400000 /* CPU has Perf Ctr Int indicator */ #define MIPS_CPU_RIXI 0x00800000 /* CPU has TLB Read/eXec Inhibit */ #define MIPS_CPU_MICROMIPS 0x01000000 /* CPU has microMIPS capability */ +#define MIPS_CPU_TLBINV 0x02000000 /* CPU supports TLBINV/F */ +#define MIPS_CPU_SEGMENTS 0x04000000 /* CPU supports Segmentation Control registers */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/dma-coherence.h b/arch/mips/include/asm/dma-coherence.h index 242cbb3ca582..bc5e85d579e6 100644 --- a/arch/mips/include/asm/dma-coherence.h +++ b/arch/mips/include/asm/dma-coherence.h @@ -9,7 +9,16 @@ #ifndef __ASM_DMA_COHERENCE_H #define __ASM_DMA_COHERENCE_H +#ifdef CONFIG_DMA_MAYBE_COHERENT extern int coherentio; extern int hw_coherentio; +#else +#ifdef CONFIG_DMA_COHERENT +#define coherentio 1 +#else +#define coherentio 0 +#endif +#define hw_coherentio 0 +#endif /* CONFIG_DMA_MAYBE_COHERENT */ #endif diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index a66359ef4ece..d4144056e928 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -36,6 +36,7 @@ #define EF_MIPS_ABI2 0x00000020 #define EF_MIPS_OPTIONS_FIRST 0x00000080 #define EF_MIPS_32BITMODE 0x00000100 +#define EF_MIPS_FP64 0x00000200 #define EF_MIPS_ABI 0x0000f000 #define EF_MIPS_ARCH 0xf0000000 @@ -176,6 +177,18 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #ifdef CONFIG_32BIT /* + * In order to be sure that we don't attempt to execute an O32 binary which + * requires 64 bit FP (FR=1) on a system which does not support it we refuse + * to execute any binary which has bits specified by the following macro set + * in its ELF header flags. + */ +#ifdef CONFIG_MIPS_O32_FP64_SUPPORT +# define __MIPS_O32_FP64_MUST_BE_ZERO 0 +#else +# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 +#endif + +/* * This is used to ensure we don't load something for the wrong architecture. */ #define elf_check_arch(hdr) \ @@ -192,6 +205,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ __res = 0; \ + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ + __res = 0; \ \ __res; \ }) @@ -249,6 +264,11 @@ extern struct mips_abi mips_abi_n32; #define SET_PERSONALITY(ex) \ do { \ + if ((ex).e_flags & EF_MIPS_FP64) \ + clear_thread_flag(TIF_32BIT_FPREGS); \ + else \ + set_thread_flag(TIF_32BIT_FPREGS); \ + \ if (personality(current->personality) != PER_LINUX) \ set_personality(PER_LINUX); \ \ @@ -271,14 +291,18 @@ do { \ #endif #ifdef CONFIG_MIPS32_O32 -#define __SET_PERSONALITY32_O32() \ +#define __SET_PERSONALITY32_O32(ex) \ do { \ set_thread_flag(TIF_32BIT_REGS); \ set_thread_flag(TIF_32BIT_ADDR); \ + \ + if (!((ex).e_flags & EF_MIPS_FP64)) \ + set_thread_flag(TIF_32BIT_FPREGS); \ + \ current->thread.abi = &mips_abi_32; \ } while (0) #else -#define __SET_PERSONALITY32_O32() \ +#define __SET_PERSONALITY32_O32(ex) \ do { } while (0) #endif @@ -289,7 +313,7 @@ do { \ ((ex).e_flags & EF_MIPS_ABI) == 0) \ __SET_PERSONALITY32_N32(); \ else \ - __SET_PERSONALITY32_O32(); \ + __SET_PERSONALITY32_O32(ex); \ } while (0) #else #define __SET_PERSONALITY32(ex) do { } while (0) @@ -300,6 +324,7 @@ do { \ unsigned int p; \ \ clear_thread_flag(TIF_32BIT_REGS); \ + clear_thread_flag(TIF_32BIT_FPREGS); \ clear_thread_flag(TIF_32BIT_ADDR); \ \ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h index d088e5db4903..cfe092fc720d 100644 --- a/arch/mips/include/asm/fpu.h +++ b/arch/mips/include/asm/fpu.h @@ -33,11 +33,48 @@ extern void _init_fpu(void); extern void _save_fp(struct task_struct *); extern void _restore_fp(struct task_struct *); -#define __enable_fpu() \ -do { \ - set_c0_status(ST0_CU1); \ - enable_fpu_hazard(); \ -} while (0) +/* + * This enum specifies a mode in which we want the FPU to operate, for cores + * which implement the Status.FR bit. Note that FPU_32BIT & FPU_64BIT + * purposefully have the values 0 & 1 respectively, so that an integer value + * of Status.FR can be trivially casted to the corresponding enum fpu_mode. + */ +enum fpu_mode { + FPU_32BIT = 0, /* FR = 0 */ + FPU_64BIT, /* FR = 1 */ + FPU_AS_IS, +}; + +static inline int __enable_fpu(enum fpu_mode mode) +{ + int fr; + + switch (mode) { + case FPU_AS_IS: + /* just enable the FPU in its current mode */ + set_c0_status(ST0_CU1); + enable_fpu_hazard(); + return 0; + + case FPU_64BIT: +#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_MIPS64)) + /* we only have a 32-bit FPU */ + return SIGFPE; +#endif + /* fall through */ + case FPU_32BIT: + /* set CU1 & change FR appropriately */ + fr = (int)mode; + change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0)); + enable_fpu_hazard(); + + /* check FR has the desired value */ + return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE; + + default: + BUG(); + } +} #define __disable_fpu() \ do { \ @@ -45,19 +82,6 @@ do { \ disable_fpu_hazard(); \ } while (0) -#define enable_fpu() \ -do { \ - if (cpu_has_fpu) \ - __enable_fpu(); \ -} while (0) - -#define disable_fpu() \ -do { \ - if (cpu_has_fpu) \ - __disable_fpu(); \ -} while (0) - - #define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) static inline int __is_fpu_owner(void) @@ -70,27 +94,46 @@ static inline int is_fpu_owner(void) return cpu_has_fpu && __is_fpu_owner(); } -static inline void __own_fpu(void) +static inline int __own_fpu(void) { - __enable_fpu(); + enum fpu_mode mode; + int ret; + + mode = !test_thread_flag(TIF_32BIT_FPREGS); + ret = __enable_fpu(mode); + if (ret) + return ret; + KSTK_STATUS(current) |= ST0_CU1; + if (mode == FPU_64BIT) + KSTK_STATUS(current) |= ST0_FR; + else /* mode == FPU_32BIT */ + KSTK_STATUS(current) &= ~ST0_FR; + set_thread_flag(TIF_USEDFPU); + return 0; } -static inline void own_fpu_inatomic(int restore) +static inline int own_fpu_inatomic(int restore) { + int ret = 0; + if (cpu_has_fpu && !__is_fpu_owner()) { - __own_fpu(); - if (restore) + ret = __own_fpu(); + if (restore && !ret) _restore_fp(current); } + return ret; } -static inline void own_fpu(int restore) +static inline int own_fpu(int restore) { + int ret; + preempt_disable(); - own_fpu_inatomic(restore); + ret = own_fpu_inatomic(restore); preempt_enable(); + return ret; } static inline void lose_fpu(int save) @@ -106,16 +149,21 @@ static inline void lose_fpu(int save) preempt_enable(); } -static inline void init_fpu(void) +static inline int init_fpu(void) { + int ret = 0; + preempt_disable(); if (cpu_has_fpu) { - __own_fpu(); - _init_fpu(); + ret = __own_fpu(); + if (!ret) + _init_fpu(); } else { fpu_emulator_init_fpu(); } + preempt_enable(); + return ret; } static inline void save_fp(struct task_struct *tsk) diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h index b0dd0c84df70..572e63ec2a38 100644 --- a/arch/mips/include/asm/highmem.h +++ b/arch/mips/include/asm/highmem.h @@ -19,7 +19,6 @@ #ifdef __KERNEL__ -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/uaccess.h> #include <asm/kmap_types.h> diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 32966969f2f9..a995fce87791 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -391,9 +391,6 @@ struct kvm_vcpu_arch { uint32_t guest_kernel_asid[NR_CPUS]; struct mm_struct guest_kernel_mm, guest_user_mm; - struct kvm_mips_tlb shadow_tlb[NR_CPUS][KVM_MIPS_GUEST_TLB_SIZE]; - - struct hrtimer comparecount_timer; int last_sched_cpu; @@ -529,7 +526,6 @@ extern enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, extern void kvm_mips_dump_host_tlbs(void); extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu); -extern void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu); extern void kvm_mips_flush_host_tlb(int skip_kseg0); extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi); extern int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index); @@ -541,10 +537,7 @@ extern unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu unsigned long gva); extern void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, struct kvm_vcpu *vcpu); -extern void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu); -extern void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu); extern void kvm_local_flush_tlb_all(void); -extern void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu); extern void kvm_mips_alloc_new_mmu_context(struct kvm_vcpu *vcpu); extern void kvm_mips_vcpu_load(struct kvm_vcpu *vcpu, int cpu); extern void kvm_mips_vcpu_put(struct kvm_vcpu *vcpu); diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index b86a1253a5bf..cd41e93bc1d8 100644 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -16,7 +16,6 @@ #define __ASM_MACH_AR71XX_REGS_H #include <linux/types.h> -#include <linux/init.h> #include <linux/io.h> #include <linux/bitops.h> diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h index cc7563ba1cbf..7527c1d33d02 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h @@ -56,4 +56,6 @@ void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo, const char *prefix); #endif +void bcm47xx_set_system_type(u16 chip_id); + #endif /* __ASM_BCM47XX_H */ diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h index 00867dd05a69..40005fb39618 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h @@ -66,6 +66,7 @@ enum bcm47xx_board { BCM47XX_BOARD_LINKSYS_WRT310NV1, BCM47XX_BOARD_LINKSYS_WRT310NV2, BCM47XX_BOARD_LINKSYS_WRT54G3GV2, + BCM47XX_BOARD_LINKSYS_WRT54GSV1, BCM47XX_BOARD_LINKSYS_WRT610NV1, BCM47XX_BOARD_LINKSYS_WRT610NV2, BCM47XX_BOARD_LINKSYS_WRTSL54GS, diff --git a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h new file mode 100644 index 000000000000..b7992cd4aaf9 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h @@ -0,0 +1,82 @@ +#ifndef __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB) +#define cpu_has_watch 1 +#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA) +#define cpu_has_watch 0 +#endif +#define cpu_has_divec 1 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +/* cpu_has_mips16 */ +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_rixi 0 +#define cpu_has_mmips 0 +#define cpu_has_smartmips 0 +#define cpu_has_vtag_icache 0 +/* cpu_has_dc_aliases */ +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_pindexed_dcache 0 +#define cpu_icache_snoops_remote_store 0 + +#define cpu_has_mips_2 1 +#define cpu_has_mips_3 0 +#define cpu_has_mips32r1 1 +#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB) +#define cpu_has_mips32r2 1 +#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA) +#define cpu_has_mips32r2 0 +#endif +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB) +#define cpu_has_dsp 1 +#define cpu_has_dsp2 1 +#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA) +#define cpu_has_dsp 0 +#define cpu_has_dsp2 0 +#endif +#define cpu_has_mipsmt 0 +/* cpu_has_userlocal */ + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB) +#define cpu_has_vint 1 +#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA) +#define cpu_has_vint 0 +#endif +#define cpu_has_veic 0 +#define cpu_has_inclusive_pcaches 0 + +#if defined(CONFIG_BCM47XX_BCMA) && !defined(CONFIG_BCM47XX_SSB) +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_has_perf_cntr_intr_bit 1 +#elif defined(CONFIG_BCM47XX_SSB) && !defined(CONFIG_BCM47XX_BCMA) +#define cpu_dcache_line_size() 16 +#define cpu_icache_line_size() 16 +#define cpu_has_perf_cntr_intr_bit 0 +#endif +#define cpu_scache_line_size() 0 +#define cpu_has_vz 0 + +#endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 19f9134bfe2f..3112f08f0c72 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -145,6 +145,7 @@ enum bcm63xx_regs_set { RSET_UART1, RSET_GPIO, RSET_SPI, + RSET_HSSPI, RSET_UDC0, RSET_OHCI0, RSET_OHCI_PRIV, @@ -193,6 +194,7 @@ enum bcm63xx_regs_set { #define RSET_ENETDMAS_SIZE(chans) (16 * (chans)) #define RSET_ENETSW_SIZE 65536 #define RSET_UART_SIZE 24 +#define RSET_HSSPI_SIZE 1536 #define RSET_UDC_SIZE 256 #define RSET_OHCI_SIZE 256 #define RSET_EHCI_SIZE 256 @@ -265,6 +267,7 @@ enum bcm63xx_regs_set { #define BCM_6328_UART1_BASE (0xb0000120) #define BCM_6328_GPIO_BASE (0xb0000080) #define BCM_6328_SPI_BASE (0xdeadbeef) +#define BCM_6328_HSSPI_BASE (0xb0001000) #define BCM_6328_UDC0_BASE (0xdeadbeef) #define BCM_6328_USBDMA_BASE (0xb000c000) #define BCM_6328_OHCI0_BASE (0xb0002600) @@ -313,6 +316,7 @@ enum bcm63xx_regs_set { #define BCM_6338_UART1_BASE (0xdeadbeef) #define BCM_6338_GPIO_BASE (0xfffe0400) #define BCM_6338_SPI_BASE (0xfffe0c00) +#define BCM_6338_HSSPI_BASE (0xdeadbeef) #define BCM_6338_UDC0_BASE (0xdeadbeef) #define BCM_6338_USBDMA_BASE (0xfffe2400) #define BCM_6338_OHCI0_BASE (0xdeadbeef) @@ -360,6 +364,7 @@ enum bcm63xx_regs_set { #define BCM_6345_UART1_BASE (0xdeadbeef) #define BCM_6345_GPIO_BASE (0xfffe0400) #define BCM_6345_SPI_BASE (0xdeadbeef) +#define BCM_6345_HSSPI_BASE (0xdeadbeef) #define BCM_6345_UDC0_BASE (0xdeadbeef) #define BCM_6345_USBDMA_BASE (0xfffe2800) #define BCM_6345_ENET0_BASE (0xfffe1800) @@ -406,6 +411,7 @@ enum bcm63xx_regs_set { #define BCM_6348_UART1_BASE (0xdeadbeef) #define BCM_6348_GPIO_BASE (0xfffe0400) #define BCM_6348_SPI_BASE (0xfffe0c00) +#define BCM_6348_HSSPI_BASE (0xdeadbeef) #define BCM_6348_UDC0_BASE (0xfffe1000) #define BCM_6348_USBDMA_BASE (0xdeadbeef) #define BCM_6348_OHCI0_BASE (0xfffe1b00) @@ -451,6 +457,7 @@ enum bcm63xx_regs_set { #define BCM_6358_UART1_BASE (0xfffe0120) #define BCM_6358_GPIO_BASE (0xfffe0080) #define BCM_6358_SPI_BASE (0xfffe0800) +#define BCM_6358_HSSPI_BASE (0xdeadbeef) #define BCM_6358_UDC0_BASE (0xfffe0800) #define BCM_6358_USBDMA_BASE (0xdeadbeef) #define BCM_6358_OHCI0_BASE (0xfffe1400) @@ -553,6 +560,7 @@ enum bcm63xx_regs_set { #define BCM_6368_UART1_BASE (0xb0000120) #define BCM_6368_GPIO_BASE (0xb0000080) #define BCM_6368_SPI_BASE (0xb0000800) +#define BCM_6368_HSSPI_BASE (0xdeadbeef) #define BCM_6368_UDC0_BASE (0xdeadbeef) #define BCM_6368_USBDMA_BASE (0xb0004800) #define BCM_6368_OHCI0_BASE (0xb0001600) @@ -604,6 +612,7 @@ extern const unsigned long *bcm63xx_regs_base; __GEN_RSET_BASE(__cpu, UART1) \ __GEN_RSET_BASE(__cpu, GPIO) \ __GEN_RSET_BASE(__cpu, SPI) \ + __GEN_RSET_BASE(__cpu, HSSPI) \ __GEN_RSET_BASE(__cpu, UDC0) \ __GEN_RSET_BASE(__cpu, OHCI0) \ __GEN_RSET_BASE(__cpu, OHCI_PRIV) \ @@ -647,6 +656,7 @@ extern const unsigned long *bcm63xx_regs_base; [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \ [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \ [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \ + [RSET_HSSPI] = BCM_## __cpu ##_HSSPI_BASE, \ [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \ [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \ [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \ @@ -727,6 +737,7 @@ enum bcm63xx_irq { IRQ_ENET0, IRQ_ENET1, IRQ_ENET_PHY, + IRQ_HSSPI, IRQ_OHCI0, IRQ_EHCI0, IRQ_USBD, @@ -815,6 +826,7 @@ enum bcm63xx_irq { #define BCM_6328_ENET0_IRQ 0 #define BCM_6328_ENET1_IRQ 0 #define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12) +#define BCM_6328_HSSPI_IRQ (IRQ_INTERNAL_BASE + 29) #define BCM_6328_OHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 9) #define BCM_6328_EHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 10) #define BCM_6328_USBD_IRQ (IRQ_INTERNAL_BASE + 4) @@ -860,6 +872,7 @@ enum bcm63xx_irq { #define BCM_6338_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) #define BCM_6338_ENET1_IRQ 0 #define BCM_6338_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_6338_HSSPI_IRQ 0 #define BCM_6338_OHCI0_IRQ 0 #define BCM_6338_EHCI0_IRQ 0 #define BCM_6338_USBD_IRQ 0 @@ -898,6 +911,7 @@ enum bcm63xx_irq { #define BCM_6345_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) #define BCM_6345_ENET1_IRQ 0 #define BCM_6345_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12) +#define BCM_6345_HSSPI_IRQ 0 #define BCM_6345_OHCI0_IRQ 0 #define BCM_6345_EHCI0_IRQ 0 #define BCM_6345_USBD_IRQ 0 @@ -936,6 +950,7 @@ enum bcm63xx_irq { #define BCM_6348_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) #define BCM_6348_ENET1_IRQ (IRQ_INTERNAL_BASE + 7) #define BCM_6348_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_6348_HSSPI_IRQ 0 #define BCM_6348_OHCI0_IRQ (IRQ_INTERNAL_BASE + 12) #define BCM_6348_EHCI0_IRQ 0 #define BCM_6348_USBD_IRQ 0 @@ -974,6 +989,7 @@ enum bcm63xx_irq { #define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) #define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6) #define BCM_6358_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_6358_HSSPI_IRQ 0 #define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5) #define BCM_6358_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10) #define BCM_6358_USBD_IRQ 0 @@ -1086,6 +1102,7 @@ enum bcm63xx_irq { #define BCM_6368_ENET0_IRQ 0 #define BCM_6368_ENET1_IRQ 0 #define BCM_6368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 15) +#define BCM_6368_HSSPI_IRQ 0 #define BCM_6368_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5) #define BCM_6368_EHCI0_IRQ (IRQ_INTERNAL_BASE + 7) #define BCM_6368_USBD_IRQ (IRQ_INTERNAL_BASE + 8) @@ -1133,6 +1150,7 @@ extern const int *bcm63xx_irqs; [IRQ_ENET0] = BCM_## __cpu ##_ENET0_IRQ, \ [IRQ_ENET1] = BCM_## __cpu ##_ENET1_IRQ, \ [IRQ_ENET_PHY] = BCM_## __cpu ##_ENET_PHY_IRQ, \ + [IRQ_HSSPI] = BCM_## __cpu ##_HSSPI_IRQ, \ [IRQ_OHCI0] = BCM_## __cpu ##_OHCI0_IRQ, \ [IRQ_EHCI0] = BCM_## __cpu ##_EHCI0_IRQ, \ [IRQ_USBD] = BCM_## __cpu ##_USBD_IRQ, \ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h new file mode 100644 index 000000000000..1b1acafb3d79 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h @@ -0,0 +1,8 @@ +#ifndef BCM63XX_DEV_HSSPI_H +#define BCM63XX_DEV_HSSPI_H + +#include <linux/types.h> + +int bcm63xx_hsspi_register(void); + +#endif /* BCM63XX_DEV_HSSPI_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 9875db31d883..ab427f8814e6 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -463,126 +463,6 @@ #define WDT_SOFTRESET_REG 0xc /************************************************************************* - * _REG relative to RSET_UARTx - *************************************************************************/ - -/* UART Control Register */ -#define UART_CTL_REG 0x0 -#define UART_CTL_RXTMOUTCNT_SHIFT 0 -#define UART_CTL_RXTMOUTCNT_MASK (0x1f << UART_CTL_RXTMOUTCNT_SHIFT) -#define UART_CTL_RSTTXDN_SHIFT 5 -#define UART_CTL_RSTTXDN_MASK (1 << UART_CTL_RSTTXDN_SHIFT) -#define UART_CTL_RSTRXFIFO_SHIFT 6 -#define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT) -#define UART_CTL_RSTTXFIFO_SHIFT 7 -#define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT) -#define UART_CTL_STOPBITS_SHIFT 8 -#define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT) -#define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT) -#define UART_CTL_STOPBITS_2 (0xf << UART_CTL_STOPBITS_SHIFT) -#define UART_CTL_BITSPERSYM_SHIFT 12 -#define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT) -#define UART_CTL_XMITBRK_SHIFT 14 -#define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT) -#define UART_CTL_RSVD_SHIFT 15 -#define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT) -#define UART_CTL_RXPAREVEN_SHIFT 16 -#define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT) -#define UART_CTL_RXPAREN_SHIFT 17 -#define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT) -#define UART_CTL_TXPAREVEN_SHIFT 18 -#define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT) -#define UART_CTL_TXPAREN_SHIFT 18 -#define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT) -#define UART_CTL_LOOPBACK_SHIFT 20 -#define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT) -#define UART_CTL_RXEN_SHIFT 21 -#define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT) -#define UART_CTL_TXEN_SHIFT 22 -#define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT) -#define UART_CTL_BRGEN_SHIFT 23 -#define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT) - -/* UART Baudword register */ -#define UART_BAUD_REG 0x4 - -/* UART Misc Control register */ -#define UART_MCTL_REG 0x8 -#define UART_MCTL_DTR_SHIFT 0 -#define UART_MCTL_DTR_MASK (1 << UART_MCTL_DTR_SHIFT) -#define UART_MCTL_RTS_SHIFT 1 -#define UART_MCTL_RTS_MASK (1 << UART_MCTL_RTS_SHIFT) -#define UART_MCTL_RXFIFOTHRESH_SHIFT 8 -#define UART_MCTL_RXFIFOTHRESH_MASK (0xf << UART_MCTL_RXFIFOTHRESH_SHIFT) -#define UART_MCTL_TXFIFOTHRESH_SHIFT 12 -#define UART_MCTL_TXFIFOTHRESH_MASK (0xf << UART_MCTL_TXFIFOTHRESH_SHIFT) -#define UART_MCTL_RXFIFOFILL_SHIFT 16 -#define UART_MCTL_RXFIFOFILL_MASK (0x1f << UART_MCTL_RXFIFOFILL_SHIFT) -#define UART_MCTL_TXFIFOFILL_SHIFT 24 -#define UART_MCTL_TXFIFOFILL_MASK (0x1f << UART_MCTL_TXFIFOFILL_SHIFT) - -/* UART External Input Configuration register */ -#define UART_EXTINP_REG 0xc -#define UART_EXTINP_RI_SHIFT 0 -#define UART_EXTINP_RI_MASK (1 << UART_EXTINP_RI_SHIFT) -#define UART_EXTINP_CTS_SHIFT 1 -#define UART_EXTINP_CTS_MASK (1 << UART_EXTINP_CTS_SHIFT) -#define UART_EXTINP_DCD_SHIFT 2 -#define UART_EXTINP_DCD_MASK (1 << UART_EXTINP_DCD_SHIFT) -#define UART_EXTINP_DSR_SHIFT 3 -#define UART_EXTINP_DSR_MASK (1 << UART_EXTINP_DSR_SHIFT) -#define UART_EXTINP_IRSTAT(x) (1 << (x + 4)) -#define UART_EXTINP_IRMASK(x) (1 << (x + 8)) -#define UART_EXTINP_IR_RI 0 -#define UART_EXTINP_IR_CTS 1 -#define UART_EXTINP_IR_DCD 2 -#define UART_EXTINP_IR_DSR 3 -#define UART_EXTINP_RI_NOSENSE_SHIFT 16 -#define UART_EXTINP_RI_NOSENSE_MASK (1 << UART_EXTINP_RI_NOSENSE_SHIFT) -#define UART_EXTINP_CTS_NOSENSE_SHIFT 17 -#define UART_EXTINP_CTS_NOSENSE_MASK (1 << UART_EXTINP_CTS_NOSENSE_SHIFT) -#define UART_EXTINP_DCD_NOSENSE_SHIFT 18 -#define UART_EXTINP_DCD_NOSENSE_MASK (1 << UART_EXTINP_DCD_NOSENSE_SHIFT) -#define UART_EXTINP_DSR_NOSENSE_SHIFT 19 -#define UART_EXTINP_DSR_NOSENSE_MASK (1 << UART_EXTINP_DSR_NOSENSE_SHIFT) - -/* UART Interrupt register */ -#define UART_IR_REG 0x10 -#define UART_IR_MASK(x) (1 << (x + 16)) -#define UART_IR_STAT(x) (1 << (x)) -#define UART_IR_EXTIP 0 -#define UART_IR_TXUNDER 1 -#define UART_IR_TXOVER 2 -#define UART_IR_TXTRESH 3 -#define UART_IR_TXRDLATCH 4 -#define UART_IR_TXEMPTY 5 -#define UART_IR_RXUNDER 6 -#define UART_IR_RXOVER 7 -#define UART_IR_RXTIMEOUT 8 -#define UART_IR_RXFULL 9 -#define UART_IR_RXTHRESH 10 -#define UART_IR_RXNOTEMPTY 11 -#define UART_IR_RXFRAMEERR 12 -#define UART_IR_RXPARERR 13 -#define UART_IR_RXBRK 14 -#define UART_IR_TXDONE 15 - -/* UART Fifo register */ -#define UART_FIFO_REG 0x14 -#define UART_FIFO_VALID_SHIFT 0 -#define UART_FIFO_VALID_MASK 0xff -#define UART_FIFO_FRAMEERR_SHIFT 8 -#define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT) -#define UART_FIFO_PARERR_SHIFT 9 -#define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT) -#define UART_FIFO_BRKDET_SHIFT 10 -#define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT) -#define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | \ - UART_FIFO_PARERR_MASK | \ - UART_FIFO_BRKDET_MASK) - - -/************************************************************************* * _REG relative to RSET_GPIO *************************************************************************/ diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h index a9e8f6b62b0b..7629c35986f7 100644 --- a/arch/mips/include/asm/mach-generic/dma-coherence.h +++ b/arch/mips/include/asm/mach-generic/dma-coherence.h @@ -49,11 +49,7 @@ static inline int plat_dma_supported(struct device *dev, u64 mask) static inline int plat_device_is_coherent(struct device *dev) { -#ifdef CONFIG_DMA_COHERENT - return 1; -#else return coherentio; -#endif } #ifdef CONFIG_SWIOTLB diff --git a/arch/mips/include/asm/mach-generic/floppy.h b/arch/mips/include/asm/mach-generic/floppy.h index 5b5cd689a2f7..e2561d99a3fe 100644 --- a/arch/mips/include/asm/mach-generic/floppy.h +++ b/arch/mips/include/asm/mach-generic/floppy.h @@ -9,7 +9,6 @@ #define __ASM_MACH_GENERIC_FLOPPY_H #include <linux/delay.h> -#include <linux/init.h> #include <linux/ioport.h> #include <linux/sched.h> #include <linux/linkage.h> diff --git a/arch/mips/include/asm/mach-generic/ide.h b/arch/mips/include/asm/mach-generic/ide.h index affa66f5c2da..4ae5fbcb15a5 100644 --- a/arch/mips/include/asm/mach-generic/ide.h +++ b/arch/mips/include/asm/mach-generic/ide.h @@ -23,7 +23,7 @@ static inline void __ide_flush_prologue(void) { #ifdef CONFIG_SMP - if (cpu_has_dc_aliases) + if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) preempt_disable(); #endif } @@ -31,14 +31,14 @@ static inline void __ide_flush_prologue(void) static inline void __ide_flush_epilogue(void) { #ifdef CONFIG_SMP - if (cpu_has_dc_aliases) + if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) preempt_enable(); #endif } static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size) { - if (cpu_has_dc_aliases) { + if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) { unsigned long end = addr + size; while (addr < end) { diff --git a/arch/mips/include/asm/mach-jazz/floppy.h b/arch/mips/include/asm/mach-jazz/floppy.h index 62aa1e287fba..4b86c88a03b7 100644 --- a/arch/mips/include/asm/mach-jazz/floppy.h +++ b/arch/mips/include/asm/mach-jazz/floppy.h @@ -9,7 +9,6 @@ #define __ASM_MACH_JAZZ_FLOPPY_H #include <linux/delay.h> -#include <linux/init.h> #include <linux/linkage.h> #include <linux/types.h> #include <linux/mm.h> diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h index 05988c2d6565..069b43a9da6f 100644 --- a/arch/mips/include/asm/mach-jz4740/platform.h +++ b/arch/mips/include/asm/mach-jz4740/platform.h @@ -21,6 +21,7 @@ extern struct platform_device jz4740_usb_ohci_device; extern struct platform_device jz4740_udc_device; +extern struct platform_device jz4740_udc_xceiv_device; extern struct platform_device jz4740_mmc_device; extern struct platform_device jz4740_rtc_device; extern struct platform_device jz4740_i2c_device; diff --git a/arch/mips/include/asm/mach-netlogic/irq.h b/arch/mips/include/asm/mach-netlogic/irq.h index 868ed8a2ed5c..c0dbd530cca6 100644 --- a/arch/mips/include/asm/mach-netlogic/irq.h +++ b/arch/mips/include/asm/mach-netlogic/irq.h @@ -9,7 +9,8 @@ #define __ASM_NETLOGIC_IRQ_H #include <asm/mach-netlogic/multi-node.h> -#define NR_IRQS (64 * NLM_NR_NODES) +#define NLM_IRQS_PER_NODE 1024 +#define NR_IRQS (NLM_IRQS_PER_NODE * NLM_NR_NODES) #define MIPS_CPU_IRQ_BASE 0 diff --git a/arch/mips/include/asm/mach-netlogic/multi-node.h b/arch/mips/include/asm/mach-netlogic/multi-node.h index d62fc773f4d7..9ed8dacdc37c 100644 --- a/arch/mips/include/asm/mach-netlogic/multi-node.h +++ b/arch/mips/include/asm/mach-netlogic/multi-node.h @@ -47,8 +47,37 @@ #endif #endif -#define NLM_CORES_PER_NODE 8 #define NLM_THREADS_PER_CORE 4 -#define NLM_CPUS_PER_NODE (NLM_CORES_PER_NODE * NLM_THREADS_PER_CORE) +#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 */ + unsigned long ebase; /* not used now */ + uint64_t irqmask; /* EIMR for the node */ + uint64_t sysbase; /* only for XLP - sys block base */ + uint64_t picbase; /* PIC block base */ + spinlock_t piclock; /* lock for PIC access */ + cpumask_t cpumask; /* logical cpu mask for node */ + unsigned int socbus; +}; + +extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; +#define nlm_get_node(i) (&nlm_nodes[i]) +#define nlm_node_present(n) ((n) >= 0 && (n) < NLM_NR_NODES && \ + nlm_get_node(n)->coremask != 0) +#ifdef CONFIG_CPU_XLR +#define nlm_current_node() (&nlm_nodes[0]) +#else +#define nlm_current_node() (&nlm_nodes[nlm_nodeid()]) +#endif +void nlm_node_init(int node); #endif diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h new file mode 100644 index 000000000000..0da99fa11c38 --- /dev/null +++ b/arch/mips/include/asm/mach-netlogic/topology.h @@ -0,0 +1,20 @@ +/* + * 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> + +#define topology_physical_package_id(cpu) cpu_to_node(cpu) +#define topology_core_id(cpu) (cpu_logical_map(cpu) / NLM_THREADS_PER_CORE) +#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu]) +#define topology_core_cpumask(cpu) cpumask_of_node(cpu_to_node(cpu)) + +#include <asm-generic/topology.h> + +#endif /* _ASM_MACH_NETLOGIC_TOPOLOGY_H */ diff --git a/arch/mips/include/asm/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h index e33227998713..836e2ede24de 100644 --- a/arch/mips/include/asm/mips-boards/piix4.h +++ b/arch/mips/include/asm/mips-boards/piix4.h @@ -26,6 +26,10 @@ #define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE (1 << 7) #define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK 0xf #define PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX 16 +/* SERIRQ Control */ +#define PIIX4_FUNC0_SERIRQC 0x64 +#define PIIX4_FUNC0_SERIRQC_EN (1 << 7) +#define PIIX4_FUNC0_SERIRQC_CONT (1 << 6) /* Top Of Memory */ #define PIIX4_FUNC0_TOM 0x69 #define PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK 0xf0 @@ -34,6 +38,9 @@ #define PIIX4_FUNC0_DLC_USBPR_EN (1 << 2) #define PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN (1 << 1) #define PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN (1 << 0) +/* General Configuration */ +#define PIIX4_FUNC0_GENCFG 0xb0 +#define PIIX4_FUNC0_GENCFG_SERIRQ (1 << 16) /* IDE Timing */ #define PIIX4_FUNC1_IDETIM_PRIMARY_LO 0x40 diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index e0331414c7d6..bbc3dd4294bc 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -14,6 +14,7 @@ #define _ASM_MIPSREGS_H #include <linux/linkage.h> +#include <linux/types.h> #include <asm/hazards.h> #include <asm/war.h> @@ -573,7 +574,9 @@ #define MIPS_CONF1_IA (_ULCAST_(7) << 16) #define MIPS_CONF1_IL (_ULCAST_(7) << 19) #define MIPS_CONF1_IS (_ULCAST_(7) << 22) -#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) +#define MIPS_CONF1_TLBS_SHIFT (25) +#define MIPS_CONF1_TLBS_SIZE (6) +#define MIPS_CONF1_TLBS (_ULCAST_(63) << MIPS_CONF1_TLBS_SHIFT) #define MIPS_CONF2_SA (_ULCAST_(15)<< 0) #define MIPS_CONF2_SL (_ULCAST_(15)<< 4) @@ -587,21 +590,53 @@ #define MIPS_CONF3_TL (_ULCAST_(1) << 0) #define MIPS_CONF3_SM (_ULCAST_(1) << 1) #define MIPS_CONF3_MT (_ULCAST_(1) << 2) +#define MIPS_CONF3_CDMM (_ULCAST_(1) << 3) #define MIPS_CONF3_SP (_ULCAST_(1) << 4) #define MIPS_CONF3_VINT (_ULCAST_(1) << 5) #define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) #define MIPS_CONF3_LPA (_ULCAST_(1) << 7) +#define MIPS_CONF3_ITL (_ULCAST_(1) << 8) +#define MIPS_CONF3_CTXTC (_ULCAST_(1) << 9) #define MIPS_CONF3_DSP (_ULCAST_(1) << 10) #define MIPS_CONF3_DSP2P (_ULCAST_(1) << 11) #define MIPS_CONF3_RXI (_ULCAST_(1) << 12) #define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) #define MIPS_CONF3_ISA (_ULCAST_(3) << 14) #define MIPS_CONF3_ISA_OE (_ULCAST_(1) << 16) +#define MIPS_CONF3_MCU (_ULCAST_(1) << 17) +#define MIPS_CONF3_MMAR (_ULCAST_(7) << 18) +#define MIPS_CONF3_IPLW (_ULCAST_(3) << 21) #define MIPS_CONF3_VZ (_ULCAST_(1) << 23) - +#define MIPS_CONF3_PW (_ULCAST_(1) << 24) +#define MIPS_CONF3_SC (_ULCAST_(1) << 25) +#define MIPS_CONF3_BI (_ULCAST_(1) << 26) +#define MIPS_CONF3_BP (_ULCAST_(1) << 27) +#define MIPS_CONF3_MSA (_ULCAST_(1) << 28) +#define MIPS_CONF3_CMGCR (_ULCAST_(1) << 29) +#define MIPS_CONF3_BPG (_ULCAST_(1) << 30) + +#define MIPS_CONF4_MMUSIZEEXT_SHIFT (0) #define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0) +#define MIPS_CONF4_FTLBSETS_SHIFT (0) +#define MIPS_CONF4_FTLBSETS_SHIFT (0) +#define MIPS_CONF4_FTLBSETS (_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT) +#define MIPS_CONF4_FTLBWAYS_SHIFT (4) +#define MIPS_CONF4_FTLBWAYS (_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT) +#define MIPS_CONF4_FTLBPAGESIZE_SHIFT (8) +/* bits 10:8 in FTLB-only configurations */ +#define MIPS_CONF4_FTLBPAGESIZE (_ULCAST_(7) << MIPS_CONF4_FTLBPAGESIZE_SHIFT) +/* bits 12:8 in VTLB-FTLB only configurations */ +#define MIPS_CONF4_VFTLBPAGESIZE (_ULCAST_(31) << MIPS_CONF4_FTLBPAGESIZE_SHIFT) #define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14) #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) +#define MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT (_ULCAST_(2) << 14) +#define MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT (_ULCAST_(3) << 14) +#define MIPS_CONF4_KSCREXIST (_ULCAST_(255) << 16) +#define MIPS_CONF4_VTLBSIZEEXT_SHIFT (24) +#define MIPS_CONF4_VTLBSIZEEXT (_ULCAST_(15) << MIPS_CONF4_VTLBSIZEEXT_SHIFT) +#define MIPS_CONF4_AE (_ULCAST_(1) << 28) +#define MIPS_CONF4_IE (_ULCAST_(3) << 29) +#define MIPS_CONF4_TLBINV (_ULCAST_(2) << 29) #define MIPS_CONF5_NF (_ULCAST_(1) << 0) #define MIPS_CONF5_UFR (_ULCAST_(1) << 2) @@ -611,11 +646,15 @@ #define MIPS_CONF5_K (_ULCAST_(1) << 30) #define MIPS_CONF6_SYND (_ULCAST_(1) << 13) +/* proAptiv FTLB on/off bit */ +#define MIPS_CONF6_FTLBEN (_ULCAST_(1) << 15) #define MIPS_CONF7_WII (_ULCAST_(1) << 31) #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) +/* EntryHI bit definition */ +#define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10) /* * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. @@ -628,6 +667,26 @@ #define MIPS_FPIR_L (_ULCAST_(1) << 21) #define MIPS_FPIR_F64 (_ULCAST_(1) << 22) +/* + * Bits in the MIPS32 Memory Segmentation registers. + */ +#define MIPS_SEGCFG_PA_SHIFT 9 +#define MIPS_SEGCFG_PA (_ULCAST_(127) << MIPS_SEGCFG_PA_SHIFT) +#define MIPS_SEGCFG_AM_SHIFT 4 +#define MIPS_SEGCFG_AM (_ULCAST_(7) << MIPS_SEGCFG_AM_SHIFT) +#define MIPS_SEGCFG_EU_SHIFT 3 +#define MIPS_SEGCFG_EU (_ULCAST_(1) << MIPS_SEGCFG_EU_SHIFT) +#define MIPS_SEGCFG_C_SHIFT 0 +#define MIPS_SEGCFG_C (_ULCAST_(7) << MIPS_SEGCFG_C_SHIFT) + +#define MIPS_SEGCFG_UUSK _ULCAST_(7) +#define MIPS_SEGCFG_USK _ULCAST_(5) +#define MIPS_SEGCFG_MUSUK _ULCAST_(4) +#define MIPS_SEGCFG_MUSK _ULCAST_(3) +#define MIPS_SEGCFG_MSK _ULCAST_(2) +#define MIPS_SEGCFG_MK _ULCAST_(1) +#define MIPS_SEGCFG_UK _ULCAST_(0) + #ifndef __ASSEMBLY__ /* @@ -649,6 +708,19 @@ static inline int mm_insn_16bit(u16 insn) } /* + * TLB Invalidate Flush + */ +static inline void tlbinvf(void) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + ".word 0x42000004\n\t" /* tlbinvf */ + ".set pop"); +} + + +/* * Functions to access the R10000 performance counters. These are basically * mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit * performance counter number encoded into bits 1 ... 5 of the instruction. @@ -1102,6 +1174,15 @@ do { \ #define read_c0_ebase() __read_32bit_c0_register($15, 1) #define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) +/* MIPSR3 */ +#define read_c0_segctl0() __read_32bit_c0_register($5, 2) +#define write_c0_segctl0(val) __write_32bit_c0_register($5, 2, val) + +#define read_c0_segctl1() __read_32bit_c0_register($5, 3) +#define write_c0_segctl1(val) __write_32bit_c0_register($5, 3, val) + +#define read_c0_segctl2() __read_32bit_c0_register($5, 4) +#define write_c0_segctl2(val) __write_32bit_c0_register($5, 4, val) /* Cavium OCTEON (cnMIPS) */ #define read_c0_cvmcount() __read_ulong_c0_register($9, 6) diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index bb68c3398c80..c281f03eb312 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -84,7 +84,6 @@ nlm_set_nmi_handler(void *handler) */ void nlm_init_boot_cpu(void); unsigned int nlm_get_cpu_frequency(void); -void nlm_node_init(int node); extern struct plat_smp_ops nlm_smp_ops; extern char nlm_reset_entry[], nlm_reset_entry_end[]; @@ -94,26 +93,16 @@ extern struct dma_map_ops nlm_swiotlb_dma_ops; extern unsigned int nlm_threads_per_core; extern cpumask_t nlm_cpumask; -struct nlm_soc_info { - unsigned long coremask; /* cores enabled on the soc */ - unsigned long ebase; - uint64_t irqmask; - uint64_t sysbase; /* only for XLP */ - uint64_t picbase; - spinlock_t piclock; -}; - -#define nlm_get_node(i) (&nlm_nodes[i]) -#ifdef CONFIG_CPU_XLR -#define nlm_current_node() (&nlm_nodes[0]) -#else -#define nlm_current_node() (&nlm_nodes[nlm_nodeid()]) -#endif - struct irq_data; uint64_t nlm_pci_irqmask(int node); +void nlm_setup_pic_irq(int node, int picirq, int irq, int irt); void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *)); +#ifdef CONFIG_PCI_MSI +void nlm_dispatch_msi(int node, int lirq); +void nlm_dispatch_msix(int node, int msixirq); +#endif + /* * The NR_IRQs is divided between nodes, each of them has a separate irq space */ @@ -122,7 +111,6 @@ static inline int nlm_irq_to_xirq(int node, int irq) return node * NR_IRQS / NLM_NR_NODES + irq; } -extern struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; extern int nlm_cpu_ready[]; #endif #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 f299d31d7c1a..de9aada6f4c1 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -146,7 +146,12 @@ static inline int hard_smp_processor_id(void) static inline int nlm_nodeid(void) { - return (__read_32bit_c0_register($15, 1) >> 5) & 0x3; + uint32_t prid = read_c0_prid(); + + if ((prid & 0xff00) == PRID_IMP_NETLOGIC_XLP9XX) + return (__read_32bit_c0_register($15, 1) >> 7) & 0x7; + else + return (__read_32bit_c0_register($15, 1) >> 5) & 0x3; } static inline unsigned int nlm_core_id(void) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h index 4e8eacb9588a..3067f983495d 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h @@ -69,44 +69,9 @@ #define BRIDGE_FLASH_LIMIT3 0x13 #define BRIDGE_DRAM_BAR(i) (0x14 + (i)) -#define BRIDGE_DRAM_BAR0 0x14 -#define BRIDGE_DRAM_BAR1 0x15 -#define BRIDGE_DRAM_BAR2 0x16 -#define BRIDGE_DRAM_BAR3 0x17 -#define BRIDGE_DRAM_BAR4 0x18 -#define BRIDGE_DRAM_BAR5 0x19 -#define BRIDGE_DRAM_BAR6 0x1a -#define BRIDGE_DRAM_BAR7 0x1b - #define BRIDGE_DRAM_LIMIT(i) (0x1c + (i)) -#define BRIDGE_DRAM_LIMIT0 0x1c -#define BRIDGE_DRAM_LIMIT1 0x1d -#define BRIDGE_DRAM_LIMIT2 0x1e -#define BRIDGE_DRAM_LIMIT3 0x1f -#define BRIDGE_DRAM_LIMIT4 0x20 -#define BRIDGE_DRAM_LIMIT5 0x21 -#define BRIDGE_DRAM_LIMIT6 0x22 -#define BRIDGE_DRAM_LIMIT7 0x23 - #define BRIDGE_DRAM_NODE_TRANSLN(i) (0x24 + (i)) -#define BRIDGE_DRAM_NODE_TRANSLN0 0x24 -#define BRIDGE_DRAM_NODE_TRANSLN1 0x25 -#define BRIDGE_DRAM_NODE_TRANSLN2 0x26 -#define BRIDGE_DRAM_NODE_TRANSLN3 0x27 -#define BRIDGE_DRAM_NODE_TRANSLN4 0x28 -#define BRIDGE_DRAM_NODE_TRANSLN5 0x29 -#define BRIDGE_DRAM_NODE_TRANSLN6 0x2a -#define BRIDGE_DRAM_NODE_TRANSLN7 0x2b - #define BRIDGE_DRAM_CHNL_TRANSLN(i) (0x2c + (i)) -#define BRIDGE_DRAM_CHNL_TRANSLN0 0x2c -#define BRIDGE_DRAM_CHNL_TRANSLN1 0x2d -#define BRIDGE_DRAM_CHNL_TRANSLN2 0x2e -#define BRIDGE_DRAM_CHNL_TRANSLN3 0x2f -#define BRIDGE_DRAM_CHNL_TRANSLN4 0x30 -#define BRIDGE_DRAM_CHNL_TRANSLN5 0x31 -#define BRIDGE_DRAM_CHNL_TRANSLN6 0x32 -#define BRIDGE_DRAM_CHNL_TRANSLN7 0x33 #define BRIDGE_PCIEMEM_BASE0 0x34 #define BRIDGE_PCIEMEM_BASE1 0x35 @@ -178,12 +143,42 @@ #define BRIDGE_GIO_WEIGHT 0x2cb #define BRIDGE_FLASH_WEIGHT 0x2cc +/* FIXME verify */ +#define BRIDGE_9XX_FLASH_BAR(i) (0x11 + (i)) +#define BRIDGE_9XX_FLASH_BAR_LIMIT(i) (0x15 + (i)) + +#define BRIDGE_9XX_DRAM_BAR(i) (0x19 + (i)) +#define BRIDGE_9XX_DRAM_LIMIT(i) (0x29 + (i)) +#define BRIDGE_9XX_DRAM_NODE_TRANSLN(i) (0x39 + (i)) +#define BRIDGE_9XX_DRAM_CHNL_TRANSLN(i) (0x49 + (i)) + +#define BRIDGE_9XX_ADDRESS_ERROR0 0x9d +#define BRIDGE_9XX_ADDRESS_ERROR1 0x9e +#define BRIDGE_9XX_ADDRESS_ERROR2 0x9f + +#define BRIDGE_9XX_PCIEMEM_BASE0 0x59 +#define BRIDGE_9XX_PCIEMEM_BASE1 0x5a +#define BRIDGE_9XX_PCIEMEM_BASE2 0x5b +#define BRIDGE_9XX_PCIEMEM_BASE3 0x5c +#define BRIDGE_9XX_PCIEMEM_LIMIT0 0x5d +#define BRIDGE_9XX_PCIEMEM_LIMIT1 0x5e +#define BRIDGE_9XX_PCIEMEM_LIMIT2 0x5f +#define BRIDGE_9XX_PCIEMEM_LIMIT3 0x60 +#define BRIDGE_9XX_PCIEIO_BASE0 0x61 +#define BRIDGE_9XX_PCIEIO_BASE1 0x62 +#define BRIDGE_9XX_PCIEIO_BASE2 0x63 +#define BRIDGE_9XX_PCIEIO_BASE3 0x64 +#define BRIDGE_9XX_PCIEIO_LIMIT0 0x65 +#define BRIDGE_9XX_PCIEIO_LIMIT1 0x66 +#define BRIDGE_9XX_PCIEIO_LIMIT2 0x67 +#define BRIDGE_9XX_PCIEIO_LIMIT3 0x68 + #ifndef __ASSEMBLY__ #define nlm_read_bridge_reg(b, r) nlm_read_reg(b, r) #define nlm_write_bridge_reg(b, r, v) nlm_write_reg(b, r, v) -#define nlm_get_bridge_pcibase(node) \ - nlm_pcicfg_base(XLP_IO_BRIDGE_OFFSET(node)) +#define nlm_get_bridge_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \ + XLP9XX_IO_BRIDGE_OFFSET(node) : XLP_IO_BRIDGE_OFFSET(node)) #define nlm_get_bridge_regbase(node) \ (nlm_get_bridge_pcibase(node) + XLP_IO_PCI_HDRSZ) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h index 55eee77adaca..1f23dfaa7167 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h @@ -48,8 +48,10 @@ #define XLP_IO_SIZE (64 << 20) /* ECFG space size */ #define XLP_IO_PCI_HDRSZ 0x100 #define XLP_IO_DEV(node, dev) ((dev) + (node) * 8) -#define XLP_HDR_OFFSET(node, bus, dev, fn) (((bus) << 20) | \ - ((XLP_IO_DEV(node, dev)) << 15) | ((fn) << 12)) +#define XLP_IO_PCI_OFFSET(b, d, f) (((b) << 20) | ((d) << 15) | ((f) << 12)) + +#define XLP_HDR_OFFSET(node, bus, dev, fn) \ + XLP_IO_PCI_OFFSET(bus, XLP_IO_DEV(node, dev), fn) #define XLP_IO_BRIDGE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 0) /* coherent inter chip */ @@ -109,6 +111,36 @@ #define XLP_IO_MMC_OFFSET(node, slot) \ ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ) +/* Things have changed drastically in XLP 9XX */ +#define XLP9XX_HDR_OFFSET(n, d, f) \ + XLP_IO_PCI_OFFSET(xlp9xx_get_socbus(n), d, f) + +#define XLP9XX_IO_BRIDGE_OFFSET(node) XLP_IO_PCI_OFFSET(0, 0, node) +#define XLP9XX_IO_PIC_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 0) +#define XLP9XX_IO_UART_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 2) +#define XLP9XX_IO_SYS_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 0) +#define XLP9XX_IO_FUSE_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 1) +#define XLP9XX_IO_JTAG_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 4) + +#define XLP9XX_IO_PCIE_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 1, i) +#define XLP9XX_IO_PCIE0_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 0) +#define XLP9XX_IO_PCIE2_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 2) +#define XLP9XX_IO_PCIE3_OFFSET(node) XLP9XX_HDR_OFFSET(node, 1, 3) + +/* XLP9xx USB block */ +#define XLP9XX_IO_USB_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 4, i) +#define XLP9XX_IO_USB_XHCI0_OFFSET(node) XLP9XX_HDR_OFFSET(node, 4, 1) +#define XLP9XX_IO_USB_XHCI1_OFFSET(node) XLP9XX_HDR_OFFSET(node, 4, 2) + +/* XLP9XX on-chip SATA controller */ +#define XLP9XX_IO_SATA_OFFSET(node) XLP9XX_HDR_OFFSET(node, 3, 2) + +#define XLP9XX_IO_NOR_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 0) +#define XLP9XX_IO_NAND_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 1) +#define XLP9XX_IO_SPI_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 2) +/* SD flash */ +#define XLP9XX_IO_MMCSD_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3) + /* PCI config header register id's */ #define XLP_PCI_CFGREG0 0x00 #define XLP_PCI_CFGREG1 0x01 @@ -156,11 +188,23 @@ #define PCI_DEVICE_ID_NLM_MMC 0x1018 #define PCI_DEVICE_ID_NLM_XHCI 0x101d +#define PCI_DEVICE_ID_XLP9XX_SATA 0x901A +#define PCI_DEVICE_ID_XLP9XX_XHCI 0x901D + #ifndef __ASSEMBLY__ #define nlm_read_pci_reg(b, r) nlm_read_reg(b, r) #define nlm_write_pci_reg(b, r, v) nlm_write_reg(b, r, v) +static inline int xlp9xx_get_socbus(int node) +{ + uint64_t socbridge; + + if (node == 0) + return 1; + socbridge = nlm_pcicfg_base(XLP9XX_IO_BRIDGE_OFFSET(node)); + return (nlm_read_pci_reg(socbridge, 0x6) >> 8) & 0xff; +} #endif /* !__ASSEMBLY */ #endif /* __NLM_HAL_IOMAP_H__ */ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h index b559cb9f56ea..d4deb87ad069 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h @@ -52,25 +52,48 @@ #define PCIE_BYTE_SWAP_MEM_LIM 0x248 #define PCIE_BYTE_SWAP_IO_BASE 0x249 #define PCIE_BYTE_SWAP_IO_LIM 0x24A + +#define PCIE_BRIDGE_MSIX_ADDR_BASE 0x24F +#define PCIE_BRIDGE_MSIX_ADDR_LIMIT 0x250 #define PCIE_MSI_STATUS 0x25A #define PCIE_MSI_EN 0x25B +#define PCIE_MSIX_STATUS 0x25D +#define PCIE_INT_STATUS0 0x25F +#define PCIE_INT_STATUS1 0x260 #define PCIE_INT_EN0 0x261 +#define PCIE_INT_EN1 0x262 -/* PCIE_MSI_EN */ -#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF +/* XLP9XX has basic changes */ +#define PCIE_9XX_BYTE_SWAP_MEM_BASE 0x25c +#define PCIE_9XX_BYTE_SWAP_MEM_LIM 0x25d +#define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e +#define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f -/* PCIE_INT_EN0 */ -#define PCIE_MSI_INT_EN (1 << 9) +/* other */ +#define PCIE_NLINKS 4 +/* MSI addresses */ +#define MSI_ADDR_BASE 0xfffee00000ULL +#define MSI_ADDR_SZ 0x10000 +#define MSI_LINK_ADDR(n, l) (MSI_ADDR_BASE + \ + (PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ) +#define MSIX_ADDR_BASE 0xfffef00000ULL +#define MSIX_LINK_ADDR(n, l) (MSIX_ADDR_BASE + \ + (PCIE_NLINKS * (n) + (l)) * MSI_ADDR_SZ) #ifndef __ASSEMBLY__ #define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r) #define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v) -#define nlm_get_pcie_base(node, inst) \ - nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst)) -#define nlm_get_pcie_regbase(node, inst) \ - (nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ) +#define nlm_get_pcie_base(node, inst) nlm_pcicfg_base(cpu_is_xlp9xx() ? \ + XLP9XX_IO_PCIE_OFFSET(node, inst) : XLP_IO_PCIE_OFFSET(node, inst)) + +#ifdef CONFIG_PCI_MSI +void xlp_init_node_msi_irqs(int node, int link); +#else +static inline void xlp_init_node_msi_irqs(int node, int link) {} +#endif + +struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev); -int xlp_pcie_link_irt(int link); #endif #endif /* __NLM_HAL_PCIBUS_H__ */ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index 105389b79f09..f10bf3bba58f 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -150,12 +150,19 @@ #define PIC_IRT0 0x74 #define PIC_IRT(i) (PIC_IRT0 + ((i) * 2)) -#define TIMER_CYCLES_MAXVAL 0xffffffffffffffffULL +#define PIC_9XX_PENDING_0 0x6 +#define PIC_9XX_PENDING_1 0x8 +#define PIC_9XX_PENDING_2 0xa +#define PIC_9XX_PENDING_3 0xc + +#define PIC_9XX_IRT0 0x1c0 +#define PIC_9XX_IRT(i) (PIC_9XX_IRT0 + ((i) * 2)) /* * IRT Map */ #define PIC_NUM_IRTS 160 +#define PIC_9XX_NUM_IRTS 256 #define PIC_IRT_WD_0_INDEX 0 #define PIC_IRT_WD_1_INDEX 1 @@ -193,14 +200,9 @@ #define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX) #define PIC_CLOCK_TIMER 7 -#define PIC_IRQ_BASE 8 #if !defined(LOCORE) && !defined(__ASSEMBLY__) -#define PIC_IRT_FIRST_IRQ (PIC_IRQ_BASE) -#define PIC_IRT_LAST_IRQ 63 -#define PIC_IRQ_IS_IRT(irq) ((irq) >= PIC_IRT_FIRST_IRQ) - /* * Misc */ @@ -210,30 +212,26 @@ #define nlm_read_pic_reg(b, r) nlm_read_reg64(b, r) #define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v) -#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node)) +#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \ + XLP9XX_IO_PIC_OFFSET(node) : XLP_IO_PIC_OFFSET(node)) #define nlm_get_pic_regbase(node) (nlm_get_pic_pcibase(node) + XLP_IO_PCI_HDRSZ) /* We use PIC on node 0 as a timer */ #define pic_timer_freq() nlm_get_pic_frequency(0) /* IRT and h/w interrupt routines */ -static inline int -nlm_pic_read_irt(uint64_t base, int irt_index) -{ - return nlm_read_pic_reg(base, PIC_IRT(irt_index)); -} - static inline void -nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu) +nlm_9xx_pic_write_irt(uint64_t base, int irt_num, int en, int nmi, + int sch, int vec, int dt, int db, int cpu) { uint64_t val; - val = nlm_read_pic_reg(base, PIC_IRT(irt)); - /* clear cpuset and mask */ - val &= ~((0x7ull << 16) | 0xffff); - /* set DB, cpuset and cpumask */ - val |= (1 << 19) | ((cpu >> 4) << 16) | (1 << (cpu & 0xf)); - nlm_write_pic_reg(base, PIC_IRT(irt), val); + val = (((uint64_t)en & 0x1) << 22) | ((nmi & 0x1) << 23) | + ((0 /*mc*/) << 20) | ((vec & 0x3f) << 24) | + ((dt & 0x1) << 21) | (0 /*ptr*/ << 16) | + (cpu & 0x3ff); + + nlm_write_pic_reg(base, PIC_9XX_IRT(irt_num), val); } static inline void @@ -254,9 +252,13 @@ static inline void nlm_pic_write_irt_direct(uint64_t base, int irt_num, int en, int nmi, int sch, int vec, int cpu) { - nlm_pic_write_irt(base, irt_num, en, nmi, sch, vec, 1, - (cpu >> 4), /* thread group */ - 1 << (cpu & 0xf)); /* thread mask */ + if (cpu_is_xlp9xx()) + nlm_9xx_pic_write_irt(base, irt_num, en, nmi, sch, vec, + 1, 0, cpu); + else + nlm_pic_write_irt(base, irt_num, en, nmi, sch, vec, 1, + (cpu >> 4), /* thread group */ + 1 << (cpu & 0xf)); /* thread mask */ } static inline uint64_t @@ -298,8 +300,13 @@ nlm_pic_enable_irt(uint64_t base, int irt) { uint64_t reg; - reg = nlm_read_pic_reg(base, PIC_IRT(irt)); - nlm_write_pic_reg(base, PIC_IRT(irt), reg | (1u << 31)); + if (cpu_is_xlp9xx()) { + reg = nlm_read_pic_reg(base, PIC_9XX_IRT(irt)); + nlm_write_pic_reg(base, PIC_9XX_IRT(irt), reg | (1 << 22)); + } else { + reg = nlm_read_pic_reg(base, PIC_IRT(irt)); + nlm_write_pic_reg(base, PIC_IRT(irt), reg | (1u << 31)); + } } static inline void @@ -307,8 +314,15 @@ nlm_pic_disable_irt(uint64_t base, int irt) { uint64_t reg; - reg = nlm_read_pic_reg(base, PIC_IRT(irt)); - nlm_write_pic_reg(base, PIC_IRT(irt), reg & ~((uint64_t)1 << 31)); + if (cpu_is_xlp9xx()) { + reg = nlm_read_pic_reg(base, PIC_9XX_IRT(irt)); + reg &= ~((uint64_t)1 << 22); + nlm_write_pic_reg(base, PIC_9XX_IRT(irt), reg); + } else { + reg = nlm_read_pic_reg(base, PIC_IRT(irt)); + reg &= ~((uint64_t)1 << 31); + nlm_write_pic_reg(base, PIC_IRT(irt), reg); + } } static inline void @@ -316,8 +330,13 @@ nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi) { uint64_t ipi; - ipi = ((uint64_t)nmi << 31) | (irq << 20); - ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */ + if (cpu_is_xlp9xx()) + ipi = (nmi << 23) | (irq << 24) | + (0/*mcm*/ << 20) | (0/*ptr*/ << 16) | hwt; + else + ipi = ((uint64_t)nmi << 31) | (irq << 20) | + ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); + nlm_write_pic_reg(base, PIC_IPI_CTL, ipi); } diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h index fcf2833c16ca..d9b107ffca93 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h @@ -147,13 +147,29 @@ #define SYS_SYS_PLL_MEM_REQ 0x2a3 #define SYS_PLL_MEM_STAT 0x2a4 +/* Registers changed on 9XX */ +#define SYS_9XX_POWER_ON_RESET_CFG 0x00 +#define SYS_9XX_CHIP_RESET 0x01 +#define SYS_9XX_CPU_RESET 0x02 +#define SYS_9XX_CPU_NONCOHERENT_MODE 0x03 + +/* XLP 9XX fuse block registers */ +#define FUSE_9XX_DEVCFG6 0xc6 + #ifndef __ASSEMBLY__ #define nlm_read_sys_reg(b, r) nlm_read_reg(b, r) #define nlm_write_sys_reg(b, r, v) nlm_write_reg(b, r, v) -#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node)) +#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(cpu_is_xlp9xx() ? \ + XLP9XX_IO_SYS_OFFSET(node) : XLP_IO_SYS_OFFSET(node)) #define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ) +/* XLP9XX fuse block */ +#define nlm_get_fuse_pcibase(node) \ + nlm_pcicfg_base(XLP9XX_IO_FUSE_OFFSET(node)) +#define nlm_get_fuse_regbase(node) \ + (nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ) + unsigned int nlm_get_pic_frequency(int node); #endif #endif diff --git a/arch/mips/include/asm/netlogic/xlp-hal/uart.h b/arch/mips/include/asm/netlogic/xlp-hal/uart.h index 86d16e1e6072..a6c54424dd95 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/uart.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/uart.h @@ -94,7 +94,8 @@ #define nlm_read_uart_reg(b, r) nlm_read_reg(b, r) #define nlm_write_uart_reg(b, r, v) nlm_write_reg(b, r, v) #define nlm_get_uart_pcibase(node, inst) \ - nlm_pcicfg_base(XLP_IO_UART_OFFSET(node, inst)) + nlm_pcicfg_base(cpu_is_xlp9xx() ? XLP9XX_IO_UART_OFFSET(node) : \ + XLP_IO_UART_OFFSET(node, inst)) #define nlm_get_uart_regbase(node, inst) \ (nlm_get_uart_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 470f2095b346..2b0c9599ebe5 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -37,10 +37,9 @@ #define PIC_UART_0_IRQ 17 #define PIC_UART_1_IRQ 18 -#define PIC_PCIE_LINK_0_IRQ 19 -#define PIC_PCIE_LINK_1_IRQ 20 -#define PIC_PCIE_LINK_2_IRQ 21 -#define PIC_PCIE_LINK_3_IRQ 22 + +#define PIC_PCIE_LINK_LEGACY_IRQ_BASE 19 +#define PIC_PCIE_LINK_LEGACY_IRQ(i) (19 + (i)) #define PIC_EHCI_0_IRQ 23 #define PIC_EHCI_1_IRQ 24 @@ -51,6 +50,8 @@ #define PIC_2XX_XHCI_0_IRQ 23 #define PIC_2XX_XHCI_1_IRQ 24 #define PIC_2XX_XHCI_2_IRQ 25 +#define PIC_9XX_XHCI_0_IRQ 23 +#define PIC_9XX_XHCI_1_IRQ 24 #define PIC_MMC_IRQ 29 #define PIC_I2C_0_IRQ 30 @@ -58,6 +59,23 @@ #define PIC_I2C_2_IRQ 32 #define PIC_I2C_3_IRQ 33 +#define PIC_PCIE_LINK_MSI_IRQ_BASE 44 /* 44 - 47 MSI IRQ */ +#define PIC_PCIE_LINK_MSI_IRQ(i) (44 + (i)) + +/* MSI-X with second link-level dispatch */ +#define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */ +#define PIC_PCIE_MSIX_IRQ(i) (48 + (i)) + +#define NLM_MSIX_VEC_BASE 96 /* 96 - 127 - MSIX mapped */ +#define NLM_MSI_VEC_BASE 128 /* 128 -255 - MSI mapped */ + +#define NLM_PIC_INDIRECT_VEC_BASE 512 +#define NLM_GPIO_VEC_BASE 768 + +#define PIC_IRQ_BASE 8 +#define PIC_IRT_FIRST_IRQ PIC_IRQ_BASE +#define PIC_IRT_LAST_IRQ 63 + #ifndef __ASSEMBLY__ /* SMP support functions */ @@ -68,6 +86,9 @@ void xlp_mmu_init(void); void nlm_hal_init(void); int xlp_get_dram_map(int n, uint64_t *dram_map); +struct pci_dev; +int xlp_socdev_to_node(const struct pci_dev *dev); + /* Device tree related */ void xlp_early_init_devtree(void); void *xlp_dt_init(void *fdtp); @@ -76,8 +97,15 @@ static inline int cpu_is_xlpii(void) { int chip = read_c0_prid() & 0xff00; - return chip == PRID_IMP_NETLOGIC_XLP2XX; + return chip == PRID_IMP_NETLOGIC_XLP2XX || + chip == PRID_IMP_NETLOGIC_XLP9XX; } +static inline int cpu_is_xlp9xx(void) +{ + int chip = read_c0_prid() & 0xff00; + + return chip == PRID_IMP_NETLOGIC_XLP9XX; +} #endif /* !__ASSEMBLY__ */ #endif /* _ASM_NLM_XLP_H */ diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h index c1667e0c272a..ceb991ca8436 100644 --- a/arch/mips/include/asm/netlogic/xlr/xlr.h +++ b/arch/mips/include/asm/netlogic/xlr/xlr.h @@ -35,11 +35,6 @@ #ifndef _ASM_NLM_XLR_H #define _ASM_NLM_XLR_H -/* Platform UART functions */ -struct uart_port; -unsigned int nlm_xlr_uart_in(struct uart_port *, int); -void nlm_xlr_uart_out(struct uart_port *, int, int); - /* SMP helpers */ void xlr_wakeup_secondary_cpus(void); diff --git a/arch/mips/include/asm/octeon/cvmx-helper-board.h b/arch/mips/include/asm/octeon/cvmx-helper-board.h index 41785dd0ddd0..893320375aef 100644 --- a/arch/mips/include/asm/octeon/cvmx-helper-board.h +++ b/arch/mips/include/asm/octeon/cvmx-helper-board.h @@ -36,6 +36,13 @@ #include <asm/octeon/cvmx-helper.h> +enum cvmx_helper_board_usb_clock_types { + USB_CLOCK_TYPE_REF_12, + USB_CLOCK_TYPE_REF_24, + USB_CLOCK_TYPE_REF_48, + USB_CLOCK_TYPE_CRYSTAL_12, +}; + typedef enum { set_phy_link_flags_autoneg = 0x1, set_phy_link_flags_flow_control_dont_touch = 0x0 << 1, @@ -154,4 +161,6 @@ extern int __cvmx_helper_board_interface_probe(int interface, */ extern int __cvmx_helper_board_hardware_enable(int interface); +enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void); + #endif /* __CVMX_HELPER_BOARD_H__ */ diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index f6be4741f7e8..5e08bcc74897 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -11,6 +11,8 @@ #include <spaces.h> #include <linux/const.h> +#include <linux/kernel.h> +#include <asm/mipsregs.h> /* * PAGE_SHIFT determines the page size @@ -33,6 +35,29 @@ #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) +/* + * This is used for calculating the real page sizes + * for FTLB or VTLB + FTLB confugrations. + */ +static inline unsigned int page_size_ftlb(unsigned int mmuextdef) +{ + switch (mmuextdef) { + case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: + if (PAGE_SIZE == (1 << 30)) + return 5; + if (PAGE_SIZE == (1llu << 32)) + return 6; + if (PAGE_SIZE > (256 << 10)) + return 7; /* reserved */ + /* fall through */ + case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT: + return (PAGE_SHIFT - 10) / 2; + default: + panic("Invalid FTLB configuration with Conf4_mmuextdef=%d value\n", + mmuextdef >> 14); + } +} + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT #define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) #define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT) diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h index 90985b61dbd9..c1020654876e 100644 --- a/arch/mips/include/asm/rtlx.h +++ b/arch/mips/include/asm/rtlx.h @@ -1,13 +1,18 @@ /* - * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * 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) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. */ - #ifndef __ASM_RTLX_H_ #define __ASM_RTLX_H_ #include <irq.h> +#define RTLX_MODULE_NAME "rtlx" + #define LX_NODE_BASE 10 #define MIPS_CPU_RTLX_IRQ 0 @@ -15,18 +20,31 @@ #define RTLX_VERSION 2 #define RTLX_xID 0x12345600 #define RTLX_ID (RTLX_xID | RTLX_VERSION) +#define RTLX_BUFFER_SIZE 2048 #define RTLX_CHANNELS 8 #define RTLX_CHANNEL_STDIO 0 #define RTLX_CHANNEL_DBG 1 #define RTLX_CHANNEL_SYSIO 2 -extern int rtlx_open(int index, int can_sleep); -extern int rtlx_release(int index); -extern ssize_t rtlx_read(int index, void __user *buff, size_t count); -extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count); -extern unsigned int rtlx_read_poll(int index, int can_sleep); -extern unsigned int rtlx_write_poll(int index); +void rtlx_starting(int vpe); +void rtlx_stopping(int vpe); + +int rtlx_open(int index, int can_sleep); +int rtlx_release(int index); +ssize_t rtlx_read(int index, void __user *buff, size_t count); +ssize_t rtlx_write(int index, const void __user *buffer, size_t count); +unsigned int rtlx_read_poll(int index, int can_sleep); +unsigned int rtlx_write_poll(int index); + +int __init rtlx_module_init(void); +void __exit rtlx_module_exit(void); + +void _interrupt_sp(void); + +extern struct vpe_notifications rtlx_notify; +extern const struct file_operations rtlx_fops; +extern void (*aprp_hook)(void); enum rtlx_state { RTLX_STATE_UNUSED = 0, @@ -35,10 +53,15 @@ enum rtlx_state { RTLX_STATE_OPENED }; -#define RTLX_BUFFER_SIZE 2048 +extern struct chan_waitqueues { + wait_queue_head_t rt_queue; + wait_queue_head_t lx_queue; + atomic_t in_open; + struct mutex mutex; +} channel_wqs[RTLX_CHANNELS]; /* each channel supports read and write. - linux (vpe0) reads lx_buffer and writes rt_buffer + linux (vpe0) reads lx_buffer and writes rt_buffer SP (vpe1) reads rt_buffer and writes lx_buffer */ struct rtlx_channel { @@ -55,11 +78,11 @@ struct rtlx_channel { char *lx_buffer; }; -struct rtlx_info { +extern struct rtlx_info { unsigned long id; enum rtlx_state state; + int ap_int_pending; /* Status of 0 or 1 for CONFIG_MIPS_CMP only */ struct rtlx_channel channel[RTLX_CHANNELS]; -}; - +} *rtlx; #endif /* __ASM_RTLX_H_ */ diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index eb0af15ac656..278d45a09728 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -19,11 +19,19 @@ struct task_struct; -/* - * switch_to(n) should switch tasks to task nr n, first - * checking that n isn't the current task, in which case it does nothing. +/** + * resume - resume execution of a task + * @prev: The task previously executed. + * @next: The task to begin executing. + * @next_ti: task_thread_info(next). + * @usedfpu: Non-zero if prev's FP context should be saved. + * + * This function is used whilst scheduling to save the context of prev & load + * the context of next. Returns prev. */ -extern asmlinkage void *resume(void *last, void *next, void *next_ti, u32 __usedfpu); +extern asmlinkage struct task_struct *resume(struct task_struct *prev, + struct task_struct *next, struct thread_info *next_ti, + u32 usedfpu); extern unsigned int ll_bit; extern struct task_struct *ll_task; diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 81c89132c59d..33e8dbfc1b63 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -29,7 +29,7 @@ static inline long syscall_get_nr(struct task_struct *task, static inline unsigned long mips_get_syscall_arg(unsigned long *arg, struct task_struct *task, struct pt_regs *regs, unsigned int n) { - unsigned long usp = regs->regs[29]; + unsigned long usp __maybe_unused = regs->regs[29]; switch (n) { case 0: case 1: case 2: case 3: diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 4f58ef6d0eed..24846f9053fe 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -110,11 +110,12 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NOHZ 19 /* in adaptive nohz mode */ #define TIF_FIXADE 20 /* Fix address errors in software */ #define TIF_LOGADE 21 /* Log address errors to syslog */ -#define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ +#define TIF_32BIT_REGS 22 /* 32-bit general purpose registers */ #define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */ #define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */ #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ #define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */ +#define TIF_32BIT_FPREGS 27 /* 32-bit floating point registers */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) @@ -131,6 +132,7 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_32BIT_ADDR (1<<TIF_32BIT_ADDR) #define _TIF_FPUBOUND (1<<TIF_FPUBOUND) #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) +#define _TIF_32BIT_FPREGS (1<<TIF_32BIT_FPREGS) #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) #define _TIF_WORK_SYSCALL_ENTRY (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \ diff --git a/arch/mips/include/asm/tlb.h b/arch/mips/include/asm/tlb.h index c67842bc8ef3..4a2349302b55 100644 --- a/arch/mips/include/asm/tlb.h +++ b/arch/mips/include/asm/tlb.h @@ -18,6 +18,10 @@ */ #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) +#define UNIQUE_ENTRYHI(idx) \ + ((CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) | \ + (cpu_has_tlbinv ? MIPS_ENTRYHI_EHINV : 0)) + #include <asm-generic/tlb.h> #endif /* __ASM_TLB_H */ diff --git a/arch/mips/include/asm/vpe.h b/arch/mips/include/asm/vpe.h index 0880fe8809b1..7849f3978fea 100644 --- a/arch/mips/include/asm/vpe.h +++ b/arch/mips/include/asm/vpe.h @@ -1,24 +1,95 @@ /* - * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. */ - #ifndef _ASM_VPE_H #define _ASM_VPE_H +#include <linux/init.h> +#include <linux/list.h> +#include <linux/smp.h> +#include <linux/spinlock.h> + +#define VPE_MODULE_NAME "vpe" +#define VPE_MODULE_MINOR 1 + +/* grab the likely amount of memory we will need. */ +#ifdef CONFIG_MIPS_VPE_LOADER_TOM +#define P_SIZE (2 * 1024 * 1024) +#else +/* add an overhead to the max kmalloc size for non-striped symbols/etc */ +#define P_SIZE (256 * 1024) +#endif + +#define MAX_VPES 16 +#define VPE_PATH_MAX 256 + +static inline int aprp_cpu_index(void) +{ +#ifdef CONFIG_MIPS_CMP + return setup_max_cpus; +#else + extern int tclimit; + return tclimit; +#endif +} + +enum vpe_state { + VPE_STATE_UNUSED = 0, + VPE_STATE_INUSE, + VPE_STATE_RUNNING +}; + +enum tc_state { + TC_STATE_UNUSED = 0, + TC_STATE_INUSE, + TC_STATE_RUNNING, + TC_STATE_DYNAMIC +}; + +struct vpe { + enum vpe_state state; + + /* (device) minor associated with this vpe */ + int minor; + + /* elfloader stuff */ + void *load_addr; + unsigned long len; + char *pbuffer; + unsigned long plen; + char cwd[VPE_PATH_MAX]; + + unsigned long __start; + + /* tc's associated with this vpe */ + struct list_head tc; + + /* The list of vpe's */ + struct list_head list; + + /* shared symbol address */ + void *shared_ptr; + + /* the list of who wants to know when something major happens */ + struct list_head notify; + + unsigned int ntcs; +}; + +struct tc { + enum tc_state state; + int index; + + struct vpe *pvpe; /* parent VPE */ + struct list_head tc; /* The list of TC's with this VPE */ + struct list_head list; /* The global list of tc's */ +}; + struct vpe_notifications { void (*start)(int vpe); void (*stop)(int vpe); @@ -26,10 +97,34 @@ struct vpe_notifications { struct list_head list; }; +struct vpe_control { + spinlock_t vpe_list_lock; + struct list_head vpe_list; /* Virtual processing elements */ + spinlock_t tc_list_lock; + struct list_head tc_list; /* Thread contexts */ +}; + +extern unsigned long physical_memsize; +extern struct vpe_control vpecontrol; +extern const struct file_operations vpe_fops; + +int vpe_notify(int index, struct vpe_notifications *notify); + +void *vpe_get_shared(int index); +char *vpe_getcwd(int index); + +struct vpe *get_vpe(int minor); +struct tc *get_tc(int index); +struct vpe *alloc_vpe(int minor); +struct tc *alloc_tc(int index); +void release_vpe(struct vpe *v); -extern int vpe_notify(int index, struct vpe_notifications *notify); +void *alloc_progmem(unsigned long len); +void release_progmem(void *ptr); -extern void *vpe_get_shared(int index); -extern char *vpe_getcwd(int index); +int __weak vpe_run(struct vpe *v); +void cleanup_tc(struct tc *tc); +int __init vpe_module_init(void); +void __exit vpe_module_exit(void); #endif /* _ASM_VPE_H */ diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index e5a676e3d3c0..b39ba25b41cc 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -98,8 +98,9 @@ enum rt_op { */ enum cop_op { mfc_op = 0x00, dmfc_op = 0x01, - cfc_op = 0x02, mtc_op = 0x04, - dmtc_op = 0x05, ctc_op = 0x06, + cfc_op = 0x02, mfhc_op = 0x03, + mtc_op = 0x04, dmtc_op = 0x05, + ctc_op = 0x06, mthc_op = 0x07, bc_op = 0x08, cop_op = 0x10, copm_op = 0x18 }; @@ -397,8 +398,10 @@ enum mm_32f_73_minor_op { mm_movt1_op = 0xa5, mm_ftruncw_op = 0xac, mm_fneg1_op = 0xad, + mm_mfhc1_op = 0xc0, mm_froundl_op = 0xcc, mm_fcvtd1_op = 0xcd, + mm_mthc1_op = 0xe0, mm_froundw_op = 0xec, mm_fcvts1_op = 0xed, }; diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 8a5ec0eedeb0..c01900e5d078 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -427,6 +427,7 @@ static struct platform_device qi_lb60_audio_device = { static struct platform_device *jz_platform_devices[] __initdata = { &jz4740_udc_device, + &jz4740_udc_xceiv_device, &jz4740_mmc_device, &jz4740_nand_device, &qi_lb60_keypad, diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index df65677f3d0b..a447101cf9f1 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -14,13 +14,14 @@ */ #include <linux/device.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/resource.h> #include <linux/dma-mapping.h> +#include <linux/usb/musb.h> + #include <asm/mach-jz4740/platform.h> #include <asm/mach-jz4740/base.h> #include <asm/mach-jz4740/irq.h> @@ -56,29 +57,35 @@ struct platform_device jz4740_usb_ohci_device = { .resource = jz4740_usb_ohci_resources, }; -/* UDC (USB gadget controller) */ -static struct resource jz4740_usb_gdt_resources[] = { - { - .start = JZ4740_UDC_BASE_ADDR, - .end = JZ4740_UDC_BASE_ADDR + 0x1000 - 1, - .flags = IORESOURCE_MEM, +/* USB Device Controller */ +struct platform_device jz4740_udc_xceiv_device = { + .name = "usb_phy_gen_xceiv", + .id = 0, +}; + +static struct resource jz4740_udc_resources[] = { + [0] = { + .start = JZ4740_UDC_BASE_ADDR, + .end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1, + .flags = IORESOURCE_MEM, }, - { - .start = JZ4740_IRQ_UDC, - .end = JZ4740_IRQ_UDC, - .flags = IORESOURCE_IRQ, + [1] = { + .start = JZ4740_IRQ_UDC, + .end = JZ4740_IRQ_UDC, + .flags = IORESOURCE_IRQ, + .name = "mc", }, }; struct platform_device jz4740_udc_device = { - .name = "jz-udc", - .id = -1, - .dev = { - .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask, + .name = "musb-jz4740", + .id = -1, + .dev = { + .dma_mask = &jz4740_udc_device.dev.coherent_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), }, - .num_resources = ARRAY_SIZE(jz4740_usb_gdt_resources), - .resource = jz4740_usb_gdt_resources, + .num_resources = ARRAY_SIZE(jz4740_udc_resources), + .resource = jz4740_udc_resources, }; /* MMC/SD controller */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 1c1b71752c84..26c6175e1379 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o obj-$(CONFIG_SYNC_R4K) += sync-r4k.o +obj-$(CONFIG_DEBUG_FS) += segment.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_MODULES) += mips_ksyms.o module.o obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o @@ -55,7 +56,11 @@ obj-$(CONFIG_MIPS_CMP) += smp-cmp.o obj-$(CONFIG_CPU_MIPSR2) += spram.o obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o +obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o +obj-$(CONFIG_MIPS_VPE_LOADER_MT) += vpe-mt.o obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o +obj-$(CONFIG_MIPS_VPE_APSP_API_CMP) += rtlx-cmp.o +obj-$(CONFIG_MIPS_VPE_APSP_API_MT) += rtlx-mt.o obj-$(CONFIG_I8259) += i8259.o obj-$(CONFIG_IRQ_CPU) += irq_cpu.o diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index 202e581e6096..7faf5f2bee25 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -28,6 +28,18 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; /* + * In order to be sure that we don't attempt to execute an O32 binary which + * requires 64 bit FP (FR=1) on a system which does not support it we refuse + * to execute any binary which has bits specified by the following macro set + * in its ELF header flags. + */ +#ifdef CONFIG_MIPS_O32_FP64_SUPPORT +# define __MIPS_O32_FP64_MUST_BE_ZERO 0 +#else +# define __MIPS_O32_FP64_MUST_BE_ZERO EF_MIPS_FP64 +#endif + +/* * This is used to ensure we don't load something for the wrong architecture. */ #define elf_check_arch(hdr) \ @@ -44,6 +56,8 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ __res = 0; \ + if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO) \ + __res = 0; \ \ __res; \ }) diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S index bd79c4f9bff4..a5bf73d22fcc 100644 --- a/arch/mips/kernel/bmips_vec.S +++ b/arch/mips/kernel/bmips_vec.S @@ -8,11 +8,11 @@ * Reset/NMI/re-entry vectors for BMIPS processors */ -#include <linux/init.h> #include <asm/asm.h> #include <asm/asmmacro.h> #include <asm/cacheops.h> +#include <asm/cpu.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> @@ -91,12 +91,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp) beqz k0, bmips_smp_entry #if defined(CONFIG_CPU_BMIPS5000) + mfc0 k0, CP0_PRID + li k1, PRID_IMP_BMIPS5000 + andi k0, 0xff00 + bne k0, k1, 1f + /* if we're not on core 0, this must be the SMP boot signal */ li k1, (3 << 25) mfc0 k0, $22 and k0, k1 bnez k0, bmips_smp_entry -#endif +1: +#endif /* CONFIG_CPU_BMIPS5000 */ #endif /* CONFIG_SMP */ /* nope, it's just a regular NMI */ @@ -139,7 +145,12 @@ bmips_smp_entry: xori k0, 0x04 mtc0 k0, CP0_CONFIG + mfc0 k0, CP0_PRID + andi k0, 0xff00 #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) + li k1, PRID_IMP_BMIPS43XX + bne k0, k1, 2f + /* initialize CPU1's local I-cache */ li k0, 0x80000000 li k1, 0x80010000 @@ -150,14 +161,21 @@ bmips_smp_entry: 1: cache Index_Store_Tag_I, 0(k0) addiu k0, 16 bne k0, k1, 1b -#elif defined(CONFIG_CPU_BMIPS5000) + + b 3f +2: +#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */ +#if defined(CONFIG_CPU_BMIPS5000) /* set exception vector base */ + li k1, PRID_IMP_BMIPS5000 + bne k0, k1, 3f + la k0, ebase lw k0, 0(k0) mtc0 k0, $15, 1 BARRIER -#endif - +#endif /* CONFIG_CPU_BMIPS5000 */ +3: /* jump back to kseg0 in case we need to remap the kseg1 area */ la k0, 1f jr k0 @@ -221,8 +239,18 @@ END(bmips_smp_int_vec) LEAF(bmips_enable_xks01) #if defined(CONFIG_XKS01) - + mfc0 t0, CP0_PRID + andi t2, t0, 0xff00 #if defined(CONFIG_CPU_BMIPS4380) + li t1, PRID_IMP_BMIPS43XX + bne t2, t1, 1f + + andi t0, 0xff + addiu t1, t0, -PRID_REV_BMIPS4380_HI + bgtz t1, 2f + addiu t0, -PRID_REV_BMIPS4380_LO + bltz t0, 2f + mfc0 t0, $22, 3 li t1, 0x1ff0 li t2, (1 << 12) | (1 << 9) @@ -231,7 +259,13 @@ LEAF(bmips_enable_xks01) or t0, t2 mtc0 t0, $22, 3 BARRIER -#elif defined(CONFIG_CPU_BMIPS5000) + b 2f +1: +#endif /* CONFIG_CPU_BMIPS4380 */ +#if defined(CONFIG_CPU_BMIPS5000) + li t1, PRID_IMP_BMIPS5000 + bne t2, t1, 2f + mfc0 t0, $22, 5 li t1, 0x01ff li t2, (1 << 8) | (1 << 5) @@ -240,12 +274,8 @@ LEAF(bmips_enable_xks01) or t0, t2 mtc0 t0, $22, 5 BARRIER -#else - -#error Missing XKS01 setup - -#endif - +#endif /* CONFIG_CPU_BMIPS5000 */ +2: #endif /* defined(CONFIG_XKS01) */ jr ra diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c814287bdf5d..530f832de02c 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -112,7 +112,7 @@ static inline unsigned long cpu_get_fpu_id(void) unsigned long tmp, fpu_id; tmp = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); fpu_id = read_32bit_cp1_register(CP1_REVISION); write_c0_status(tmp); return fpu_id; @@ -163,6 +163,25 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa) static char unknown_isa[] = KERN_ERR \ "Unsupported ISA type, c0.config0: %d."; +static void set_ftlb_enable(struct cpuinfo_mips *c, int enable) +{ + unsigned int config6; + /* + * Config6 is implementation dependent and it's currently only + * used by proAptiv + */ + if (c->cputype == CPU_PROAPTIV) { + config6 = read_c0_config6(); + if (enable) + /* Enable FTLB */ + write_c0_config6(config6 | MIPS_CONF6_FTLBEN); + else + /* Disable FTLB */ + write_c0_config6(config6 & ~MIPS_CONF6_FTLBEN); + back_to_back_c0_hazard(); + } +} + static inline unsigned int decode_config0(struct cpuinfo_mips *c) { unsigned int config0; @@ -170,8 +189,13 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c) config0 = read_c0_config(); - if (((config0 & MIPS_CONF_MT) >> 7) == 1) + /* + * Look for Standard TLB or Dual VTLB and FTLB + */ + if ((((config0 & MIPS_CONF_MT) >> 7) == 1) || + (((config0 & MIPS_CONF_MT) >> 7) == 4)) c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; switch (isa) { case 0: @@ -226,8 +250,11 @@ static inline unsigned int decode_config1(struct cpuinfo_mips *c) c->options |= MIPS_CPU_FPU; c->options |= MIPS_CPU_32FPR; } - if (cpu_has_tlb) + if (cpu_has_tlb) { c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; + c->tlbsizevtlb = c->tlbsize; + c->tlbsizeftlbsets = 0; + } return config1 & MIPS_CONF_M; } @@ -272,6 +299,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_MICROMIPS; if (config3 & MIPS_CONF3_VZ) c->ases |= MIPS_ASE_VZ; + if (config3 & MIPS_CONF3_SC) + c->options |= MIPS_CPU_SEGMENTS; return config3 & MIPS_CONF_M; } @@ -279,12 +308,51 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) static inline unsigned int decode_config4(struct cpuinfo_mips *c) { unsigned int config4; + unsigned int newcf4; + unsigned int mmuextdef; + unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE; config4 = read_c0_config4(); - if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT - && cpu_has_tlb) - c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + if (cpu_has_tlb) { + if (((config4 & MIPS_CONF4_IE) >> 29) == 2) + c->options |= MIPS_CPU_TLBINV; + mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF; + switch (mmuextdef) { + case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT: + c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + c->tlbsizevtlb = c->tlbsize; + break; + case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT: + c->tlbsizevtlb += + ((config4 & MIPS_CONF4_VTLBSIZEEXT) >> + MIPS_CONF4_VTLBSIZEEXT_SHIFT) * 0x40; + c->tlbsize = c->tlbsizevtlb; + ftlb_page = MIPS_CONF4_VFTLBPAGESIZE; + /* fall through */ + case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: + newcf4 = (config4 & ~ftlb_page) | + (page_size_ftlb(mmuextdef) << + MIPS_CONF4_FTLBPAGESIZE_SHIFT); + write_c0_config4(newcf4); + back_to_back_c0_hazard(); + config4 = read_c0_config4(); + if (config4 != newcf4) { + pr_err("PAGE_SIZE 0x%lx is not supported by FTLB (config4=0x%x)\n", + PAGE_SIZE, config4); + /* Switch FTLB off */ + set_ftlb_enable(c, 0); + break; + } + c->tlbsizeftlbsets = 1 << + ((config4 & MIPS_CONF4_FTLBSETS) >> + MIPS_CONF4_FTLBSETS_SHIFT); + c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >> + MIPS_CONF4_FTLBWAYS_SHIFT) + 2; + c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets; + break; + } + } c->kscratch_mask = (config4 >> 16) & 0xff; @@ -312,6 +380,9 @@ static void decode_configs(struct cpuinfo_mips *c) c->scache.flags = MIPS_CACHE_NOT_PRESENT; + /* Enable FTLB if present */ + set_ftlb_enable(c, 1); + ok = decode_config0(c); /* Read Config registers. */ BUG_ON(!ok); /* Arch spec violation! */ if (ok) @@ -675,7 +746,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) { - decode_configs(c); switch (c->processor_id & PRID_IMP_MASK) { case PRID_IMP_4KC: c->cputype = CPU_4KC; @@ -739,8 +809,26 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_74K; __cpu_name[cpu] = "MIPS 1074Kc"; break; + case PRID_IMP_INTERAPTIV_UP: + c->cputype = CPU_INTERAPTIV; + __cpu_name[cpu] = "MIPS interAptiv"; + break; + case PRID_IMP_INTERAPTIV_MP: + c->cputype = CPU_INTERAPTIV; + __cpu_name[cpu] = "MIPS interAptiv (multi)"; + break; + case PRID_IMP_PROAPTIV_UP: + c->cputype = CPU_PROAPTIV; + __cpu_name[cpu] = "MIPS proAptiv"; + break; + case PRID_IMP_PROAPTIV_MP: + c->cputype = CPU_PROAPTIV; + __cpu_name[cpu] = "MIPS proAptiv (multi)"; + break; } + decode_configs(c); + spram_config(); } @@ -943,6 +1031,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) switch (c->processor_id & PRID_IMP_MASK) { case PRID_IMP_NETLOGIC_XLP2XX: + case PRID_IMP_NETLOGIC_XLP9XX: c->cputype = CPU_XLP; __cpu_name[cpu] = "Broadcom XLPII"; break; diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c index 93aa302948d7..d21264681e97 100644 --- a/arch/mips/kernel/crash.c +++ b/arch/mips/kernel/crash.c @@ -5,7 +5,6 @@ #include <linux/bootmem.h> #include <linux/crash_dump.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/irq.h> #include <linux/types.h> #include <linux/sched.h> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 47d7583cd67f..d84f6a509502 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -476,6 +476,7 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER ov ov sti silent /* #12 */ BUILD_HANDLER tr tr sti silent /* #13 */ BUILD_HANDLER fpe fpe fpe silent /* #15 */ + BUILD_HANDLER ftlb ftlb none silent /* #16 */ BUILD_HANDLER mdmx mdmx sti silent /* #22 */ #ifdef CONFIG_HARDWARE_WATCHPOINTS /* diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index f7991d95bff9..3553243bf9d6 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -184,6 +184,8 @@ void __init check_wait(void) case CPU_24K: case CPU_34K: case CPU_1004K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: cpu_wait = r4k_wait; if (read_c0_config7() & MIPS_CONF7_WII) cpu_wait = r4k_wait_irqoff; diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 8c58d8a84bf3..00d20974b3e7 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -65,26 +65,25 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpu_data[n].watch_reg_masks[i]); seq_printf(m, "]\n"); } - if (cpu_has_mips_r) { - seq_printf(m, "isa\t\t\t: mips1"); - if (cpu_has_mips_2) - seq_printf(m, "%s", " mips2"); - if (cpu_has_mips_3) - seq_printf(m, "%s", " mips3"); - if (cpu_has_mips_4) - seq_printf(m, "%s", " mips4"); - if (cpu_has_mips_5) - seq_printf(m, "%s", " mips5"); - if (cpu_has_mips32r1) - seq_printf(m, "%s", " mips32r1"); - if (cpu_has_mips32r2) - seq_printf(m, "%s", " mips32r2"); - if (cpu_has_mips64r1) - seq_printf(m, "%s", " mips64r1"); - if (cpu_has_mips64r2) - seq_printf(m, "%s", " mips64r2"); - seq_printf(m, "\n"); - } + + seq_printf(m, "isa\t\t\t: mips1"); + if (cpu_has_mips_2) + seq_printf(m, "%s", " mips2"); + if (cpu_has_mips_3) + seq_printf(m, "%s", " mips3"); + if (cpu_has_mips_4) + seq_printf(m, "%s", " mips4"); + if (cpu_has_mips_5) + seq_printf(m, "%s", " mips5"); + if (cpu_has_mips32r1) + seq_printf(m, "%s", " mips32r1"); + if (cpu_has_mips32r2) + seq_printf(m, "%s", " mips32r2"); + if (cpu_has_mips64r1) + seq_printf(m, "%s", " mips64r1"); + if (cpu_has_mips64r2) + seq_printf(m, "%s", " mips64r2"); + seq_printf(m, "\n"); seq_printf(m, "ASEs implemented\t:"); if (cpu_has_mips16) seq_printf(m, "%s", " mips16"); @@ -107,7 +106,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "kscratch registers\t: %d\n", hweight8(cpu_data[n].kscratch_mask)); seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); - +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) + if (cpu_has_mipsmt) { + seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id); +#if defined(CONFIG_MIPS_MT_SMTC) + seq_printf(m, "TC\t\t\t: %d\n", cpu_data[n].tc_id); +#endif + } +#endif sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); seq_printf(m, fmt, 'D', vced_count); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index ddc76103e78c..6ae540e133b2 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -60,15 +60,11 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) /* New thread loses kernel privileges. */ status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK); -#ifdef CONFIG_64BIT - status |= test_thread_flag(TIF_32BIT_REGS) ? 0 : ST0_FR; -#endif status |= KU_USER; regs->cp0_status = status; clear_used_math(); clear_fpu_owner(); - if (cpu_has_dsp) - __init_dsp(); + init_dsp(); regs->cp0_epc = pc; regs->regs[29] = sp; } diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index b52e1d2b33e0..7da9b76db4d9 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -137,13 +137,13 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data) if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); write_c0_status(flags); evpe(vpflags); } else { flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); write_c0_status(flags); } @@ -408,6 +408,7 @@ long arch_ptrace(struct task_struct *child, long request, /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; + fpureg_t *fregs; unsigned long tmp = 0; regs = task_pt_regs(child); @@ -418,26 +419,28 @@ long arch_ptrace(struct task_struct *child, long request, tmp = regs->regs[addr]; break; case FPR_BASE ... FPR_BASE + 31: - if (tsk_used_math(child)) { - fpureg_t *fregs = get_fpu_regs(child); + if (!tsk_used_math(child)) { + /* FP not yet used */ + tmp = -1; + break; + } + fregs = get_fpu_regs(child); #ifdef CONFIG_32BIT + if (test_thread_flag(TIF_32BIT_FPREGS)) { /* * The odd registers are actually the high * order bits of the values stored in the even * registers - unless we're using r2k_switch.S. */ if (addr & 1) - tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + tmp = fregs[(addr & ~1) - 32] >> 32; else - tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); -#endif -#ifdef CONFIG_64BIT - tmp = fregs[addr - FPR_BASE]; -#endif - } else { - tmp = -1; /* FP not yet used */ + tmp = fregs[addr - 32]; + break; } +#endif + tmp = fregs[addr - FPR_BASE]; break; case PC: tmp = regs->cp0_epc; @@ -483,13 +486,13 @@ long arch_ptrace(struct task_struct *child, long request, if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); write_c0_status(flags); evpe(vpflags); } else { flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); write_c0_status(flags); } @@ -554,22 +557,25 @@ long arch_ptrace(struct task_struct *child, long request, child->thread.fpu.fcr31 = 0; } #ifdef CONFIG_32BIT - /* - * The odd registers are actually the high order bits - * of the values stored in the even registers - unless - * we're using r2k_switch.S. - */ - if (addr & 1) { - fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; - fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; - } else { - fregs[addr - FPR_BASE] &= ~0xffffffffLL; - fregs[addr - FPR_BASE] |= data; + if (test_thread_flag(TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even + * registers - unless we're using r2k_switch.S. + */ + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= + 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= + ((u64)data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; + } + break; } #endif -#ifdef CONFIG_64BIT fregs[addr - FPR_BASE] = data; -#endif break; } case PC: diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 9486055ba660..b8aa2dd5b00b 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -80,6 +80,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; + fpureg_t *fregs; unsigned int tmp; regs = task_pt_regs(child); @@ -90,21 +91,25 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, tmp = regs->regs[addr]; break; case FPR_BASE ... FPR_BASE + 31: - if (tsk_used_math(child)) { - fpureg_t *fregs = get_fpu_regs(child); - + if (!tsk_used_math(child)) { + /* FP not yet used */ + tmp = -1; + break; + } + fregs = get_fpu_regs(child); + if (test_thread_flag(TIF_32BIT_FPREGS)) { /* * The odd registers are actually the high * order bits of the values stored in the even * registers - unless we're using r2k_switch.S. */ if (addr & 1) - tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); + tmp = fregs[(addr & ~1) - 32] >> 32; else - tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); - } else { - tmp = -1; /* FP not yet used */ + tmp = fregs[addr - 32]; + break; } + tmp = fregs[addr - FPR_BASE]; break; case PC: tmp = regs->cp0_epc; @@ -147,13 +152,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); write_c0_status(flags); evpe(vpflags); } else { flags = read_c0_status(); - __enable_fpu(); + __enable_fpu(FPU_AS_IS); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); write_c0_status(flags); } @@ -236,20 +241,24 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, sizeof(child->thread.fpu)); child->thread.fpu.fcr31 = 0; } - /* - * The odd registers are actually the high order bits - * of the values stored in the even registers - unless - * we're using r2k_switch.S. - */ - if (addr & 1) { - fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; - fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; - } else { - fregs[addr - FPR_BASE] &= ~0xffffffffLL; - /* Must cast, lest sign extension fill upper - bits! */ - fregs[addr - FPR_BASE] |= (unsigned int)data; + if (test_thread_flag(TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even + * registers - unless we're using r2k_switch.S. + */ + if (addr & 1) { + fregs[(addr & ~1) - FPR_BASE] &= + 0xffffffff; + fregs[(addr & ~1) - FPR_BASE] |= + ((u64)data) << 32; + } else { + fregs[addr - FPR_BASE] &= ~0xffffffffLL; + fregs[addr - FPR_BASE] |= data; + } + break; } + fregs[addr - FPR_BASE] = data; break; } case PC: diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 55ffe149dae9..253b2fb52026 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -35,7 +35,15 @@ LEAF(_save_fp_context) cfc1 t1, fcr31 -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS32_R2) + .set push +#ifdef CONFIG_MIPS32_R2 + .set mips64r2 + mfc0 t0, CP0_STATUS + sll t0, t0, 5 + bgez t0, 1f # skip storing odd if FR=0 + nop +#endif /* Store the 16 odd double precision registers */ EX sdc1 $f1, SC_FPREGS+8(a0) EX sdc1 $f3, SC_FPREGS+24(a0) @@ -53,6 +61,7 @@ LEAF(_save_fp_context) EX sdc1 $f27, SC_FPREGS+216(a0) EX sdc1 $f29, SC_FPREGS+232(a0) EX sdc1 $f31, SC_FPREGS+248(a0) +1: .set pop #endif /* Store the 16 even double precision registers */ @@ -82,7 +91,31 @@ LEAF(_save_fp_context) LEAF(_save_fp_context32) cfc1 t1, fcr31 - EX sdc1 $f0, SC32_FPREGS+0(a0) + mfc0 t0, CP0_STATUS + sll t0, t0, 5 + bgez t0, 1f # skip storing odd if FR=0 + nop + + /* Store the 16 odd double precision registers */ + EX sdc1 $f1, SC32_FPREGS+8(a0) + EX sdc1 $f3, SC32_FPREGS+24(a0) + EX sdc1 $f5, SC32_FPREGS+40(a0) + EX sdc1 $f7, SC32_FPREGS+56(a0) + EX sdc1 $f9, SC32_FPREGS+72(a0) + EX sdc1 $f11, SC32_FPREGS+88(a0) + EX sdc1 $f13, SC32_FPREGS+104(a0) + EX sdc1 $f15, SC32_FPREGS+120(a0) + EX sdc1 $f17, SC32_FPREGS+136(a0) + EX sdc1 $f19, SC32_FPREGS+152(a0) + EX sdc1 $f21, SC32_FPREGS+168(a0) + EX sdc1 $f23, SC32_FPREGS+184(a0) + EX sdc1 $f25, SC32_FPREGS+200(a0) + EX sdc1 $f27, SC32_FPREGS+216(a0) + EX sdc1 $f29, SC32_FPREGS+232(a0) + EX sdc1 $f31, SC32_FPREGS+248(a0) + + /* Store the 16 even double precision registers */ +1: EX sdc1 $f0, SC32_FPREGS+0(a0) EX sdc1 $f2, SC32_FPREGS+16(a0) EX sdc1 $f4, SC32_FPREGS+32(a0) EX sdc1 $f6, SC32_FPREGS+48(a0) @@ -114,7 +147,16 @@ LEAF(_save_fp_context32) */ LEAF(_restore_fp_context) EX lw t0, SC_FPC_CSR(a0) -#ifdef CONFIG_64BIT + +#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS32_R2) + .set push +#ifdef CONFIG_MIPS32_R2 + .set mips64r2 + mfc0 t0, CP0_STATUS + sll t0, t0, 5 + bgez t0, 1f # skip loading odd if FR=0 + nop +#endif EX ldc1 $f1, SC_FPREGS+8(a0) EX ldc1 $f3, SC_FPREGS+24(a0) EX ldc1 $f5, SC_FPREGS+40(a0) @@ -131,6 +173,7 @@ LEAF(_restore_fp_context) EX ldc1 $f27, SC_FPREGS+216(a0) EX ldc1 $f29, SC_FPREGS+232(a0) EX ldc1 $f31, SC_FPREGS+248(a0) +1: .set pop #endif EX ldc1 $f0, SC_FPREGS+0(a0) EX ldc1 $f2, SC_FPREGS+16(a0) @@ -157,7 +200,30 @@ LEAF(_restore_fp_context) LEAF(_restore_fp_context32) /* Restore an o32 sigcontext. */ EX lw t0, SC32_FPC_CSR(a0) - EX ldc1 $f0, SC32_FPREGS+0(a0) + + mfc0 t0, CP0_STATUS + sll t0, t0, 5 + bgez t0, 1f # skip loading odd if FR=0 + nop + + EX ldc1 $f1, SC32_FPREGS+8(a0) + EX ldc1 $f3, SC32_FPREGS+24(a0) + EX ldc1 $f5, SC32_FPREGS+40(a0) + EX ldc1 $f7, SC32_FPREGS+56(a0) + EX ldc1 $f9, SC32_FPREGS+72(a0) + EX ldc1 $f11, SC32_FPREGS+88(a0) + EX ldc1 $f13, SC32_FPREGS+104(a0) + EX ldc1 $f15, SC32_FPREGS+120(a0) + EX ldc1 $f17, SC32_FPREGS+136(a0) + EX ldc1 $f19, SC32_FPREGS+152(a0) + EX ldc1 $f21, SC32_FPREGS+168(a0) + EX ldc1 $f23, SC32_FPREGS+184(a0) + EX ldc1 $f25, SC32_FPREGS+200(a0) + EX ldc1 $f27, SC32_FPREGS+216(a0) + EX ldc1 $f29, SC32_FPREGS+232(a0) + EX ldc1 $f31, SC32_FPREGS+248(a0) + +1: EX ldc1 $f0, SC32_FPREGS+0(a0) EX ldc1 $f2, SC32_FPREGS+16(a0) EX ldc1 $f4, SC32_FPREGS+32(a0) EX ldc1 $f6, SC32_FPREGS+48(a0) diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 078de5eaca8f..cc78dd9a17c7 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -123,7 +123,7 @@ * Save a thread's fp context. */ LEAF(_save_fp) -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) mfc0 t0, CP0_STATUS #endif fpu_save_double a0 t0 t1 # clobbers t1 @@ -134,7 +134,7 @@ LEAF(_save_fp) * Restore a thread's fp context. */ LEAF(_restore_fp) -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) mfc0 t0, CP0_STATUS #endif fpu_restore_double a0 t0 t1 # clobbers t1 @@ -228,6 +228,47 @@ LEAF(_init_fpu) mtc1 t1, $f29 mtc1 t1, $f30 mtc1 t1, $f31 + +#ifdef CONFIG_CPU_MIPS32_R2 + .set push + .set mips64r2 + sll t0, t0, 5 # is Status.FR set? + bgez t0, 1f # no: skip setting upper 32b + + mthc1 t1, $f0 + mthc1 t1, $f1 + mthc1 t1, $f2 + mthc1 t1, $f3 + mthc1 t1, $f4 + mthc1 t1, $f5 + mthc1 t1, $f6 + mthc1 t1, $f7 + mthc1 t1, $f8 + mthc1 t1, $f9 + mthc1 t1, $f10 + mthc1 t1, $f11 + mthc1 t1, $f12 + mthc1 t1, $f13 + mthc1 t1, $f14 + mthc1 t1, $f15 + mthc1 t1, $f16 + mthc1 t1, $f17 + mthc1 t1, $f18 + mthc1 t1, $f19 + mthc1 t1, $f20 + mthc1 t1, $f21 + mthc1 t1, $f22 + mthc1 t1, $f23 + mthc1 t1, $f24 + mthc1 t1, $f25 + mthc1 t1, $f26 + mthc1 t1, $f27 + mthc1 t1, $f28 + mthc1 t1, $f29 + mthc1 t1, $f30 + mthc1 t1, $f31 +1: .set pop +#endif /* CONFIG_CPU_MIPS32_R2 */ #else .set mips3 dmtc1 t1, $f0 diff --git a/arch/mips/kernel/rtlx-cmp.c b/arch/mips/kernel/rtlx-cmp.c new file mode 100644 index 000000000000..56dc69635153 --- /dev/null +++ b/arch/mips/kernel/rtlx-cmp.c @@ -0,0 +1,116 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/err.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/smp.h> + +#include <asm/mips_mt.h> +#include <asm/vpe.h> +#include <asm/rtlx.h> + +static int major; + +static void rtlx_interrupt(void) +{ + int i; + struct rtlx_info *info; + struct rtlx_info **p = vpe_get_shared(aprp_cpu_index()); + + if (p == NULL || *p == NULL) + return; + + info = *p; + + if (info->ap_int_pending == 1 && smp_processor_id() == 0) { + for (i = 0; i < RTLX_CHANNELS; i++) { + wake_up(&channel_wqs[i].lx_queue); + wake_up(&channel_wqs[i].rt_queue); + } + info->ap_int_pending = 0; + } +} + +void _interrupt_sp(void) +{ + smp_send_reschedule(aprp_cpu_index()); +} + +int __init rtlx_module_init(void) +{ + struct device *dev; + int i, err; + + if (!cpu_has_mipsmt) { + pr_warn("VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + if (num_possible_cpus() - aprp_cpu_index() < 1) { + pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n" + "Pass maxcpus=<n> argument as kernel argument\n"); + + return -ENODEV; + } + + major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops); + if (major < 0) { + pr_err("rtlx_module_init: unable to register device\n"); + return major; + } + + /* initialise the wait queues */ + for (i = 0; i < RTLX_CHANNELS; i++) { + init_waitqueue_head(&channel_wqs[i].rt_queue); + init_waitqueue_head(&channel_wqs[i].lx_queue); + atomic_set(&channel_wqs[i].in_open, 0); + mutex_init(&channel_wqs[i].mutex); + + dev = device_create(mt_class, NULL, MKDEV(major, i), NULL, + "%s%d", RTLX_MODULE_NAME, i); + if (IS_ERR(dev)) { + err = PTR_ERR(dev); + goto out_chrdev; + } + } + + /* set up notifiers */ + rtlx_notify.start = rtlx_starting; + rtlx_notify.stop = rtlx_stopping; + vpe_notify(aprp_cpu_index(), &rtlx_notify); + + if (cpu_has_vint) { + aprp_hook = rtlx_interrupt; + } else { + pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); + err = -ENODEV; + goto out_class; + } + + return 0; + +out_class: + for (i = 0; i < RTLX_CHANNELS; i++) + device_destroy(mt_class, MKDEV(major, i)); +out_chrdev: + unregister_chrdev(major, RTLX_MODULE_NAME); + + return err; +} + +void __exit rtlx_module_exit(void) +{ + int i; + + for (i = 0; i < RTLX_CHANNELS; i++) + device_destroy(mt_class, MKDEV(major, i)); + unregister_chrdev(major, RTLX_MODULE_NAME); +} diff --git a/arch/mips/kernel/rtlx-mt.c b/arch/mips/kernel/rtlx-mt.c new file mode 100644 index 000000000000..91d61ba422b4 --- /dev/null +++ b/arch/mips/kernel/rtlx-mt.c @@ -0,0 +1,148 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/err.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include <asm/mips_mt.h> +#include <asm/vpe.h> +#include <asm/rtlx.h> + +static int major; + +static void rtlx_dispatch(void) +{ + if (read_c0_cause() & read_c0_status() & C_SW0) + do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ); +} + +/* + * Interrupt handler may be called before rtlx_init has otherwise had + * a chance to run. + */ +static irqreturn_t rtlx_interrupt(int irq, void *dev_id) +{ + unsigned int vpeflags; + unsigned long flags; + int i; + + /* Ought not to be strictly necessary for SMTC builds */ + local_irq_save(flags); + vpeflags = dvpe(); + set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ); + irq_enable_hazard(); + evpe(vpeflags); + local_irq_restore(flags); + + for (i = 0; i < RTLX_CHANNELS; i++) { + wake_up(&channel_wqs[i].lx_queue); + wake_up(&channel_wqs[i].rt_queue); + } + + return IRQ_HANDLED; +} + +static struct irqaction rtlx_irq = { + .handler = rtlx_interrupt, + .name = "RTLX", +}; + +static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ; + +void _interrupt_sp(void) +{ + unsigned long flags; + + local_irq_save(flags); + dvpe(); + settc(1); + write_vpe_c0_cause(read_vpe_c0_cause() | C_SW0); + evpe(EVPE_ENABLE); + local_irq_restore(flags); +} + +int __init rtlx_module_init(void) +{ + struct device *dev; + int i, err; + + if (!cpu_has_mipsmt) { + pr_warn("VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + if (aprp_cpu_index() == 0) { + pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n" + "Pass maxtcs=<n> argument as kernel argument\n"); + + return -ENODEV; + } + + major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops); + if (major < 0) { + pr_err("rtlx_module_init: unable to register device\n"); + return major; + } + + /* initialise the wait queues */ + for (i = 0; i < RTLX_CHANNELS; i++) { + init_waitqueue_head(&channel_wqs[i].rt_queue); + init_waitqueue_head(&channel_wqs[i].lx_queue); + atomic_set(&channel_wqs[i].in_open, 0); + mutex_init(&channel_wqs[i].mutex); + + dev = device_create(mt_class, NULL, MKDEV(major, i), NULL, + "%s%d", RTLX_MODULE_NAME, i); + if (IS_ERR(dev)) { + err = PTR_ERR(dev); + goto out_chrdev; + } + } + + /* set up notifiers */ + rtlx_notify.start = rtlx_starting; + rtlx_notify.stop = rtlx_stopping; + vpe_notify(aprp_cpu_index(), &rtlx_notify); + + if (cpu_has_vint) { + aprp_hook = rtlx_dispatch; + } else { + pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); + err = -ENODEV; + goto out_class; + } + + rtlx_irq.dev_id = rtlx; + err = setup_irq(rtlx_irq_num, &rtlx_irq); + if (err) + goto out_class; + + return 0; + +out_class: + for (i = 0; i < RTLX_CHANNELS; i++) + device_destroy(mt_class, MKDEV(major, i)); +out_chrdev: + unregister_chrdev(major, RTLX_MODULE_NAME); + + return err; +} + +void __exit rtlx_module_exit(void) +{ + int i; + + for (i = 0; i < RTLX_CHANNELS; i++) + device_destroy(mt_class, MKDEV(major, i)); + unregister_chrdev(major, RTLX_MODULE_NAME); +} diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 2c12ea1668d1..31b1b763cb29 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -1,114 +1,51 @@ /* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. * Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org) - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * + * Copyright (C) 2013 Imagination Technologies Ltd. */ - -#include <linux/device.h> #include <linux/kernel.h> #include <linux/fs.h> -#include <linux/init.h> -#include <asm/uaccess.h> -#include <linux/list.h> -#include <linux/vmalloc.h> -#include <linux/elf.h> -#include <linux/seq_file.h> #include <linux/syscalls.h> #include <linux/moduleloader.h> -#include <linux/interrupt.h> -#include <linux/poll.h> -#include <linux/sched.h> -#include <linux/wait.h> +#include <linux/atomic.h> #include <asm/mipsmtregs.h> #include <asm/mips_mt.h> -#include <asm/cacheflush.h> -#include <linux/atomic.h> -#include <asm/cpu.h> #include <asm/processor.h> -#include <asm/vpe.h> #include <asm/rtlx.h> #include <asm/setup.h> +#include <asm/vpe.h> -static struct rtlx_info *rtlx; -static int major; -static char module_name[] = "rtlx"; - -static struct chan_waitqueues { - wait_queue_head_t rt_queue; - wait_queue_head_t lx_queue; - atomic_t in_open; - struct mutex mutex; -} channel_wqs[RTLX_CHANNELS]; - -static struct vpe_notifications notify; static int sp_stopping; - -extern void *vpe_get_shared(int index); - -static void rtlx_dispatch(void) -{ - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ); -} - - -/* Interrupt handler may be called before rtlx_init has otherwise had - a chance to run. -*/ -static irqreturn_t rtlx_interrupt(int irq, void *dev_id) -{ - unsigned int vpeflags; - unsigned long flags; - int i; - - /* Ought not to be strictly necessary for SMTC builds */ - local_irq_save(flags); - vpeflags = dvpe(); - set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ); - irq_enable_hazard(); - evpe(vpeflags); - local_irq_restore(flags); - - for (i = 0; i < RTLX_CHANNELS; i++) { - wake_up(&channel_wqs[i].lx_queue); - wake_up(&channel_wqs[i].rt_queue); - } - - return IRQ_HANDLED; -} +struct rtlx_info *rtlx; +struct chan_waitqueues channel_wqs[RTLX_CHANNELS]; +struct vpe_notifications rtlx_notify; +void (*aprp_hook)(void) = NULL; +EXPORT_SYMBOL(aprp_hook); static void __used dump_rtlx(void) { int i; - printk("id 0x%lx state %d\n", rtlx->id, rtlx->state); + pr_info("id 0x%lx state %d\n", rtlx->id, rtlx->state); for (i = 0; i < RTLX_CHANNELS; i++) { struct rtlx_channel *chan = &rtlx->channel[i]; - printk(" rt_state %d lx_state %d buffer_size %d\n", - chan->rt_state, chan->lx_state, chan->buffer_size); + pr_info(" rt_state %d lx_state %d buffer_size %d\n", + chan->rt_state, chan->lx_state, chan->buffer_size); - printk(" rt_read %d rt_write %d\n", - chan->rt_read, chan->rt_write); + pr_info(" rt_read %d rt_write %d\n", + chan->rt_read, chan->rt_write); - printk(" lx_read %d lx_write %d\n", - chan->lx_read, chan->lx_write); + pr_info(" lx_read %d lx_write %d\n", + chan->lx_read, chan->lx_write); - printk(" rt_buffer <%s>\n", chan->rt_buffer); - printk(" lx_buffer <%s>\n", chan->lx_buffer); + pr_info(" rt_buffer <%s>\n", chan->rt_buffer); + pr_info(" lx_buffer <%s>\n", chan->lx_buffer); } } @@ -116,8 +53,7 @@ static void __used dump_rtlx(void) static int rtlx_init(struct rtlx_info *rtlxi) { if (rtlxi->id != RTLX_ID) { - printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n", - rtlxi, rtlxi->id); + pr_err("no valid RTLX id at 0x%p 0x%lx\n", rtlxi, rtlxi->id); return -ENOEXEC; } @@ -127,20 +63,20 @@ static int rtlx_init(struct rtlx_info *rtlxi) } /* notifications */ -static void starting(int vpe) +void rtlx_starting(int vpe) { int i; sp_stopping = 0; /* force a reload of rtlx */ - rtlx=NULL; + rtlx = NULL; /* wake up any sleeping rtlx_open's */ for (i = 0; i < RTLX_CHANNELS; i++) wake_up_interruptible(&channel_wqs[i].lx_queue); } -static void stopping(int vpe) +void rtlx_stopping(int vpe) { int i; @@ -158,31 +94,30 @@ int rtlx_open(int index, int can_sleep) int ret = 0; if (index >= RTLX_CHANNELS) { - printk(KERN_DEBUG "rtlx_open index out of range\n"); + pr_debug(KERN_DEBUG "rtlx_open index out of range\n"); return -ENOSYS; } if (atomic_inc_return(&channel_wqs[index].in_open) > 1) { - printk(KERN_DEBUG "rtlx_open channel %d already opened\n", - index); + pr_debug(KERN_DEBUG "rtlx_open channel %d already opened\n", index); ret = -EBUSY; goto out_fail; } if (rtlx == NULL) { - if( (p = vpe_get_shared(tclimit)) == NULL) { - if (can_sleep) { - ret = __wait_event_interruptible( + p = vpe_get_shared(aprp_cpu_index()); + if (p == NULL) { + if (can_sleep) { + ret = __wait_event_interruptible( channel_wqs[index].lx_queue, - (p = vpe_get_shared(tclimit))); - if (ret) + (p = vpe_get_shared(aprp_cpu_index()))); + if (ret) + goto out_fail; + } else { + pr_debug("No SP program loaded, and device opened with O_NONBLOCK\n"); + ret = -ENOSYS; goto out_fail; - } else { - printk(KERN_DEBUG "No SP program loaded, and device " - "opened with O_NONBLOCK\n"); - ret = -ENOSYS; - goto out_fail; - } + } } smp_rmb(); @@ -204,24 +139,24 @@ int rtlx_open(int index, int can_sleep) ret = -ERESTARTSYS; goto out_fail; } - finish_wait(&channel_wqs[index].lx_queue, &wait); + finish_wait(&channel_wqs[index].lx_queue, + &wait); } else { - pr_err(" *vpe_get_shared is NULL. " - "Has an SP program been loaded?\n"); + pr_err(" *vpe_get_shared is NULL. Has an SP program been loaded?\n"); ret = -ENOSYS; goto out_fail; } } if ((unsigned int)*p < KSEG0) { - printk(KERN_WARNING "vpe_get_shared returned an " - "invalid pointer maybe an error code %d\n", - (int)*p); + pr_warn("vpe_get_shared returned an invalid pointer maybe an error code %d\n", + (int)*p); ret = -ENOSYS; goto out_fail; } - if ((ret = rtlx_init(*p)) < 0) + ret = rtlx_init(*p); + if (ret < 0) goto out_ret; } @@ -352,7 +287,7 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count) size_t fl; if (rtlx == NULL) - return(-ENOSYS); + return -ENOSYS; rt = &rtlx->channel[index]; @@ -361,8 +296,8 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count) rt_read = rt->rt_read; /* total number of bytes to copy */ - count = min(count, (size_t)write_spacefree(rt_read, rt->rt_write, - rt->buffer_size)); + count = min_t(size_t, count, write_spacefree(rt_read, rt->rt_write, + rt->buffer_size)); /* first bit from write pointer to the end of the buffer, or count */ fl = min(count, (size_t) rt->buffer_size - rt->rt_write); @@ -372,9 +307,8 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count) goto out; /* if there's any left copy to the beginning of the buffer */ - if (count - fl) { + if (count - fl) failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); - } out: count -= failed; @@ -384,6 +318,8 @@ out: smp_wmb(); mutex_unlock(&channel_wqs[index].mutex); + _interrupt_sp(); + return count; } @@ -398,7 +334,7 @@ static int file_release(struct inode *inode, struct file *filp) return rtlx_release(iminor(inode)); } -static unsigned int file_poll(struct file *file, poll_table * wait) +static unsigned int file_poll(struct file *file, poll_table *wait) { int minor = iminor(file_inode(file)); unsigned int mask = 0; @@ -420,21 +356,20 @@ static unsigned int file_poll(struct file *file, poll_table * wait) return mask; } -static ssize_t file_read(struct file *file, char __user * buffer, size_t count, - loff_t * ppos) +static ssize_t file_read(struct file *file, char __user *buffer, size_t count, + loff_t *ppos) { int minor = iminor(file_inode(file)); /* data available? */ - if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) { - return 0; // -EAGAIN makes cat whinge - } + if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) + return 0; /* -EAGAIN makes 'cat' whine */ return rtlx_read(minor, buffer, count); } -static ssize_t file_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) +static ssize_t file_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { int minor = iminor(file_inode(file)); @@ -454,100 +389,16 @@ static ssize_t file_write(struct file *file, const char __user * buffer, return rtlx_write(minor, buffer, count); } -static const struct file_operations rtlx_fops = { +const struct file_operations rtlx_fops = { .owner = THIS_MODULE, - .open = file_open, + .open = file_open, .release = file_release, .write = file_write, - .read = file_read, - .poll = file_poll, + .read = file_read, + .poll = file_poll, .llseek = noop_llseek, }; -static struct irqaction rtlx_irq = { - .handler = rtlx_interrupt, - .name = "RTLX", -}; - -static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ; - -static char register_chrdev_failed[] __initdata = - KERN_ERR "rtlx_module_init: unable to register device\n"; - -static int __init rtlx_module_init(void) -{ - struct device *dev; - int i, err; - - if (!cpu_has_mipsmt) { - printk("VPE loader: not a MIPS MT capable processor\n"); - return -ENODEV; - } - - if (tclimit == 0) { - printk(KERN_WARNING "No TCs reserved for AP/SP, not " - "initializing RTLX.\nPass maxtcs=<n> argument as kernel " - "argument\n"); - - return -ENODEV; - } - - major = register_chrdev(0, module_name, &rtlx_fops); - if (major < 0) { - printk(register_chrdev_failed); - return major; - } - - /* initialise the wait queues */ - for (i = 0; i < RTLX_CHANNELS; i++) { - init_waitqueue_head(&channel_wqs[i].rt_queue); - init_waitqueue_head(&channel_wqs[i].lx_queue); - atomic_set(&channel_wqs[i].in_open, 0); - mutex_init(&channel_wqs[i].mutex); - - dev = device_create(mt_class, NULL, MKDEV(major, i), NULL, - "%s%d", module_name, i); - if (IS_ERR(dev)) { - err = PTR_ERR(dev); - goto out_chrdev; - } - } - - /* set up notifiers */ - notify.start = starting; - notify.stop = stopping; - vpe_notify(tclimit, ¬ify); - - if (cpu_has_vint) - set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); - else { - pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); - err = -ENODEV; - goto out_chrdev; - } - - rtlx_irq.dev_id = rtlx; - setup_irq(rtlx_irq_num, &rtlx_irq); - - return 0; - -out_chrdev: - for (i = 0; i < RTLX_CHANNELS; i++) - device_destroy(mt_class, MKDEV(major, i)); - - return err; -} - -static void __exit rtlx_module_exit(void) -{ - int i; - - for (i = 0; i < RTLX_CHANNELS; i++) - device_destroy(mt_class, MKDEV(major, i)); - - unregister_chrdev(major, module_name); -} - module_init(rtlx_module_init); module_exit(rtlx_module_exit); diff --git a/arch/mips/kernel/segment.c b/arch/mips/kernel/segment.c new file mode 100644 index 000000000000..076ead2a9859 --- /dev/null +++ b/arch/mips/kernel/segment.c @@ -0,0 +1,110 @@ +/* + * 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 Imagination Technologies Ltd. + */ + +#include <linux/kernel.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <asm/cpu.h> +#include <asm/mipsregs.h> + +static void build_segment_config(char *str, unsigned int cfg) +{ + unsigned int am; + static const char * const am_str[] = { + "UK", "MK", "MSK", "MUSK", "MUSUK", "USK", + "RSRVD", "UUSK"}; + + /* Segment access mode. */ + am = (cfg & MIPS_SEGCFG_AM) >> MIPS_SEGCFG_AM_SHIFT; + str += sprintf(str, "%-5s", am_str[am]); + + /* + * Access modes MK, MSK and MUSK are mapped segments. Therefore + * there is no direct physical address mapping. + */ + if ((am == 0) || (am > 3)) { + str += sprintf(str, " %03lx", + ((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT)); + str += sprintf(str, " %01ld", + ((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT)); + } else { + str += sprintf(str, " UND"); + str += sprintf(str, " U"); + } + + /* Exception configuration. */ + str += sprintf(str, " %01ld\n", + ((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT)); +} + +static int show_segments(struct seq_file *m, void *v) +{ + unsigned int segcfg; + char str[42]; + + seq_puts(m, "Segment Virtual Size Access Mode Physical Caching EU\n"); + seq_puts(m, "------- ------- ---- ----------- -------- ------- --\n"); + + segcfg = read_c0_segctl0(); + build_segment_config(str, segcfg); + seq_printf(m, " 0 e0000000 512M %s", str); + + segcfg >>= 16; + build_segment_config(str, segcfg); + seq_printf(m, " 1 c0000000 512M %s", str); + + segcfg = read_c0_segctl1(); + build_segment_config(str, segcfg); + seq_printf(m, " 2 a0000000 512M %s", str); + + segcfg >>= 16; + build_segment_config(str, segcfg); + seq_printf(m, " 3 80000000 512M %s", str); + + segcfg = read_c0_segctl2(); + build_segment_config(str, segcfg); + seq_printf(m, " 4 40000000 1G %s", str); + + segcfg >>= 16; + build_segment_config(str, segcfg); + seq_printf(m, " 5 00000000 1G %s\n", str); + + return 0; +} + +static int segments_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_segments, NULL); +} + +static const struct file_operations segments_fops = { + .open = segments_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init segments_info(void) +{ + extern struct dentry *mips_debugfs_dir; + struct dentry *segments; + + if (cpu_has_segments) { + if (!mips_debugfs_dir) + return -ENODEV; + + segments = debugfs_create_file("segments", S_IRUGO, + mips_debugfs_dir, NULL, + &segments_fops); + if (!segments) + return -ENOMEM; + } + return 0; +} + +device_initcall(segments_info); diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 2f285abc76d5..5199563c4403 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -71,8 +71,9 @@ static int protected_save_fp_context(struct sigcontext __user *sc) int err; while (1) { lock_fpu_owner(); - own_fpu_inatomic(1); - err = save_fp_context(sc); /* this might fail */ + err = own_fpu_inatomic(1); + if (!err) + err = save_fp_context(sc); /* this might fail */ unlock_fpu_owner(); if (likely(!err)) break; @@ -91,8 +92,9 @@ static int protected_restore_fp_context(struct sigcontext __user *sc) int err, tmp __maybe_unused; while (1) { lock_fpu_owner(); - own_fpu_inatomic(0); - err = restore_fp_context(sc); /* this might fail */ + err = own_fpu_inatomic(0); + if (!err) + err = restore_fp_context(sc); /* this might fail */ unlock_fpu_owner(); if (likely(!err)) break; diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 1905a419aa46..3d60f7750fa8 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -85,8 +85,9 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) int err; while (1) { lock_fpu_owner(); - own_fpu_inatomic(1); - err = save_fp_context32(sc); /* this might fail */ + err = own_fpu_inatomic(1); + if (!err) + err = save_fp_context32(sc); /* this might fail */ unlock_fpu_owner(); if (likely(!err)) break; @@ -105,8 +106,9 @@ static int protected_restore_fp_context32(struct sigcontext32 __user *sc) int err, tmp __maybe_unused; while (1) { lock_fpu_owner(); - own_fpu_inatomic(0); - err = restore_fp_context32(sc); /* this might fail */ + err = own_fpu_inatomic(0); + if (!err) + err = restore_fp_context32(sc); /* this might fail */ unlock_fpu_owner(); if (likely(!err)) break; diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 2362665ba496..ea4c2dc31692 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -49,8 +49,10 @@ cpumask_t bmips_booted_mask; unsigned long bmips_smp_boot_sp; unsigned long bmips_smp_boot_gp; -static void bmips_send_ipi_single(int cpu, unsigned int action); -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id); +static void bmips43xx_send_ipi_single(int cpu, unsigned int action); +static void bmips5000_send_ipi_single(int cpu, unsigned int action); +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id); +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id); /* SW interrupts 0,1 are used for interprocessor signaling */ #define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0) @@ -64,49 +66,58 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id); static void __init bmips_smp_setup(void) { int i, cpu = 1, boot_cpu = 0; - -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) int cpu_hw_intr; - /* arbitration priority */ - clear_c0_brcm_cmt_ctrl(0x30); - - /* NBK and weak order flags */ - set_c0_brcm_config_0(0x30000); - - /* Find out if we are running on TP0 or TP1 */ - boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); - - /* - * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread - * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output - * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output - */ - if (boot_cpu == 0) - cpu_hw_intr = 0x02; - else - cpu_hw_intr = 0x1d; - - change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15)); - - /* single core, 2 threads (2 pipelines) */ - max_cpus = 2; -#elif defined(CONFIG_CPU_BMIPS5000) - /* enable raceless SW interrupts */ - set_c0_brcm_config(0x03 << 22); - - /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */ - change_c0_brcm_mode(0x1f << 27, 0x02 << 27); - - /* N cores, 2 threads per core */ - max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1; + switch (current_cpu_type()) { + case CPU_BMIPS4350: + case CPU_BMIPS4380: + /* arbitration priority */ + clear_c0_brcm_cmt_ctrl(0x30); + + /* NBK and weak order flags */ + set_c0_brcm_config_0(0x30000); + + /* Find out if we are running on TP0 or TP1 */ + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); + + /* + * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other + * thread + * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output + * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output + */ + if (boot_cpu == 0) + cpu_hw_intr = 0x02; + else + cpu_hw_intr = 0x1d; + + change_c0_brcm_cmt_intr(0xf8018000, + (cpu_hw_intr << 27) | (0x03 << 15)); + + /* single core, 2 threads (2 pipelines) */ + max_cpus = 2; + + break; + case CPU_BMIPS5000: + /* enable raceless SW interrupts */ + set_c0_brcm_config(0x03 << 22); + + /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */ + change_c0_brcm_mode(0x1f << 27, 0x02 << 27); + + /* N cores, 2 threads per core */ + max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1; + + /* clear any pending SW interrupts */ + for (i = 0; i < max_cpus; i++) { + write_c0_brcm_action(ACTION_CLR_IPI(i, 0)); + write_c0_brcm_action(ACTION_CLR_IPI(i, 1)); + } - /* clear any pending SW interrupts */ - for (i = 0; i < max_cpus; i++) { - write_c0_brcm_action(ACTION_CLR_IPI(i, 0)); - write_c0_brcm_action(ACTION_CLR_IPI(i, 1)); + break; + default: + max_cpus = 1; } -#endif if (!bmips_smp_enabled) max_cpus = 1; @@ -134,6 +145,20 @@ static void __init bmips_smp_setup(void) */ static void bmips_prepare_cpus(unsigned int max_cpus) { + irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id); + + switch (current_cpu_type()) { + case CPU_BMIPS4350: + case CPU_BMIPS4380: + bmips_ipi_interrupt = bmips43xx_ipi_interrupt; + break; + case CPU_BMIPS5000: + bmips_ipi_interrupt = bmips5000_ipi_interrupt; + break; + default: + return; + } + if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU, "smp_ipi0", NULL)) panic("Can't request IPI0 interrupt"); @@ -168,26 +193,39 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) pr_info("SMP: Booting CPU%d...\n", cpu); - if (cpumask_test_cpu(cpu, &bmips_booted_mask)) - bmips_send_ipi_single(cpu, 0); + if (cpumask_test_cpu(cpu, &bmips_booted_mask)) { + switch (current_cpu_type()) { + case CPU_BMIPS4350: + case CPU_BMIPS4380: + bmips43xx_send_ipi_single(cpu, 0); + break; + case CPU_BMIPS5000: + bmips5000_send_ipi_single(cpu, 0); + break; + } + } else { -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) - /* Reset slave TP1 if booting from TP0 */ - if (cpu_logical_map(cpu) == 1) - set_c0_brcm_cmt_ctrl(0x01); -#elif defined(CONFIG_CPU_BMIPS5000) - if (cpu & 0x01) - write_c0_brcm_action(ACTION_BOOT_THREAD(cpu)); - else { - /* - * core N thread 0 was already booted; just - * pulse the NMI line - */ - bmips_write_zscm_reg(0x210, 0xc0000000); - udelay(10); - bmips_write_zscm_reg(0x210, 0x00); + switch (current_cpu_type()) { + case CPU_BMIPS4350: + case CPU_BMIPS4380: + /* Reset slave TP1 if booting from TP0 */ + if (cpu_logical_map(cpu) == 1) + set_c0_brcm_cmt_ctrl(0x01); + break; + case CPU_BMIPS5000: + if (cpu & 0x01) + write_c0_brcm_action(ACTION_BOOT_THREAD(cpu)); + else { + /* + * core N thread 0 was already booted; just + * pulse the NMI line + */ + bmips_write_zscm_reg(0x210, 0xc0000000); + udelay(10); + bmips_write_zscm_reg(0x210, 0x00); + } + break; } -#endif cpumask_set_cpu(cpu, &bmips_booted_mask); } } @@ -199,26 +237,32 @@ static void bmips_init_secondary(void) { /* move NMI vector to kseg0, in case XKS01 is enabled */ -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) - void __iomem *cbr = BMIPS_GET_CBR(); + void __iomem *cbr; unsigned long old_vec; unsigned long relo_vector; int boot_cpu; - boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); - relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 : - BMIPS_RELO_VECTOR_CONTROL_1; + switch (current_cpu_type()) { + case CPU_BMIPS4350: + case CPU_BMIPS4380: + cbr = BMIPS_GET_CBR(); - old_vec = __raw_readl(cbr + relo_vector); - __raw_writel(old_vec & ~0x20000000, cbr + relo_vector); + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); + relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 : + BMIPS_RELO_VECTOR_CONTROL_1; - clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); -#elif defined(CONFIG_CPU_BMIPS5000) - write_c0_brcm_bootvec(read_c0_brcm_bootvec() & - (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000)); + old_vec = __raw_readl(cbr + relo_vector); + __raw_writel(old_vec & ~0x20000000, cbr + relo_vector); - write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); -#endif + clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); + break; + case CPU_BMIPS5000: + write_c0_brcm_bootvec(read_c0_brcm_bootvec() & + (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000)); + + write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); + break; + } } /* @@ -243,8 +287,6 @@ static void bmips_cpus_done(void) { } -#if defined(CONFIG_CPU_BMIPS5000) - /* * BMIPS5000 raceless IPIs * @@ -253,12 +295,12 @@ static void bmips_cpus_done(void) * IPI1 is used for SMP_CALL_FUNCTION */ -static void bmips_send_ipi_single(int cpu, unsigned int action) +static void bmips5000_send_ipi_single(int cpu, unsigned int action) { write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION)); } -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id) +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id) { int action = irq - IPI0_IRQ; @@ -272,7 +314,14 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -#else +static void bmips5000_send_ipi_mask(const struct cpumask *mask, + unsigned int action) +{ + unsigned int i; + + for_each_cpu(i, mask) + bmips5000_send_ipi_single(i, action); +} /* * BMIPS43xx racey IPIs @@ -287,7 +336,7 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id) static DEFINE_SPINLOCK(ipi_lock); static DEFINE_PER_CPU(int, ipi_action_mask); -static void bmips_send_ipi_single(int cpu, unsigned int action) +static void bmips43xx_send_ipi_single(int cpu, unsigned int action) { unsigned long flags; @@ -298,7 +347,7 @@ static void bmips_send_ipi_single(int cpu, unsigned int action) spin_unlock_irqrestore(&ipi_lock, flags); } -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id) +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id) { unsigned long flags; int action, cpu = irq - IPI0_IRQ; @@ -317,15 +366,13 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -#endif /* BMIPS type */ - -static void bmips_send_ipi_mask(const struct cpumask *mask, +static void bmips43xx_send_ipi_mask(const struct cpumask *mask, unsigned int action) { unsigned int i; for_each_cpu(i, mask) - bmips_send_ipi_single(i, action); + bmips43xx_send_ipi_single(i, action); } #ifdef CONFIG_HOTPLUG_CPU @@ -381,15 +428,30 @@ void __ref play_dead(void) #endif /* CONFIG_HOTPLUG_CPU */ -struct plat_smp_ops bmips_smp_ops = { +struct plat_smp_ops bmips43xx_smp_ops = { + .smp_setup = bmips_smp_setup, + .prepare_cpus = bmips_prepare_cpus, + .boot_secondary = bmips_boot_secondary, + .smp_finish = bmips_smp_finish, + .init_secondary = bmips_init_secondary, + .cpus_done = bmips_cpus_done, + .send_ipi_single = bmips43xx_send_ipi_single, + .send_ipi_mask = bmips43xx_send_ipi_mask, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = bmips_cpu_disable, + .cpu_die = bmips_cpu_die, +#endif +}; + +struct plat_smp_ops bmips5000_smp_ops = { .smp_setup = bmips_smp_setup, .prepare_cpus = bmips_prepare_cpus, .boot_secondary = bmips_boot_secondary, .smp_finish = bmips_smp_finish, .init_secondary = bmips_init_secondary, .cpus_done = bmips_cpus_done, - .send_ipi_single = bmips_send_ipi_single, - .send_ipi_mask = bmips_send_ipi_mask, + .send_ipi_single = bmips5000_send_ipi_single, + .send_ipi_mask = bmips5000_send_ipi_mask, #ifdef CONFIG_HOTPLUG_CPU .cpu_disable = bmips_cpu_disable, .cpu_die = bmips_cpu_die, @@ -427,43 +489,47 @@ void bmips_ebase_setup(void) BUG_ON(ebase != CKSEG0); -#if defined(CONFIG_CPU_BMIPS4350) - /* - * BMIPS4350 cannot relocate the normal vectors, but it - * can relocate the BEV=1 vectors. So CPU1 starts up at - * the relocated BEV=1, IV=0 general exception vector @ - * 0xa000_0380. - * - * set_uncached_handler() is used here because: - * - CPU1 will run this from uncached space - * - None of the cacheflush functions are set up yet - */ - set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0, - &bmips_smp_int_vec, 0x80); - __sync(); - return; -#elif defined(CONFIG_CPU_BMIPS4380) - /* - * 0x8000_0000: reset/NMI (initially in kseg1) - * 0x8000_0400: normal vectors - */ - new_ebase = 0x80000400; - cbr = BMIPS_GET_CBR(); - __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0); - __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1); -#elif defined(CONFIG_CPU_BMIPS5000) - /* - * 0x8000_0000: reset/NMI (initially in kseg1) - * 0x8000_1000: normal vectors - */ - new_ebase = 0x80001000; - write_c0_brcm_bootvec(0xa0088008); - write_c0_ebase(new_ebase); - if (max_cpus > 2) - bmips_write_zscm_reg(0xa0, 0xa008a008); -#else - return; -#endif + switch (current_cpu_type()) { + case CPU_BMIPS4350: + /* + * BMIPS4350 cannot relocate the normal vectors, but it + * can relocate the BEV=1 vectors. So CPU1 starts up at + * the relocated BEV=1, IV=0 general exception vector @ + * 0xa000_0380. + * + * set_uncached_handler() is used here because: + * - CPU1 will run this from uncached space + * - None of the cacheflush functions are set up yet + */ + set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0, + &bmips_smp_int_vec, 0x80); + __sync(); + return; + case CPU_BMIPS4380: + /* + * 0x8000_0000: reset/NMI (initially in kseg1) + * 0x8000_0400: normal vectors + */ + new_ebase = 0x80000400; + cbr = BMIPS_GET_CBR(); + __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0); + __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1); + break; + case CPU_BMIPS5000: + /* + * 0x8000_0000: reset/NMI (initially in kseg1) + * 0x8000_1000: normal vectors + */ + new_ebase = 0x80001000; + write_c0_brcm_bootvec(0xa0088008); + write_c0_ebase(new_ebase); + if (max_cpus > 2) + bmips_write_zscm_reg(0xa0, 0xa008a008); + break; + default: + return; + } + board_nmi_handler_setup = &bmips_nmi_handler_setup; ebase = new_ebase; } diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index 5969f1e9b62a..1b925d8a610c 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -199,11 +199,14 @@ void __init cmp_prepare_cpus(unsigned int max_cpus) pr_debug("SMPCMP: CPU%d: %s max_cpus=%d\n", smp_processor_id(), __func__, max_cpus); +#ifdef CONFIG_MIPS_MT /* * FIXME: some of these options are per-system, some per-core and * some per-cpu */ mips_mt_set_cpuoptions(); +#endif + } struct plat_smp_ops cmp_smp_ops = { diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 57a3f7a2b370..0fb8cefc9114 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -71,6 +71,7 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0, /* Record this as available CPU */ set_cpu_possible(tc, true); + set_cpu_present(tc, true); __cpu_number_map[tc] = ++ncpu; __cpu_logical_map[ncpu] = tc; } @@ -112,12 +113,39 @@ static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0) write_tc_c0_tchalt(TCHALT_H); } +#ifdef CONFIG_IRQ_GIC +static void mp_send_ipi_single(int cpu, unsigned int action) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (action) { + case SMP_CALL_FUNCTION: + gic_send_ipi(plat_ipi_call_int_xlate(cpu)); + break; + + case SMP_RESCHEDULE_YOURSELF: + gic_send_ipi(plat_ipi_resched_int_xlate(cpu)); + break; + } + + local_irq_restore(flags); +} +#endif + static void vsmp_send_ipi_single(int cpu, unsigned int action) { int i; unsigned long flags; int vpflags; +#ifdef CONFIG_IRQ_GIC + if (gic_present) { + mp_send_ipi_single(cpu, action); + return; + } +#endif local_irq_save(flags); vpflags = dvpe(); /* can't access the other CPU's registers whilst MVPE enabled */ diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c index 93f86817f20a..b242e2c10ea0 100644 --- a/arch/mips/kernel/spram.c +++ b/arch/mips/kernel/spram.c @@ -8,7 +8,6 @@ * * Copyright (C) 2007, 2008 MIPS Technologies, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/ptrace.h> #include <linux/stddef.h> @@ -206,6 +205,8 @@ void spram_config(void) case CPU_34K: case CPU_74K: case CPU_1004K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: config0 = read_c0_config(); /* FIXME: addresses are Malta specific */ if (config0 & (1<<24)) { diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 84536bf4a154..c24ad5f4b324 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -11,7 +11,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/irqflags.h> #include <linux/cpumask.h> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index f9c8746be8d6..e0b499694d18 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -78,6 +78,7 @@ extern asmlinkage void handle_cpu(void); extern asmlinkage void handle_ov(void); extern asmlinkage void handle_tr(void); extern asmlinkage void handle_fpe(void); +extern asmlinkage void handle_ftlb(void); extern asmlinkage void handle_mdmx(void); extern asmlinkage void handle_watch(void); extern asmlinkage void handle_mt(void); @@ -1080,7 +1081,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) unsigned long old_epc, old31; unsigned int opcode; unsigned int cpid; - int status; + int status, err; unsigned long __maybe_unused flags; prev_state = exception_enter(); @@ -1153,19 +1154,19 @@ asmlinkage void do_cpu(struct pt_regs *regs) case 1: if (used_math()) /* Using the FPU again. */ - own_fpu(1); + err = own_fpu(1); else { /* First time FPU user. */ - init_fpu(); + err = init_fpu(); set_used_math(); } - if (!raw_cpu_has_fpu) { + 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)) + if (!process_fpemu_return(sig, fault_addr) && !err) mt_ase_fp_affinity(); } @@ -1336,6 +1337,8 @@ static inline void parity_protection_init(void) case CPU_34K: case CPU_74K: case CPU_1004K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: { #define ERRCTL_PE 0x80000000 #define ERRCTL_L2P 0x00800000 @@ -1425,14 +1428,27 @@ asmlinkage void cache_parity_error(void) printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", reg_val & (1<<30) ? "secondary" : "primary", reg_val & (1<<31) ? "data" : "insn"); - printk("Error bits: %s%s%s%s%s%s%s\n", - reg_val & (1<<29) ? "ED " : "", - reg_val & (1<<28) ? "ET " : "", - reg_val & (1<<26) ? "EE " : "", - reg_val & (1<<25) ? "EB " : "", - reg_val & (1<<24) ? "EI " : "", - reg_val & (1<<23) ? "E1 " : "", - reg_val & (1<<22) ? "E0 " : ""); + if (cpu_has_mips_r2 && + ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + pr_err("Error bits: %s%s%s%s%s%s%s%s\n", + reg_val & (1<<29) ? "ED " : "", + reg_val & (1<<28) ? "ET " : "", + reg_val & (1<<27) ? "ES " : "", + reg_val & (1<<26) ? "EE " : "", + reg_val & (1<<25) ? "EB " : "", + reg_val & (1<<24) ? "EI " : "", + reg_val & (1<<23) ? "E1 " : "", + reg_val & (1<<22) ? "E0 " : ""); + } else { + pr_err("Error bits: %s%s%s%s%s%s%s\n", + reg_val & (1<<29) ? "ED " : "", + reg_val & (1<<28) ? "ET " : "", + reg_val & (1<<26) ? "EE " : "", + reg_val & (1<<25) ? "EB " : "", + reg_val & (1<<24) ? "EI " : "", + reg_val & (1<<23) ? "E1 " : "", + reg_val & (1<<22) ? "E0 " : ""); + } printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) @@ -1446,6 +1462,34 @@ asmlinkage void cache_parity_error(void) panic("Can't handle the cache error!"); } +asmlinkage void do_ftlb(void) +{ + const int field = 2 * sizeof(unsigned long); + unsigned int reg_val; + + /* For the moment, report the problem and hang. */ + if (cpu_has_mips_r2 && + ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) { + pr_err("FTLB error exception, cp0_ecc=0x%08x:\n", + read_c0_ecc()); + pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); + reg_val = read_c0_cacheerr(); + pr_err("c0_cacheerr == %08x\n", reg_val); + + if ((reg_val & 0xc0000000) == 0xc0000000) { + pr_err("Decoded c0_cacheerr: FTLB parity error\n"); + } else { + pr_err("Decoded c0_cacheerr: %s cache fault in %s reference.\n", + reg_val & (1<<30) ? "secondary" : "primary", + reg_val & (1<<31) ? "data" : "insn"); + } + } else { + pr_err("FTLB error exception\n"); + } + /* Just print the cacheerr bits for now */ + cache_parity_error(); +} + /* * SDBBP EJTAG debug exception handler. * We skip the instruction and return to the next instruction. @@ -1995,6 +2039,7 @@ void __init trap_init(void) if (cpu_has_fpu && !cpu_has_nofpuex) set_except_vector(15, handle_fpe); + set_except_vector(16, handle_ftlb); set_except_vector(22, handle_mdmx); if (cpu_has_mcheck) diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c new file mode 100644 index 000000000000..9268ebc0f61e --- /dev/null +++ b/arch/mips/kernel/vpe-cmp.c @@ -0,0 +1,180 @@ +/* + * 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) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/export.h> + +#include <asm/vpe.h> + +static int major; + +void cleanup_tc(struct tc *tc) +{ + +} + +static ssize_t store_kill(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + struct vpe_notifications *notifier; + + list_for_each_entry(notifier, &vpe->notify, list) + notifier->stop(aprp_cpu_index()); + + release_progmem(vpe->load_addr); + vpe->state = VPE_STATE_UNUSED; + + return len; +} +static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill); + +static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr, + char *buf) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + + return sprintf(buf, "%d\n", vpe->ntcs); +} + +static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + unsigned long new; + int ret; + + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; + + /* APRP can only reserve one TC in a VPE and no more. */ + if (new != 1) + return -EINVAL; + + vpe->ntcs = new; + + return len; +} +static DEVICE_ATTR_RW(ntcs); + +static struct attribute *vpe_attrs[] = { + &dev_attr_kill.attr, + &dev_attr_ntcs.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vpe); + +static void vpe_device_release(struct device *cd) +{ + kfree(cd); +} + +static struct class vpe_class = { + .name = "vpe", + .owner = THIS_MODULE, + .dev_release = vpe_device_release, + .dev_groups = vpe_groups, +}; + +static struct device vpe_device; + +int __init vpe_module_init(void) +{ + struct vpe *v = NULL; + struct tc *t; + int err; + + if (!cpu_has_mipsmt) { + pr_warn("VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + if (num_possible_cpus() - aprp_cpu_index() < 1) { + pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxcpus=<n> argument as kernel argument\n"); + return -ENODEV; + } + + major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops); + if (major < 0) { + pr_warn("VPE loader: unable to register character device\n"); + return major; + } + + err = class_register(&vpe_class); + if (err) { + pr_err("vpe_class registration failed\n"); + goto out_chrdev; + } + + device_initialize(&vpe_device); + vpe_device.class = &vpe_class, + vpe_device.parent = NULL, + dev_set_name(&vpe_device, "vpe_sp"); + vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR); + err = device_add(&vpe_device); + if (err) { + pr_err("Adding vpe_device failed\n"); + goto out_class; + } + + t = alloc_tc(aprp_cpu_index()); + if (!t) { + pr_warn("VPE: unable to allocate TC\n"); + err = -ENOMEM; + goto out_dev; + } + + /* VPE */ + v = alloc_vpe(aprp_cpu_index()); + if (v == NULL) { + pr_warn("VPE: unable to allocate VPE\n"); + kfree(t); + err = -ENOMEM; + goto out_dev; + } + + v->ntcs = 1; + + /* add the tc to the list of this vpe's tc's. */ + list_add(&t->tc, &v->tc); + + /* TC */ + t->pvpe = v; /* set the parent vpe */ + + return 0; + +out_dev: + device_del(&vpe_device); + +out_class: + class_unregister(&vpe_class); + +out_chrdev: + unregister_chrdev(major, VPE_MODULE_NAME); + + return err; +} + +void __exit vpe_module_exit(void) +{ + struct vpe *v, *n; + + device_del(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + + /* No locking needed here */ + list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) + if (v->state != VPE_STATE_UNUSED) + release_vpe(v); +} diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c new file mode 100644 index 000000000000..949ae0e17018 --- /dev/null +++ b/arch/mips/kernel/vpe-mt.c @@ -0,0 +1,523 @@ +/* + * 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) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/export.h> + +#include <asm/mipsregs.h> +#include <asm/mipsmtregs.h> +#include <asm/mips_mt.h> +#include <asm/vpe.h> + +static int major; + +/* The number of TCs and VPEs physically available on the core */ +static int hw_tcs, hw_vpes; + +/* We are prepared so configure and start the VPE... */ +int vpe_run(struct vpe *v) +{ + unsigned long flags, val, dmt_flag; + struct vpe_notifications *notifier; + unsigned int vpeflags; + struct tc *t; + + /* check we are the Master VPE */ + local_irq_save(flags); + val = read_c0_vpeconf0(); + if (!(val & VPECONF0_MVP)) { + pr_warn("VPE loader: only Master VPE's are able to config MT\n"); + local_irq_restore(flags); + + return -1; + } + + dmt_flag = dmt(); + vpeflags = dvpe(); + + if (list_empty(&v->tc)) { + evpe(vpeflags); + emt(dmt_flag); + local_irq_restore(flags); + + pr_warn("VPE loader: No TC's associated with VPE %d\n", + v->minor); + + return -ENOEXEC; + } + + t = list_first_entry(&v->tc, struct tc, tc); + + /* Put MVPE's into 'configuration state' */ + set_c0_mvpcontrol(MVPCONTROL_VPC); + + settc(t->index); + + /* should check it is halted, and not activated */ + if ((read_tc_c0_tcstatus() & TCSTATUS_A) || + !(read_tc_c0_tchalt() & TCHALT_H)) { + evpe(vpeflags); + emt(dmt_flag); + local_irq_restore(flags); + + pr_warn("VPE loader: TC %d is already active!\n", + t->index); + + return -ENOEXEC; + } + + /* + * Write the address we want it to start running from in the TCPC + * register. + */ + write_tc_c0_tcrestart((unsigned long)v->__start); + write_tc_c0_tccontext((unsigned long)0); + + /* + * Mark the TC as activated, not interrupt exempt and not dynamically + * allocatable + */ + val = read_tc_c0_tcstatus(); + val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A; + write_tc_c0_tcstatus(val); + + write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H); + + /* + * The sde-kit passes 'memsize' to __start in $a3, so set something + * here... Or set $a3 to zero and define DFLT_STACK_SIZE and + * DFLT_HEAP_SIZE when you compile your program + */ + mttgpr(6, v->ntcs); + mttgpr(7, physical_memsize); + + /* set up VPE1 */ + /* + * bind the TC to VPE 1 as late as possible so we only have the final + * VPE registers to set up, and so an EJTAG probe can trigger on it + */ + write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1); + + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA)); + + back_to_back_c0_hazard(); + + /* Set up the XTC bit in vpeconf0 to point at our tc */ + write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) + | (t->index << VPECONF0_XTC_SHIFT)); + + back_to_back_c0_hazard(); + + /* enable this VPE */ + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); + + /* clear out any left overs from a previous program */ + write_vpe_c0_status(0); + write_vpe_c0_cause(0); + + /* take system out of configuration state */ + clear_c0_mvpcontrol(MVPCONTROL_VPC); + + /* + * SMTC/SMVP kernels manage VPE enable independently, + * but uniprocessor kernels need to turn it on, even + * if that wasn't the pre-dvpe() state. + */ +#ifdef CONFIG_SMP + evpe(vpeflags); +#else + evpe(EVPE_ENABLE); +#endif + emt(dmt_flag); + local_irq_restore(flags); + + list_for_each_entry(notifier, &v->notify, list) + notifier->start(VPE_MODULE_MINOR); + + return 0; +} + +void cleanup_tc(struct tc *tc) +{ + unsigned long flags; + unsigned int mtflags, vpflags; + int tmp; + + local_irq_save(flags); + mtflags = dmt(); + vpflags = dvpe(); + /* Put MVPE's into 'configuration state' */ + set_c0_mvpcontrol(MVPCONTROL_VPC); + + settc(tc->index); + tmp = read_tc_c0_tcstatus(); + + /* mark not allocated and not dynamically allocatable */ + tmp &= ~(TCSTATUS_A | TCSTATUS_DA); + tmp |= TCSTATUS_IXMT; /* interrupt exempt */ + write_tc_c0_tcstatus(tmp); + + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + + clear_c0_mvpcontrol(MVPCONTROL_VPC); + evpe(vpflags); + emt(mtflags); + local_irq_restore(flags); +} + +/* module wrapper entry points */ +/* give me a vpe */ +void *vpe_alloc(void) +{ + int i; + struct vpe *v; + + /* find a vpe */ + for (i = 1; i < MAX_VPES; i++) { + v = get_vpe(i); + if (v != NULL) { + v->state = VPE_STATE_INUSE; + return v; + } + } + return NULL; +} +EXPORT_SYMBOL(vpe_alloc); + +/* start running from here */ +int vpe_start(void *vpe, unsigned long start) +{ + struct vpe *v = vpe; + + v->__start = start; + return vpe_run(v); +} +EXPORT_SYMBOL(vpe_start); + +/* halt it for now */ +int vpe_stop(void *vpe) +{ + struct vpe *v = vpe; + struct tc *t; + unsigned int evpe_flags; + + evpe_flags = dvpe(); + + t = list_entry(v->tc.next, struct tc, tc); + if (t != NULL) { + settc(t->index); + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); + } + + evpe(evpe_flags); + + return 0; +} +EXPORT_SYMBOL(vpe_stop); + +/* I've done with it thank you */ +int vpe_free(void *vpe) +{ + struct vpe *v = vpe; + struct tc *t; + unsigned int evpe_flags; + + t = list_entry(v->tc.next, struct tc, tc); + if (t == NULL) + return -ENOEXEC; + + evpe_flags = dvpe(); + + /* Put MVPE's into 'configuration state' */ + set_c0_mvpcontrol(MVPCONTROL_VPC); + + settc(t->index); + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); + + /* halt the TC */ + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + + /* mark the TC unallocated */ + write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); + + v->state = VPE_STATE_UNUSED; + + clear_c0_mvpcontrol(MVPCONTROL_VPC); + evpe(evpe_flags); + + return 0; +} +EXPORT_SYMBOL(vpe_free); + +static ssize_t store_kill(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + struct vpe_notifications *notifier; + + list_for_each_entry(notifier, &vpe->notify, list) + notifier->stop(aprp_cpu_index()); + + release_progmem(vpe->load_addr); + cleanup_tc(get_tc(aprp_cpu_index())); + vpe_stop(vpe); + vpe_free(vpe); + + return len; +} +static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill); + +static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr, + char *buf) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + + return sprintf(buf, "%d\n", vpe->ntcs); +} + +static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(aprp_cpu_index()); + unsigned long new; + int ret; + + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; + + if (new == 0 || new > (hw_tcs - aprp_cpu_index())) + return -EINVAL; + + vpe->ntcs = new; + + return len; +} +static DEVICE_ATTR_RW(ntcs); + +static struct attribute *vpe_attrs[] = { + &dev_attr_kill.attr, + &dev_attr_ntcs.attr, + NULL, +}; +ATTRIBUTE_GROUPS(vpe); + +static void vpe_device_release(struct device *cd) +{ + kfree(cd); +} + +static struct class vpe_class = { + .name = "vpe", + .owner = THIS_MODULE, + .dev_release = vpe_device_release, + .dev_groups = vpe_groups, +}; + +static struct device vpe_device; + +int __init vpe_module_init(void) +{ + unsigned int mtflags, vpflags; + unsigned long flags, val; + struct vpe *v = NULL; + struct tc *t; + int tc, err; + + if (!cpu_has_mipsmt) { + pr_warn("VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + if (vpelimit == 0) { + pr_warn("No VPEs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxvpes=<n> argument as kernel argument\n"); + + return -ENODEV; + } + + if (aprp_cpu_index() == 0) { + pr_warn("No TCs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxtcs=<n> argument as kernel argument\n"); + + return -ENODEV; + } + + major = register_chrdev(0, VPE_MODULE_NAME, &vpe_fops); + if (major < 0) { + pr_warn("VPE loader: unable to register character device\n"); + return major; + } + + err = class_register(&vpe_class); + if (err) { + pr_err("vpe_class registration failed\n"); + goto out_chrdev; + } + + device_initialize(&vpe_device); + vpe_device.class = &vpe_class, + vpe_device.parent = NULL, + dev_set_name(&vpe_device, "vpe1"); + vpe_device.devt = MKDEV(major, VPE_MODULE_MINOR); + err = device_add(&vpe_device); + if (err) { + pr_err("Adding vpe_device failed\n"); + goto out_class; + } + + local_irq_save(flags); + mtflags = dmt(); + vpflags = dvpe(); + + /* Put MVPE's into 'configuration state' */ + set_c0_mvpcontrol(MVPCONTROL_VPC); + + val = read_c0_mvpconf0(); + hw_tcs = (val & MVPCONF0_PTC) + 1; + hw_vpes = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; + + for (tc = aprp_cpu_index(); tc < hw_tcs; tc++) { + /* + * Must re-enable multithreading temporarily or in case we + * reschedule send IPIs or similar we might hang. + */ + clear_c0_mvpcontrol(MVPCONTROL_VPC); + evpe(vpflags); + emt(mtflags); + local_irq_restore(flags); + t = alloc_tc(tc); + if (!t) { + err = -ENOMEM; + goto out_dev; + } + + local_irq_save(flags); + mtflags = dmt(); + vpflags = dvpe(); + set_c0_mvpcontrol(MVPCONTROL_VPC); + + /* VPE's */ + if (tc < hw_tcs) { + settc(tc); + + v = alloc_vpe(tc); + if (v == NULL) { + pr_warn("VPE: unable to allocate VPE\n"); + goto out_reenable; + } + + v->ntcs = hw_tcs - aprp_cpu_index(); + + /* add the tc to the list of this vpe's tc's. */ + list_add(&t->tc, &v->tc); + + /* deactivate all but vpe0 */ + if (tc >= aprp_cpu_index()) { + unsigned long tmp = read_vpe_c0_vpeconf0(); + + tmp &= ~VPECONF0_VPA; + + /* master VPE */ + tmp |= VPECONF0_MVP; + write_vpe_c0_vpeconf0(tmp); + } + + /* disable multi-threading with TC's */ + write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & + ~VPECONTROL_TE); + + if (tc >= vpelimit) { + /* + * Set config to be the same as vpe0, + * particularly kseg0 coherency alg + */ + write_vpe_c0_config(read_c0_config()); + } + } + + /* TC's */ + t->pvpe = v; /* set the parent vpe */ + + if (tc >= aprp_cpu_index()) { + unsigned long tmp; + + settc(tc); + + /* Any TC that is bound to VPE0 gets left as is - in + * case we are running SMTC on VPE0. A TC that is bound + * to any other VPE gets bound to VPE0, ideally I'd like + * to make it homeless but it doesn't appear to let me + * bind a TC to a non-existent VPE. Which is perfectly + * reasonable. + * + * The (un)bound state is visible to an EJTAG probe so + * may notify GDB... + */ + tmp = read_tc_c0_tcbind(); + if (tmp & TCBIND_CURVPE) { + /* tc is bound >vpe0 */ + write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE); + + t->pvpe = get_vpe(0); /* set the parent vpe */ + } + + /* halt the TC */ + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + + tmp = read_tc_c0_tcstatus(); + + /* mark not activated and not dynamically allocatable */ + tmp &= ~(TCSTATUS_A | TCSTATUS_DA); + tmp |= TCSTATUS_IXMT; /* interrupt exempt */ + write_tc_c0_tcstatus(tmp); + } + } + +out_reenable: + /* release config state */ + clear_c0_mvpcontrol(MVPCONTROL_VPC); + + evpe(vpflags); + emt(mtflags); + local_irq_restore(flags); + + return 0; + +out_dev: + device_del(&vpe_device); + +out_class: + class_unregister(&vpe_class); + +out_chrdev: + unregister_chrdev(major, VPE_MODULE_NAME); + + return err; +} + +void __exit vpe_module_exit(void) +{ + struct vpe *v, *n; + + device_del(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + + /* No locking needed here */ + list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) { + if (v->state != VPE_STATE_UNUSED) + release_vpe(v); + } +} diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 2d5c142bad67..11da314565cc 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1,37 +1,22 @@ /* - * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ - -/* - * VPE support module + * 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. * - * Provides support for loading a MIPS SP program on VPE1. - * The SP environment is rather simple, no tlb's. It needs to be relocatable - * (or partially linked). You should initialise your stack in the startup - * code. This loader looks for the symbol __start and sets up - * execution to resume from there. The MIPS SDE kit contains suitable examples. + * Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. * - * To load and run, simply cat a SP 'program file' to /dev/vpe1. - * i.e cat spapp >/dev/vpe1. + * VPE spport module for loading a MIPS SP program into VPE1. The SP + * environment is rather simple since there are no TLBs. It needs + * to be relocatable (or partiall linked). Initialize your stack in + * the startup-code. The loader looks for the symbol __start and sets + * up the execution to resume from there. To load and run, simply do + * a cat SP 'binary' to the /dev/vpe1 device. */ #include <linux/kernel.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/init.h> -#include <asm/uaccess.h> #include <linux/slab.h> #include <linux/list.h> #include <linux/vmalloc.h> @@ -46,13 +31,10 @@ #include <asm/mipsmtregs.h> #include <asm/cacheflush.h> #include <linux/atomic.h> -#include <asm/cpu.h> #include <asm/mips_mt.h> #include <asm/processor.h> #include <asm/vpe.h> -typedef void *vpe_handle; - #ifndef ARCH_SHF_SMALL #define ARCH_SHF_SMALL 0 #endif @@ -60,95 +42,15 @@ typedef void *vpe_handle; /* If this is set, the section belongs in the init part of the module */ #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) -/* - * The number of TCs and VPEs physically available on the core - */ -static int hw_tcs, hw_vpes; -static char module_name[] = "vpe"; -static int major; -static const int minor = 1; /* fixed for now */ - -/* grab the likely amount of memory we will need. */ -#ifdef CONFIG_MIPS_VPE_LOADER_TOM -#define P_SIZE (2 * 1024 * 1024) -#else -/* add an overhead to the max kmalloc size for non-striped symbols/etc */ -#define P_SIZE (256 * 1024) -#endif - -extern unsigned long physical_memsize; - -#define MAX_VPES 16 -#define VPE_PATH_MAX 256 - -enum vpe_state { - VPE_STATE_UNUSED = 0, - VPE_STATE_INUSE, - VPE_STATE_RUNNING -}; - -enum tc_state { - TC_STATE_UNUSED = 0, - TC_STATE_INUSE, - TC_STATE_RUNNING, - TC_STATE_DYNAMIC -}; - -struct vpe { - enum vpe_state state; - - /* (device) minor associated with this vpe */ - int minor; - - /* elfloader stuff */ - void *load_addr; - unsigned long len; - char *pbuffer; - unsigned long plen; - char cwd[VPE_PATH_MAX]; - - unsigned long __start; - - /* tc's associated with this vpe */ - struct list_head tc; - - /* The list of vpe's */ - struct list_head list; - - /* shared symbol address */ - void *shared_ptr; - - /* the list of who wants to know when something major happens */ - struct list_head notify; - - unsigned int ntcs; -}; - -struct tc { - enum tc_state state; - int index; - - struct vpe *pvpe; /* parent VPE */ - struct list_head tc; /* The list of TC's with this VPE */ - struct list_head list; /* The global list of tc's */ -}; - -struct { - spinlock_t vpe_list_lock; - struct list_head vpe_list; /* Virtual processing elements */ - spinlock_t tc_list_lock; - struct list_head tc_list; /* Thread contexts */ -} vpecontrol = { +struct vpe_control vpecontrol = { .vpe_list_lock = __SPIN_LOCK_UNLOCKED(vpe_list_lock), .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), .tc_list_lock = __SPIN_LOCK_UNLOCKED(tc_list_lock), .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) }; -static void release_progmem(void *ptr); - /* get the vpe associated with this minor */ -static struct vpe *get_vpe(int minor) +struct vpe *get_vpe(int minor) { struct vpe *res, *v; @@ -158,7 +60,7 @@ static struct vpe *get_vpe(int minor) res = NULL; spin_lock(&vpecontrol.vpe_list_lock); list_for_each_entry(v, &vpecontrol.vpe_list, list) { - if (v->minor == minor) { + if (v->minor == VPE_MODULE_MINOR) { res = v; break; } @@ -169,7 +71,7 @@ static struct vpe *get_vpe(int minor) } /* get the vpe associated with this minor */ -static struct tc *get_tc(int index) +struct tc *get_tc(int index) { struct tc *res, *t; @@ -187,12 +89,13 @@ static struct tc *get_tc(int index) } /* allocate a vpe and associate it with this minor (or index) */ -static struct vpe *alloc_vpe(int minor) +struct vpe *alloc_vpe(int minor) { struct vpe *v; - if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) - return NULL; + v = kzalloc(sizeof(struct vpe), GFP_KERNEL); + if (v == NULL) + goto out; INIT_LIST_HEAD(&v->tc); spin_lock(&vpecontrol.vpe_list_lock); @@ -200,17 +103,19 @@ static struct vpe *alloc_vpe(int minor) spin_unlock(&vpecontrol.vpe_list_lock); INIT_LIST_HEAD(&v->notify); - v->minor = minor; + v->minor = VPE_MODULE_MINOR; +out: return v; } /* allocate a tc. At startup only tc0 is running, all other can be halted. */ -static struct tc *alloc_tc(int index) +struct tc *alloc_tc(int index) { struct tc *tc; - if ((tc = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) + tc = kzalloc(sizeof(struct tc), GFP_KERNEL); + if (tc == NULL) goto out; INIT_LIST_HEAD(&tc->tc); @@ -225,7 +130,7 @@ out: } /* clean up and free everything */ -static void release_vpe(struct vpe *v) +void release_vpe(struct vpe *v) { list_del(&v->list); if (v->load_addr) @@ -233,28 +138,8 @@ static void release_vpe(struct vpe *v) kfree(v); } -static void __maybe_unused dump_mtregs(void) -{ - unsigned long val; - - val = read_c0_config3(); - printk("config3 0x%lx MT %ld\n", val, - (val & CONFIG3_MT) >> CONFIG3_MT_SHIFT); - - val = read_c0_mvpcontrol(); - printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val, - (val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT, - (val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT, - (val & MVPCONTROL_EVP)); - - val = read_c0_mvpconf0(); - printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val, - (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT, - val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT); -} - -/* Find some VPE program space */ -static void *alloc_progmem(unsigned long len) +/* Find some VPE program space */ +void *alloc_progmem(unsigned long len) { void *addr; @@ -273,7 +158,7 @@ static void *alloc_progmem(unsigned long len) return addr; } -static void release_progmem(void *ptr) +void release_progmem(void *ptr) { #ifndef CONFIG_MIPS_VPE_LOADER_TOM kfree(ptr); @@ -281,7 +166,7 @@ static void release_progmem(void *ptr) } /* Update size with this section: return offset. */ -static long get_offset(unsigned long *size, Elf_Shdr * sechdr) +static long get_offset(unsigned long *size, Elf_Shdr *sechdr) { long ret; @@ -294,8 +179,8 @@ static long get_offset(unsigned long *size, Elf_Shdr * sechdr) might -- code, read-only data, read-write data, small data. Tally sizes, and place the offsets into sh_entsize fields: high bit means it belongs in init. */ -static void layout_sections(struct module *mod, const Elf_Ehdr * hdr, - Elf_Shdr * sechdrs, const char *secstrings) +static void layout_sections(struct module *mod, const Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, const char *secstrings) { static unsigned long const masks[][2] = { /* NOTE: all executable code must be the first section @@ -315,7 +200,6 @@ static void layout_sections(struct module *mod, const Elf_Ehdr * hdr, for (i = 0; i < hdr->e_shnum; ++i) { Elf_Shdr *s = &sechdrs[i]; - // || strncmp(secstrings + s->sh_name, ".init", 5) == 0) if ((s->sh_flags & masks[m][0]) != masks[m][0] || (s->sh_flags & masks[m][1]) || s->sh_entsize != ~0UL) @@ -330,7 +214,6 @@ static void layout_sections(struct module *mod, const Elf_Ehdr * hdr, } } - /* from module-elf32.c, but subverted a little */ struct mips_hi16 { @@ -353,20 +236,18 @@ static int apply_r_mips_gprel16(struct module *me, uint32_t *location, { int rel; - if( !(*location & 0xffff) ) { + if (!(*location & 0xffff)) { rel = (int)v - gp_addr; - } - else { + } else { /* .sbss + gp(relative) + offset */ /* kludge! */ rel = (int)(short)((int)v + gp_offs + (int)(short)(*location & 0xffff) - gp_addr); } - if( (rel > 32768) || (rel < -32768) ) { - printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: " - "relative address 0x%x out of range of gp register\n", - rel); + if ((rel > 32768) || (rel < -32768)) { + pr_debug("VPE loader: apply_r_mips_gprel16: relative address 0x%x out of range of gp register\n", + rel); return -ENOEXEC; } @@ -380,12 +261,12 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location, { int rel; rel = (((unsigned int)v - (unsigned int)location)); - rel >>= 2; // because the offset is in _instructions_ not bytes. - rel -= 1; // and one instruction less due to the branch delay slot. + rel >>= 2; /* because the offset is in _instructions_ not bytes. */ + rel -= 1; /* and one instruction less due to the branch delay slot. */ - if( (rel > 32768) || (rel < -32768) ) { - printk(KERN_DEBUG "VPE loader: " - "apply_r_mips_pc16: relative address out of range 0x%x\n", rel); + if ((rel > 32768) || (rel < -32768)) { + pr_debug("VPE loader: apply_r_mips_pc16: relative address out of range 0x%x\n", + rel); return -ENOEXEC; } @@ -406,8 +287,7 @@ static int apply_r_mips_26(struct module *me, uint32_t *location, Elf32_Addr v) { if (v % 4) { - printk(KERN_DEBUG "VPE loader: apply_r_mips_26 " - " unaligned relocation\n"); + pr_debug("VPE loader: apply_r_mips_26: unaligned relocation\n"); return -ENOEXEC; } @@ -438,7 +318,7 @@ static int apply_r_mips_hi16(struct module *me, uint32_t *location, * the carry we need to add. Save the information, and let LO16 do the * actual relocation. */ - n = kmalloc(sizeof *n, GFP_KERNEL); + n = kmalloc(sizeof(*n), GFP_KERNEL); if (!n) return -ENOMEM; @@ -470,9 +350,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, * The value for the HI16 had best be the same. */ if (v != l->value) { - printk(KERN_DEBUG "VPE loader: " - "apply_r_mips_lo16/hi16: \t" - "inconsistent value information\n"); + pr_debug("VPE loader: apply_r_mips_lo16/hi16: inconsistent value information\n"); goto out_free; } @@ -568,20 +446,19 @@ static int apply_relocations(Elf32_Shdr *sechdrs, + ELF32_R_SYM(r_info); if (!sym->st_value) { - printk(KERN_DEBUG "%s: undefined weak symbol %s\n", - me->name, strtab + sym->st_name); + pr_debug("%s: undefined weak symbol %s\n", + me->name, strtab + sym->st_name); /* just print the warning, dont barf */ } v = sym->st_value; res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v); - if( res ) { + if (res) { char *r = rstrs[ELF32_R_TYPE(r_info)]; - printk(KERN_WARNING "VPE loader: .text+0x%x " - "relocation type %s for symbol \"%s\" failed\n", - rel[i].r_offset, r ? r : "UNKNOWN", - strtab + sym->st_name); + pr_warn("VPE loader: .text+0x%x relocation type %s for symbol \"%s\" failed\n", + rel[i].r_offset, r ? r : "UNKNOWN", + strtab + sym->st_name); return res; } } @@ -596,10 +473,8 @@ static inline void save_gp_address(unsigned int secbase, unsigned int rel) } /* end module-elf32.c */ - - /* Change all symbols so that sh_value encodes the pointer directly. */ -static void simplify_symbols(Elf_Shdr * sechdrs, +static void simplify_symbols(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, const char *secstrings, @@ -640,18 +515,16 @@ static void simplify_symbols(Elf_Shdr * sechdrs, break; case SHN_MIPS_SCOMMON: - printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON " - "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name, - sym[i].st_shndx); - // .sbss section + pr_debug("simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n", + strtab + sym[i].st_name, sym[i].st_shndx); + /* .sbss section */ break; default: secbase = sechdrs[sym[i].st_shndx].sh_addr; - if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0) { + if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0) save_gp_address(secbase, sym[i].st_value); - } sym[i].st_value += secbase; break; @@ -660,142 +533,21 @@ static void simplify_symbols(Elf_Shdr * sechdrs, } #ifdef DEBUG_ELFLOADER -static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex, +static void dump_elfsymbols(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, struct module *mod) { Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); - printk(KERN_DEBUG "dump_elfsymbols: n %d\n", n); + pr_debug("dump_elfsymbols: n %d\n", n); for (i = 1; i < n; i++) { - printk(KERN_DEBUG " i %d name <%s> 0x%x\n", i, - strtab + sym[i].st_name, sym[i].st_value); + pr_debug(" i %d name <%s> 0x%x\n", i, strtab + sym[i].st_name, + sym[i].st_value); } } #endif -/* We are prepared so configure and start the VPE... */ -static int vpe_run(struct vpe * v) -{ - unsigned long flags, val, dmt_flag; - struct vpe_notifications *n; - unsigned int vpeflags; - struct tc *t; - - /* check we are the Master VPE */ - local_irq_save(flags); - val = read_c0_vpeconf0(); - if (!(val & VPECONF0_MVP)) { - printk(KERN_WARNING - "VPE loader: only Master VPE's are allowed to configure MT\n"); - local_irq_restore(flags); - - return -1; - } - - dmt_flag = dmt(); - vpeflags = dvpe(); - - if (list_empty(&v->tc)) { - evpe(vpeflags); - emt(dmt_flag); - local_irq_restore(flags); - - printk(KERN_WARNING - "VPE loader: No TC's associated with VPE %d\n", - v->minor); - - return -ENOEXEC; - } - - t = list_first_entry(&v->tc, struct tc, tc); - - /* Put MVPE's into 'configuration state' */ - set_c0_mvpcontrol(MVPCONTROL_VPC); - - settc(t->index); - - /* should check it is halted, and not activated */ - if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) { - evpe(vpeflags); - emt(dmt_flag); - local_irq_restore(flags); - - printk(KERN_WARNING "VPE loader: TC %d is already active!\n", - t->index); - - return -ENOEXEC; - } - - /* Write the address we want it to start running from in the TCPC register. */ - write_tc_c0_tcrestart((unsigned long)v->__start); - write_tc_c0_tccontext((unsigned long)0); - - /* - * Mark the TC as activated, not interrupt exempt and not dynamically - * allocatable - */ - val = read_tc_c0_tcstatus(); - val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A; - write_tc_c0_tcstatus(val); - - write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H); - - /* - * The sde-kit passes 'memsize' to __start in $a3, so set something - * here... Or set $a3 to zero and define DFLT_STACK_SIZE and - * DFLT_HEAP_SIZE when you compile your program - */ - mttgpr(6, v->ntcs); - mttgpr(7, physical_memsize); - - /* set up VPE1 */ - /* - * bind the TC to VPE 1 as late as possible so we only have the final - * VPE registers to set up, and so an EJTAG probe can trigger on it - */ - write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1); - - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA)); - - back_to_back_c0_hazard(); - - /* Set up the XTC bit in vpeconf0 to point at our tc */ - write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) - | (t->index << VPECONF0_XTC_SHIFT)); - - back_to_back_c0_hazard(); - - /* enable this VPE */ - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); - - /* clear out any left overs from a previous program */ - write_vpe_c0_status(0); - write_vpe_c0_cause(0); - - /* take system out of configuration state */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); - - /* - * SMTC/SMVP kernels manage VPE enable independently, - * but uniprocessor kernels need to turn it on, even - * if that wasn't the pre-dvpe() state. - */ -#ifdef CONFIG_SMP - evpe(vpeflags); -#else - evpe(EVPE_ENABLE); -#endif - emt(dmt_flag); - local_irq_restore(flags); - - list_for_each_entry(n, &v->notify, list) - n->start(minor); - - return 0; -} - -static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, +static int find_vpe_symbols(struct vpe *v, Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, struct module *mod) { @@ -803,16 +555,14 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); for (i = 1; i < n; i++) { - if (strcmp(strtab + sym[i].st_name, "__start") == 0) { + if (strcmp(strtab + sym[i].st_name, "__start") == 0) v->__start = sym[i].st_value; - } - if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0) { + if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0) v->shared_ptr = (void *)sym[i].st_value; - } } - if ( (v->__start == 0) || (v->shared_ptr == NULL)) + if ((v->__start == 0) || (v->shared_ptr == NULL)) return -1; return 0; @@ -823,14 +573,14 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, * contents of the program (p)buffer performing relocatations/etc, free's it * when finished. */ -static int vpe_elfload(struct vpe * v) +static int vpe_elfload(struct vpe *v) { Elf_Ehdr *hdr; Elf_Shdr *sechdrs; long err = 0; char *secstrings, *strtab = NULL; unsigned int len, i, symindex = 0, strindex = 0, relocate = 0; - struct module mod; // so we can re-use the relocations code + struct module mod; /* so we can re-use the relocations code */ memset(&mod, 0, sizeof(struct module)); strcpy(mod.name, "VPE loader"); @@ -844,8 +594,7 @@ static int vpe_elfload(struct vpe * v) || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC) || !elf_check_arch(hdr) || hdr->e_shentsize != sizeof(*sechdrs)) { - printk(KERN_WARNING - "VPE loader: program wrong arch or weird elf version\n"); + pr_warn("VPE loader: program wrong arch or weird elf version\n"); return -ENOEXEC; } @@ -854,8 +603,7 @@ static int vpe_elfload(struct vpe * v) relocate = 1; if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) { - printk(KERN_ERR "VPE loader: program length %u truncated\n", - len); + pr_err("VPE loader: program length %u truncated\n", len); return -ENOEXEC; } @@ -870,22 +618,24 @@ static int vpe_elfload(struct vpe * v) if (relocate) { for (i = 1; i < hdr->e_shnum; i++) { - if (sechdrs[i].sh_type != SHT_NOBITS - && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) { - printk(KERN_ERR "VPE program length %u truncated\n", + if ((sechdrs[i].sh_type != SHT_NOBITS) && + (len < sechdrs[i].sh_offset + sechdrs[i].sh_size)) { + pr_err("VPE program length %u truncated\n", len); return -ENOEXEC; } /* Mark all sections sh_addr with their address in the temporary image. */ - sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset; + sechdrs[i].sh_addr = (size_t) hdr + + sechdrs[i].sh_offset; /* Internal symbols and strings. */ if (sechdrs[i].sh_type == SHT_SYMTAB) { symindex = i; strindex = sechdrs[i].sh_link; - strtab = (char *)hdr + sechdrs[strindex].sh_offset; + strtab = (char *)hdr + + sechdrs[strindex].sh_offset; } } layout_sections(&mod, hdr, sechdrs, secstrings); @@ -912,8 +662,9 @@ static int vpe_elfload(struct vpe * v) /* Update sh_addr to point to copy in image. */ sechdrs[i].sh_addr = (unsigned long)dest; - printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n", - secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr); + pr_debug(" section sh_name %s sh_addr 0x%x\n", + secstrings + sechdrs[i].sh_name, + sechdrs[i].sh_addr); } /* Fix up syms, so that st_value is a pointer to location. */ @@ -934,17 +685,18 @@ static int vpe_elfload(struct vpe * v) continue; if (sechdrs[i].sh_type == SHT_REL) - err = apply_relocations(sechdrs, strtab, symindex, i, - &mod); + err = apply_relocations(sechdrs, strtab, + symindex, i, &mod); else if (sechdrs[i].sh_type == SHT_RELA) - err = apply_relocate_add(sechdrs, strtab, symindex, i, - &mod); + err = apply_relocate_add(sechdrs, strtab, + symindex, i, &mod); if (err < 0) return err; } } else { - struct elf_phdr *phdr = (struct elf_phdr *) ((char *)hdr + hdr->e_phoff); + struct elf_phdr *phdr = (struct elf_phdr *) + ((char *)hdr + hdr->e_phoff); for (i = 0; i < hdr->e_phnum; i++) { if (phdr->p_type == PT_LOAD) { @@ -962,11 +714,15 @@ static int vpe_elfload(struct vpe * v) if (sechdrs[i].sh_type == SHT_SYMTAB) { symindex = i; strindex = sechdrs[i].sh_link; - strtab = (char *)hdr + sechdrs[strindex].sh_offset; + strtab = (char *)hdr + + sechdrs[strindex].sh_offset; - /* mark the symtab's address for when we try to find the - magic symbols */ - sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset; + /* + * mark symtab's address for when we try + * to find the magic symbols + */ + sechdrs[i].sh_addr = (size_t) hdr + + sechdrs[i].sh_offset; } } } @@ -977,53 +733,19 @@ static int vpe_elfload(struct vpe * v) if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) { if (v->__start == 0) { - printk(KERN_WARNING "VPE loader: program does not contain " - "a __start symbol\n"); + pr_warn("VPE loader: program does not contain a __start symbol\n"); return -ENOEXEC; } if (v->shared_ptr == NULL) - printk(KERN_WARNING "VPE loader: " - "program does not contain vpe_shared symbol.\n" - " Unable to use AMVP (AP/SP) facilities.\n"); + pr_warn("VPE loader: program does not contain vpe_shared symbol.\n" + " Unable to use AMVP (AP/SP) facilities.\n"); } - printk(" elf loaded\n"); + pr_info(" elf loaded\n"); return 0; } -static void cleanup_tc(struct tc *tc) -{ - unsigned long flags; - unsigned int mtflags, vpflags; - int tmp; - - local_irq_save(flags); - mtflags = dmt(); - vpflags = dvpe(); - /* Put MVPE's into 'configuration state' */ - set_c0_mvpcontrol(MVPCONTROL_VPC); - - settc(tc->index); - tmp = read_tc_c0_tcstatus(); - - /* mark not allocated and not dynamically allocatable */ - tmp &= ~(TCSTATUS_A | TCSTATUS_DA); - tmp |= TCSTATUS_IXMT; /* interrupt exempt */ - write_tc_c0_tcstatus(tmp); - - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - - /* bind it to anything other than VPE1 */ -// write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE - - clear_c0_mvpcontrol(MVPCONTROL_VPC); - evpe(vpflags); - emt(mtflags); - local_irq_restore(flags); -} - static int getcwd(char *buff, int size) { mm_segment_t old_fs; @@ -1043,39 +765,39 @@ static int getcwd(char *buff, int size) static int vpe_open(struct inode *inode, struct file *filp) { enum vpe_state state; - struct vpe_notifications *not; + struct vpe_notifications *notifier; struct vpe *v; int ret; - if (minor != iminor(inode)) { + if (VPE_MODULE_MINOR != iminor(inode)) { /* assume only 1 device at the moment. */ - pr_warning("VPE loader: only vpe1 is supported\n"); + pr_warn("VPE loader: only vpe1 is supported\n"); return -ENODEV; } - if ((v = get_vpe(tclimit)) == NULL) { - pr_warning("VPE loader: unable to get vpe\n"); + v = get_vpe(aprp_cpu_index()); + if (v == NULL) { + pr_warn("VPE loader: unable to get vpe\n"); return -ENODEV; } state = xchg(&v->state, VPE_STATE_INUSE); if (state != VPE_STATE_UNUSED) { - printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); + pr_debug("VPE loader: tc in use dumping regs\n"); - list_for_each_entry(not, &v->notify, list) { - not->stop(tclimit); - } + list_for_each_entry(notifier, &v->notify, list) + notifier->stop(aprp_cpu_index()); release_progmem(v->load_addr); - cleanup_tc(get_tc(tclimit)); + cleanup_tc(get_tc(aprp_cpu_index())); } /* this of-course trashes what was there before... */ v->pbuffer = vmalloc(P_SIZE); if (!v->pbuffer) { - pr_warning("VPE loader: unable to allocate memory\n"); + pr_warn("VPE loader: unable to allocate memory\n"); return -ENOMEM; } v->plen = P_SIZE; @@ -1085,7 +807,7 @@ static int vpe_open(struct inode *inode, struct file *filp) v->cwd[0] = 0; ret = getcwd(v->cwd, VPE_PATH_MAX); if (ret < 0) - printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret); + pr_warn("VPE loader: open, getcwd returned %d\n", ret); v->shared_ptr = NULL; v->__start = 0; @@ -1099,20 +821,20 @@ static int vpe_release(struct inode *inode, struct file *filp) Elf_Ehdr *hdr; int ret = 0; - v = get_vpe(tclimit); + v = get_vpe(aprp_cpu_index()); if (v == NULL) return -ENODEV; hdr = (Elf_Ehdr *) v->pbuffer; if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) == 0) { - if (vpe_elfload(v) >= 0) { + if ((vpe_elfload(v) >= 0) && vpe_run) { vpe_run(v); } else { - printk(KERN_WARNING "VPE loader: ELF load failed.\n"); + pr_warn("VPE loader: ELF load failed.\n"); ret = -ENOEXEC; } } else { - printk(KERN_WARNING "VPE loader: only elf files are supported\n"); + pr_warn("VPE loader: only elf files are supported\n"); ret = -ENOEXEC; } @@ -1130,22 +852,22 @@ static int vpe_release(struct inode *inode, struct file *filp) return ret; } -static ssize_t vpe_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) +static ssize_t vpe_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { size_t ret = count; struct vpe *v; - if (iminor(file_inode(file)) != minor) + if (iminor(file_inode(file)) != VPE_MODULE_MINOR) return -ENODEV; - v = get_vpe(tclimit); + v = get_vpe(aprp_cpu_index()); + if (v == NULL) return -ENODEV; if ((count + v->len) > v->plen) { - printk(KERN_WARNING - "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); + pr_warn("VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); return -ENOMEM; } @@ -1157,7 +879,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, return ret; } -static const struct file_operations vpe_fops = { +const struct file_operations vpe_fops = { .owner = THIS_MODULE, .open = vpe_open, .release = vpe_release, @@ -1165,396 +887,40 @@ static const struct file_operations vpe_fops = { .llseek = noop_llseek, }; -/* module wrapper entry points */ -/* give me a vpe */ -vpe_handle vpe_alloc(void) -{ - int i; - struct vpe *v; - - /* find a vpe */ - for (i = 1; i < MAX_VPES; i++) { - if ((v = get_vpe(i)) != NULL) { - v->state = VPE_STATE_INUSE; - return v; - } - } - return NULL; -} - -EXPORT_SYMBOL(vpe_alloc); - -/* start running from here */ -int vpe_start(vpe_handle vpe, unsigned long start) -{ - struct vpe *v = vpe; - - v->__start = start; - return vpe_run(v); -} - -EXPORT_SYMBOL(vpe_start); - -/* halt it for now */ -int vpe_stop(vpe_handle vpe) -{ - struct vpe *v = vpe; - struct tc *t; - unsigned int evpe_flags; - - evpe_flags = dvpe(); - - if ((t = list_entry(v->tc.next, struct tc, tc)) != NULL) { - - settc(t->index); - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); - } - - evpe(evpe_flags); - - return 0; -} - -EXPORT_SYMBOL(vpe_stop); - -/* I've done with it thank you */ -int vpe_free(vpe_handle vpe) -{ - struct vpe *v = vpe; - struct tc *t; - unsigned int evpe_flags; - - if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) { - return -ENOEXEC; - } - - evpe_flags = dvpe(); - - /* Put MVPE's into 'configuration state' */ - set_c0_mvpcontrol(MVPCONTROL_VPC); - - settc(t->index); - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); - - /* halt the TC */ - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - - /* mark the TC unallocated */ - write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); - - v->state = VPE_STATE_UNUSED; - - clear_c0_mvpcontrol(MVPCONTROL_VPC); - evpe(evpe_flags); - - return 0; -} - -EXPORT_SYMBOL(vpe_free); - void *vpe_get_shared(int index) { - struct vpe *v; + struct vpe *v = get_vpe(index); - if ((v = get_vpe(index)) == NULL) + if (v == NULL) return NULL; return v->shared_ptr; } - EXPORT_SYMBOL(vpe_get_shared); int vpe_notify(int index, struct vpe_notifications *notify) { - struct vpe *v; + struct vpe *v = get_vpe(index); - if ((v = get_vpe(index)) == NULL) + if (v == NULL) return -1; list_add(¬ify->list, &v->notify); return 0; } - EXPORT_SYMBOL(vpe_notify); char *vpe_getcwd(int index) { - struct vpe *v; + struct vpe *v = get_vpe(index); - if ((v = get_vpe(index)) == NULL) + if (v == NULL) return NULL; return v->cwd; } - EXPORT_SYMBOL(vpe_getcwd); -static ssize_t store_kill(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct vpe *vpe = get_vpe(tclimit); - struct vpe_notifications *not; - - list_for_each_entry(not, &vpe->notify, list) { - not->stop(tclimit); - } - - release_progmem(vpe->load_addr); - cleanup_tc(get_tc(tclimit)); - vpe_stop(vpe); - vpe_free(vpe); - - return len; -} -static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill); - -static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr, - char *buf) -{ - struct vpe *vpe = get_vpe(tclimit); - - return sprintf(buf, "%d\n", vpe->ntcs); -} - -static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ - struct vpe *vpe = get_vpe(tclimit); - unsigned long new; - char *endp; - - new = simple_strtoul(buf, &endp, 0); - if (endp == buf) - goto out_einval; - - if (new == 0 || new > (hw_tcs - tclimit)) - goto out_einval; - - vpe->ntcs = new; - - return len; - -out_einval: - return -EINVAL; -} -static DEVICE_ATTR_RW(ntcs); - -static struct attribute *vpe_attrs[] = { - &dev_attr_kill.attr, - &dev_attr_ntcs.attr, - NULL, -}; -ATTRIBUTE_GROUPS(vpe); - -static void vpe_device_release(struct device *cd) -{ - kfree(cd); -} - -struct class vpe_class = { - .name = "vpe", - .owner = THIS_MODULE, - .dev_release = vpe_device_release, - .dev_groups = vpe_groups, -}; - -struct device vpe_device; - -static int __init vpe_module_init(void) -{ - unsigned int mtflags, vpflags; - unsigned long flags, val; - struct vpe *v = NULL; - struct tc *t; - int tc, err; - - if (!cpu_has_mipsmt) { - printk("VPE loader: not a MIPS MT capable processor\n"); - return -ENODEV; - } - - if (vpelimit == 0) { - printk(KERN_WARNING "No VPEs reserved for AP/SP, not " - "initializing VPE loader.\nPass maxvpes=<n> argument as " - "kernel argument\n"); - - return -ENODEV; - } - - if (tclimit == 0) { - printk(KERN_WARNING "No TCs reserved for AP/SP, not " - "initializing VPE loader.\nPass maxtcs=<n> argument as " - "kernel argument\n"); - - return -ENODEV; - } - - major = register_chrdev(0, module_name, &vpe_fops); - if (major < 0) { - printk("VPE loader: unable to register character device\n"); - return major; - } - - err = class_register(&vpe_class); - if (err) { - printk(KERN_ERR "vpe_class registration failed\n"); - goto out_chrdev; - } - - device_initialize(&vpe_device); - vpe_device.class = &vpe_class, - vpe_device.parent = NULL, - dev_set_name(&vpe_device, "vpe1"); - vpe_device.devt = MKDEV(major, minor); - err = device_add(&vpe_device); - if (err) { - printk(KERN_ERR "Adding vpe_device failed\n"); - goto out_class; - } - - local_irq_save(flags); - mtflags = dmt(); - vpflags = dvpe(); - - /* Put MVPE's into 'configuration state' */ - set_c0_mvpcontrol(MVPCONTROL_VPC); - - /* dump_mtregs(); */ - - val = read_c0_mvpconf0(); - hw_tcs = (val & MVPCONF0_PTC) + 1; - hw_vpes = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; - - for (tc = tclimit; tc < hw_tcs; tc++) { - /* - * Must re-enable multithreading temporarily or in case we - * reschedule send IPIs or similar we might hang. - */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); - evpe(vpflags); - emt(mtflags); - local_irq_restore(flags); - t = alloc_tc(tc); - if (!t) { - err = -ENOMEM; - goto out; - } - - local_irq_save(flags); - mtflags = dmt(); - vpflags = dvpe(); - set_c0_mvpcontrol(MVPCONTROL_VPC); - - /* VPE's */ - if (tc < hw_tcs) { - settc(tc); - - if ((v = alloc_vpe(tc)) == NULL) { - printk(KERN_WARNING "VPE: unable to allocate VPE\n"); - - goto out_reenable; - } - - v->ntcs = hw_tcs - tclimit; - - /* add the tc to the list of this vpe's tc's. */ - list_add(&t->tc, &v->tc); - - /* deactivate all but vpe0 */ - if (tc >= tclimit) { - unsigned long tmp = read_vpe_c0_vpeconf0(); - - tmp &= ~VPECONF0_VPA; - - /* master VPE */ - tmp |= VPECONF0_MVP; - write_vpe_c0_vpeconf0(tmp); - } - - /* disable multi-threading with TC's */ - write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); - - if (tc >= vpelimit) { - /* - * Set config to be the same as vpe0, - * particularly kseg0 coherency alg - */ - write_vpe_c0_config(read_c0_config()); - } - } - - /* TC's */ - t->pvpe = v; /* set the parent vpe */ - - if (tc >= tclimit) { - unsigned long tmp; - - settc(tc); - - /* Any TC that is bound to VPE0 gets left as is - in case - we are running SMTC on VPE0. A TC that is bound to any - other VPE gets bound to VPE0, ideally I'd like to make - it homeless but it doesn't appear to let me bind a TC - to a non-existent VPE. Which is perfectly reasonable. - - The (un)bound state is visible to an EJTAG probe so may - notify GDB... - */ - - if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) { - /* tc is bound >vpe0 */ - write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE); - - t->pvpe = get_vpe(0); /* set the parent vpe */ - } - - /* halt the TC */ - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - - tmp = read_tc_c0_tcstatus(); - - /* mark not activated and not dynamically allocatable */ - tmp &= ~(TCSTATUS_A | TCSTATUS_DA); - tmp |= TCSTATUS_IXMT; /* interrupt exempt */ - write_tc_c0_tcstatus(tmp); - } - } - -out_reenable: - /* release config state */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); - - evpe(vpflags); - emt(mtflags); - local_irq_restore(flags); - - return 0; - -out_class: - class_unregister(&vpe_class); -out_chrdev: - unregister_chrdev(major, module_name); - -out: - return err; -} - -static void __exit vpe_module_exit(void) -{ - struct vpe *v, *n; - - device_del(&vpe_device); - unregister_chrdev(major, module_name); - - /* No locking needed here */ - list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) { - if (v->state != VPE_STATE_UNUSED) - release_vpe(v); - } -} - module_init(vpe_module_init); module_exit(vpe_module_exit); MODULE_DESCRIPTION("MIPS VPE Loader"); diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c index 73b34827826c..da5186fbd77a 100644 --- a/arch/mips/kvm/kvm_mips.c +++ b/arch/mips/kvm/kvm_mips.c @@ -1001,7 +1001,6 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup; - kvm_mips_init_shadow_tlb(vcpu); return 0; } diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c index c777dd36d4a8..50ab9c4d4a5d 100644 --- a/arch/mips/kvm/kvm_tlb.c +++ b/arch/mips/kvm/kvm_tlb.c @@ -10,7 +10,6 @@ * Authors: Sanjay Lal <sanjayl@kymasys.com> */ -#include <linux/init.h> #include <linux/sched.h> #include <linux/smp.h> #include <linux/mm.h> @@ -25,6 +24,7 @@ #include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/cacheflush.h> +#include <asm/tlb.h> #undef CONFIG_MIPS_MT #include <asm/r4kcache.h> @@ -35,9 +35,6 @@ #define PRIx64 "llx" -/* Use VZ EntryHi.EHINV to invalidate TLB entries */ -#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) - atomic_t kvm_mips_instance; EXPORT_SYMBOL(kvm_mips_instance); @@ -147,30 +144,6 @@ void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu) } } -void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu) -{ - int i; - volatile struct kvm_mips_tlb tlb; - - printk("Shadow TLBs:\n"); - for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) { - tlb = vcpu->arch.shadow_tlb[smp_processor_id()][i]; - printk("TLB%c%3d Hi 0x%08lx ", - (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', - i, tlb.tlb_hi); - printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ", - (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0), - (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', - (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', - (tlb.tlb_lo0 >> 3) & 7); - printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n", - (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1), - (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', - (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', - (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask); - } -} - static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn) { int srcu_idx, err = 0; @@ -657,70 +630,6 @@ kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, cpu_context(cpu, mm) = asid_cache(cpu) = asid; } -void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu) -{ - unsigned long flags; - unsigned long old_entryhi; - unsigned long old_pagemask; - int entry = 0; - int cpu = smp_processor_id(); - - local_irq_save(flags); - - old_entryhi = read_c0_entryhi(); - old_pagemask = read_c0_pagemask(); - - for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { - write_c0_index(entry); - mtc0_tlbw_hazard(); - tlb_read(); - tlbw_use_hazard(); - - vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = read_c0_entryhi(); - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = read_c0_entrylo0(); - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = read_c0_entrylo1(); - vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = read_c0_pagemask(); - } - - write_c0_entryhi(old_entryhi); - write_c0_pagemask(old_pagemask); - mtc0_tlbw_hazard(); - - local_irq_restore(flags); - -} - -void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - int cpu = smp_processor_id(); - - local_irq_save(flags); - - old_ctx = read_c0_entryhi(); - - for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { - write_c0_entryhi(vcpu->arch.shadow_tlb[cpu][entry].tlb_hi); - mtc0_tlbw_hazard(); - write_c0_entrylo0(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0); - write_c0_entrylo1(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1); - - write_c0_index(entry); - mtc0_tlbw_hazard(); - - tlb_write_indexed(); - tlbw_use_hazard(); - } - - tlbw_use_hazard(); - write_c0_entryhi(old_ctx); - mtc0_tlbw_hazard(); - local_irq_restore(flags); -} - - void kvm_local_flush_tlb_all(void) { unsigned long flags; @@ -749,30 +658,6 @@ void kvm_local_flush_tlb_all(void) local_irq_restore(flags); } -void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu) -{ - int cpu, entry; - - for_each_possible_cpu(cpu) { - for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { - vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = - UNIQUE_ENTRYHI(entry); - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = 0x0; - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = 0x0; - vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = - read_c0_pagemask(); -#ifdef DEBUG - kvm_debug - ("shadow_tlb[%d][%d]: tlb_hi: %#lx, lo0: %#lx, lo1: %#lx\n", - cpu, entry, - vcpu->arch.shadow_tlb[cpu][entry].tlb_hi, - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0, - vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1); -#endif - } - } -} - /* Restore ASID once we are scheduled back after preemption */ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { @@ -810,14 +695,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id); } - /* Only reload shadow host TLB if new ASIDs haven't been allocated */ -#if 0 - if ((atomic_read(&kvm_mips_instance) > 1) && !newasid) { - kvm_mips_flush_host_tlb(0); - kvm_shadow_tlb_load(vcpu); - } -#endif - if (!newasid) { /* If we preempted while the guest was executing, then reload the pre-empted ASID */ if (current->flags & PF_VCPU) { @@ -863,12 +740,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) vcpu->arch.preempt_entryhi = read_c0_entryhi(); vcpu->arch.last_sched_cpu = cpu; -#if 0 - if ((atomic_read(&kvm_mips_instance) > 1)) { - kvm_shadow_tlb_put(vcpu); - } -#endif - if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) & ASID_VERSION_MASK)) { kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__, @@ -930,10 +801,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu) } EXPORT_SYMBOL(kvm_local_flush_tlb_all); -EXPORT_SYMBOL(kvm_shadow_tlb_put); EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault); EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault); -EXPORT_SYMBOL(kvm_mips_init_shadow_tlb); EXPORT_SYMBOL(kvm_mips_dump_host_tlbs); EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault); EXPORT_SYMBOL(kvm_mips_host_tlb_lookup); @@ -941,8 +810,6 @@ EXPORT_SYMBOL(kvm_mips_flush_host_tlb); EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup); EXPORT_SYMBOL(kvm_mips_host_tlb_inv); EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa); -EXPORT_SYMBOL(kvm_shadow_tlb_load); -EXPORT_SYMBOL(kvm_mips_dump_shadow_tlbs); EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs); EXPORT_SYMBOL(kvm_get_inst); EXPORT_SYMBOL(kvm_arch_vcpu_load); diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c index 1ab576dc9bd1..8750dc0a1bf6 100644 --- a/arch/mips/lantiq/xway/clk.c +++ b/arch/mips/lantiq/xway/clk.c @@ -8,7 +8,6 @@ #include <linux/io.h> #include <linux/export.h> -#include <linux/init.h> #include <linux/clk.h> #include <asm/time.h> diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c index 08f7ebd9c774..78a91fa41944 100644 --- a/arch/mips/lantiq/xway/dma.c +++ b/arch/mips/lantiq/xway/dma.c @@ -220,10 +220,6 @@ ltq_dma_init(struct platform_device *pdev) int i; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - panic("Failed to get dma resource"); - - /* remap dma register range */ ltq_dma_membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ltq_dma_membase)) panic("Failed to remap dma resource"); diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c index 793e234719a6..942f32b91d12 100644 --- a/arch/mips/lasat/at93c.c +++ b/arch/mips/lasat/at93c.c @@ -8,7 +8,6 @@ #include <linux/delay.h> #include <asm/lasat/lasat.h> #include <linux/module.h> -#include <linux/init.h> #include "at93c.h" diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c index 7eb334892693..d613b97cd513 100644 --- a/arch/mips/lasat/picvue.c +++ b/arch/mips/lasat/picvue.c @@ -9,7 +9,6 @@ #include <asm/bootinfo.h> #include <asm/lasat/lasat.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/string.h> diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c index d8522f8e842a..09d5deea747f 100644 --- a/arch/mips/lib/uncached.c +++ b/arch/mips/lib/uncached.c @@ -8,7 +8,6 @@ * Author: Maciej W. Rozycki <macro@mips.com> */ -#include <linux/init.h> #include <asm/addrspace.h> #include <asm/bug.h> diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c index 4dc2f5fa3f67..aed32b88576c 100644 --- a/arch/mips/loongson/lemote-2f/clock.c +++ b/arch/mips/loongson/lemote-2f/clock.c @@ -10,7 +10,6 @@ #include <linux/cpufreq.h> #include <linux/errno.h> #include <linux/export.h> -#include <linux/init.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/spinlock.h> diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index efe008846ed0..506925b2c3f3 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -417,14 +417,20 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr) case mm_mtc1_op: case mm_cfc1_op: case mm_ctc1_op: + case mm_mfhc1_op: + case mm_mthc1_op: if (insn.mm_fp1_format.op == mm_mfc1_op) op = mfc_op; else if (insn.mm_fp1_format.op == mm_mtc1_op) op = mtc_op; else if (insn.mm_fp1_format.op == mm_cfc1_op) op = cfc_op; - else + else if (insn.mm_fp1_format.op == mm_ctc1_op) op = ctc_op; + else if (insn.mm_fp1_format.op == mm_mfhc1_op) + op = mfhc_op; + else + op = mthc_op; mips32_insn.fp1_format.opcode = cop1_op; mips32_insn.fp1_format.op = op; mips32_insn.fp1_format.rt = @@ -853,20 +859,20 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, * In the Linux kernel, we support selection of FPR format on the * basis of the Status.FR bit. If an FPU is not present, the FR bit * is hardwired to zero, which would imply a 32-bit FPU even for - * 64-bit CPUs so we rather look at TIF_32BIT_REGS. + * 64-bit CPUs so we rather look at TIF_32BIT_FPREGS. * FPU emu is slow and bulky and optimizing this function offers fairly * sizeable benefits so we try to be clever and make this function return * a constant whenever possible, that is on 64-bit kernels without O32 - * compatibility enabled and on 32-bit kernels. + * compatibility enabled and on 32-bit without 64-bit FPU support. */ static inline int cop1_64bit(struct pt_regs *xcp) { #if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32) return 1; -#elif defined(CONFIG_64BIT) && defined(CONFIG_MIPS32_O32) - return !test_thread_flag(TIF_32BIT_REGS); -#else +#elif defined(CONFIG_32BIT) && !defined(CONFIG_MIPS_O32_FP64_SUPPORT) return 0; +#else + return !test_thread_flag(TIF_32BIT_FPREGS); #endif } @@ -878,6 +884,10 @@ static inline int cop1_64bit(struct pt_regs *xcp) ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \ ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32) +#define SIFROMHREG(si, x) ((si) = (int)(ctx->fpr[x] >> 32)) +#define SITOHREG(si, x) (ctx->fpr[x] = \ + ctx->fpr[x] << 32 >> 32 | (u64)(si) << 32) + #define DIFROMREG(di, x) ((di) = ctx->fpr[x & ~(cop1_64bit(xcp) == 0)]) #define DITOREG(di, x) (ctx->fpr[x & ~(cop1_64bit(xcp) == 0)] = (di)) @@ -1055,6 +1065,25 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; #endif + case mfhc_op: + if (!cpu_has_mips_r2) + goto sigill; + + /* copregister rd -> gpr[rt] */ + if (MIPSInst_RT(ir) != 0) { + SIFROMHREG(xcp->regs[MIPSInst_RT(ir)], + MIPSInst_RD(ir)); + } + break; + + case mthc_op: + if (!cpu_has_mips_r2) + goto sigill; + + /* copregister rd <- gpr[rt] */ + SITOHREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); + break; + case mfc_op: /* copregister rd -> gpr[rt] */ if (MIPSInst_RT(ir) != 0) { @@ -1263,6 +1292,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #endif default: +sigill: return SIGILL; } diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index 1c586575fe17..3aeae07ed5b8 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c @@ -89,8 +89,9 @@ int fpu_emulator_save_context32(struct sigcontext32 __user *sc) { int i; int err = 0; + int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; - for (i = 0; i < 32; i+=2) { + for (i = 0; i < 32; i += inc) { err |= __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } @@ -103,8 +104,9 @@ int fpu_emulator_restore_context32(struct sigcontext32 __user *sc) { int i; int err = 0; + int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; - for (i = 0; i < 32; i+=2) { + for (i = 0; i < 32; i += inc) { err |= __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index c8efdb5b6ee0..f41a5c5b0865 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -6,7 +6,6 @@ * Copyright (C) 2005-2007 Cavium Networks */ #include <linux/export.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 2fcde0c8ea02..135ec313c1f6 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -9,7 +9,6 @@ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov * Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 49e572d879e1..c14259edd53f 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1020,10 +1020,14 @@ static void probe_pcache(void) */ config1 = read_c0_config1(); - if ((lsize = ((config1 >> 19) & 7))) - c->icache.linesz = 2 << lsize; - else - c->icache.linesz = lsize; + lsize = (config1 >> 19) & 7; + + /* IL == 7 is reserved */ + if (lsize == 7) + panic("Invalid icache line size"); + + c->icache.linesz = lsize ? 2 << lsize : 0; + c->icache.sets = 32 << (((config1 >> 22) + 1) & 7); c->icache.ways = 1 + ((config1 >> 16) & 7); @@ -1040,10 +1044,14 @@ static void probe_pcache(void) */ c->dcache.flags = 0; - if ((lsize = ((config1 >> 10) & 7))) - c->dcache.linesz = 2 << lsize; - else - c->dcache.linesz= lsize; + lsize = (config1 >> 10) & 7; + + /* DL == 7 is reserved */ + if (lsize == 7) + panic("Invalid dcache line size"); + + c->dcache.linesz = lsize ? 2 << lsize : 0; + c->dcache.sets = 32 << (((config1 >> 13) + 1) & 7); c->dcache.ways = 1 + ((config1 >> 7) & 7); @@ -1105,6 +1113,8 @@ static void probe_pcache(void) case CPU_34K: case CPU_74K: case CPU_1004K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: if (current_cpu_type() == CPU_74K) alias_74k_erratum(c); if ((read_c0_config7() & (1 << 16))) { diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 15f813c303b4..fde7e56d13fe 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -8,7 +8,6 @@ */ #include <linux/fs.h> #include <linux/fcntl.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/linkage.h> #include <linux/module.h> diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S index 191cf6e0c725..5d5f29681a21 100644 --- a/arch/mips/mm/cex-sb1.S +++ b/arch/mips/mm/cex-sb1.S @@ -15,7 +15,6 @@ * 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/init.h> #include <asm/asm.h> #include <asm/regdef.h> diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 2e9418562258..44b6dff5aba2 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -23,6 +23,7 @@ #include <dma-coherence.h> +#ifdef CONFIG_DMA_MAYBE_COHERENT int coherentio = 0; /* User defined DMA coherency from command line. */ EXPORT_SYMBOL_GPL(coherentio); int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */ @@ -42,6 +43,7 @@ static int __init setnocoherentio(char *str) return 0; } early_param("nocoherentio", setnocoherentio); +#endif static inline struct page *dma_addr_to_page(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/mips/mm/hugetlbpage.c b/arch/mips/mm/hugetlbpage.c index 01fda4419ed0..77e0ae036e7c 100644 --- a/arch/mips/mm/hugetlbpage.c +++ b/arch/mips/mm/hugetlbpage.c @@ -11,7 +11,6 @@ * Copyright (C) 2008, 2009 Cavium Networks, Inc. */ -#include <linux/init.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/hugetlb.h> diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 12156176c7ca..6b59617760c1 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -171,8 +171,6 @@ void *kmap_coherent(struct page *page, unsigned long addr) return (void*) vaddr; } -#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) - void kunmap_coherent(void) { #ifndef CONFIG_MIPS_MT_SMTC diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index cbd81d17793a..58033c44690d 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -8,7 +8,6 @@ * Copyright (C) 2008 Thiemo Seufer * Copyright (C) 2012 MIPS Technologies, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 08d05aee8788..7a56aee5fce7 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -76,6 +76,8 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) case CPU_34K: case CPU_74K: case CPU_1004K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: case CPU_BMIPS5000: if (config2 & (1 << 12)) return 0; diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index aaffbba33706..9ac1efcfbcc7 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -6,7 +6,6 @@ #undef DEBUG -#include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bitops.h> diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 9aca10994cd2..d657493ef561 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -10,7 +10,6 @@ * Copyright (C) 2002 Ralf Baechle * Copyright (C) 2002 Maciej W. Rozycki */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index da3b0b9c9eae..ae4ca2450707 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -20,16 +20,11 @@ #include <asm/bootinfo.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> +#include <asm/tlb.h> #include <asm/tlbmisc.h> extern void build_tlb_refill_handler(void); -/* - * Make sure all entries differ. If they're not different - * MIPS32 will take revenge ... - */ -#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) - /* Atomicity and interruptability */ #ifdef CONFIG_MIPS_MT_SMTC @@ -77,7 +72,7 @@ void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; - int entry; + int entry, ftlbhighset; ENTER_CRITICAL(flags); /* Save old context and create impossible VPN2 value */ @@ -88,13 +83,30 @@ void local_flush_tlb_all(void) entry = read_c0_wired(); /* Blast 'em all away. */ - while (entry < current_cpu_data.tlbsize) { - /* Make sure all entries differ. */ - write_c0_entryhi(UNIQUE_ENTRYHI(entry)); - write_c0_index(entry); - mtc0_tlbw_hazard(); - tlb_write_indexed(); - entry++; + if (cpu_has_tlbinv) { + if (current_cpu_data.tlbsizevtlb) { + write_c0_index(0); + mtc0_tlbw_hazard(); + tlbinvf(); /* invalidate VTLB */ + } + ftlbhighset = current_cpu_data.tlbsizevtlb + + current_cpu_data.tlbsizeftlbsets; + for (entry = current_cpu_data.tlbsizevtlb; + entry < ftlbhighset; + entry++) { + write_c0_index(entry); + mtc0_tlbw_hazard(); + tlbinvf(); /* invalidate one FTLB set */ + } + } else { + while (entry < current_cpu_data.tlbsize) { + /* Make sure all entries differ. */ + write_c0_entryhi(UNIQUE_ENTRYHI(entry)); + write_c0_index(entry); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + entry++; + } } tlbw_use_hazard(); write_c0_entryhi(old_ctx); @@ -133,7 +145,9 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, start = round_down(start, PAGE_SIZE << 1); end = round_up(end, PAGE_SIZE << 1); size = (end - start) >> (PAGE_SHIFT + 1); - if (size <= current_cpu_data.tlbsize/2) { + if (size <= (current_cpu_data.tlbsizeftlbsets ? + current_cpu_data.tlbsize / 8 : + current_cpu_data.tlbsize / 2)) { int oldpid = read_c0_entryhi(); int newpid = cpu_asid(cpu, mm); @@ -172,7 +186,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) ENTER_CRITICAL(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; - if (size <= current_cpu_data.tlbsize / 2) { + if (size <= (current_cpu_data.tlbsizeftlbsets ? + current_cpu_data.tlbsize / 8 : + current_cpu_data.tlbsize / 2)) { int pid = read_c0_entryhi(); start &= (PAGE_MASK << 1); diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 6a99733a4440..138a2ec7cc6b 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -8,7 +8,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. */ -#include <linux/init.h> #include <linux/sched.h> #include <linux/smp.h> #include <linux/mm.h> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 183f2b583e4d..b234b1b5ccad 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -26,7 +26,6 @@ #include <linux/types.h> #include <linux/smp.h> #include <linux/string.h> -#include <linux/init.h> #include <linux/cache.h> #include <asm/cacheflush.h> @@ -510,6 +509,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l, switch (current_cpu_type()) { case CPU_M14KC: case CPU_74K: + case CPU_PROAPTIV: break; default: diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 060000fa653c..b8d580ca02e5 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/types.h> -#include <linux/init.h> #include <asm/inst.h> #include <asm/elf.h> diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 0c724589854e..3abd609518c9 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/types.h> -#include <linux/init.h> #include <asm/inst.h> #include <asm/elf.h> diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 72fdedbf76db..eae0ba3876d9 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -9,7 +9,5 @@ obj-y := malta-amon.o malta-display.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o -obj-$(CONFIG_EARLY_PRINTK) += malta-console.o - # FIXME FIXME FIXME obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o diff --git a/arch/mips/mti-malta/malta-amon.c b/arch/mips/mti-malta/malta-amon.c index 1e4784458016..592ac0427426 100644 --- a/arch/mips/mti-malta/malta-amon.c +++ b/arch/mips/mti-malta/malta-amon.c @@ -1,30 +1,20 @@ /* - * Copyright (C) 2007 MIPS Technologies, Inc. - * All rights reserved. - - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * 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. * - * 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. + * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. * - * Arbitrary Monitor interface + * Arbitrary Monitor Interface */ - #include <linux/kernel.h> -#include <linux/init.h> #include <linux/smp.h> #include <asm/addrspace.h> -#include <asm/mips-boards/launch.h> #include <asm/mipsmtregs.h> +#include <asm/mips-boards/launch.h> +#include <asm/vpe.h> int amon_cpu_avail(int cpu) { @@ -48,7 +38,7 @@ int amon_cpu_avail(int cpu) return 1; } -void amon_cpu_start(int cpu, +int amon_cpu_start(int cpu, unsigned long pc, unsigned long sp, unsigned long gp, unsigned long a0) { @@ -56,10 +46,10 @@ void amon_cpu_start(int cpu, (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); if (!amon_cpu_avail(cpu)) - return; + return -1; if (cpu == smp_processor_id()) { pr_debug("launch: I am cpu%d!\n", cpu); - return; + return -1; } launch += cpu; @@ -78,4 +68,21 @@ void amon_cpu_start(int cpu, ; smp_rmb(); /* Target will be updating flags soon */ pr_debug("launch: cpu%d gone!\n", cpu); + + return 0; +} + +#ifdef CONFIG_MIPS_VPE_LOADER +int vpe_run(struct vpe *v) +{ + struct vpe_notifications *n; + + if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0) + return -1; + + list_for_each_entry(n, &v->notify, list) + n->start(VPE_MODULE_MINOR); + + return 0; } +#endif diff --git a/arch/mips/mti-malta/malta-console.c b/arch/mips/mti-malta/malta-console.c deleted file mode 100644 index 43bcfb4f8167..000000000000 --- a/arch/mips/mti-malta/malta-console.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Putting things on the screen/serial line using YAMONs facilities. - */ -#include <linux/console.h> -#include <linux/init.h> -#include <linux/serial_reg.h> -#include <asm/io.h> - - -#define PORT(offset) (0x3f8 + (offset)) - - -static inline unsigned int serial_in(int offset) -{ - return inb(PORT(offset)); -} - -static inline void serial_out(int offset, int value) -{ - outb(value, PORT(offset)); -} - -int prom_putchar(char c) -{ - while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) - ; - - serial_out(UART_TX, c); - - return 1; -} diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index ff8caffd3266..fcebfced26d0 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/string.h> #include <linux/kernel.h> +#include <linux/serial_8250.h> #include <asm/cacheflush.h> #include <asm/smp-ops.h> @@ -44,32 +45,39 @@ static void __init console_config(void) char parity = '\0', bits = '\0', flow = '\0'; char *s; - if ((strstr(fw_getcmdline(), "console=")) == NULL) { - s = fw_getenv("modetty0"); - if (s) { - while (*s >= '0' && *s <= '9') - baud = baud*10 + *s++ - '0'; - if (*s == ',') - s++; - if (*s) - parity = *s++; - if (*s == ',') - s++; - if (*s) - bits = *s++; - if (*s == ',') - s++; - if (*s == 'h') - flow = 'r'; - } - if (baud == 0) - baud = 38400; - if (parity != 'n' && parity != 'o' && parity != 'e') - parity = 'n'; - if (bits != '7' && bits != '8') - bits = '8'; - if (flow == '\0') + s = fw_getenv("modetty0"); + if (s) { + while (*s >= '0' && *s <= '9') + baud = baud*10 + *s++ - '0'; + if (*s == ',') + s++; + if (*s) + parity = *s++; + if (*s == ',') + s++; + if (*s) + bits = *s++; + if (*s == ',') + s++; + if (*s == 'h') flow = 'r'; + } + if (baud == 0) + baud = 38400; + if (parity != 'n' && parity != 'o' && parity != 'e') + parity = 'n'; + if (bits != '7' && bits != '8') + bits = '8'; + if (flow == '\0') + flow = 'r'; + + if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) { + sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud, + parity, bits); + setup_early_serial8250_console(console_string); + } + + if ((strstr(fw_getcmdline(), "console=")) == NULL) { sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow); strcat(fw_getcmdline(), console_string); diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 0892575f829d..ca3e3a46a42f 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -1,25 +1,16 @@ /* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc. * Copyright (C) 2001 Ralf Baechle - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * Copyright (C) 2013 Imagination Technologies Ltd. * * Routines for generic manipulation of the interrupts found on the MIPS - * Malta board. - * The interrupt controller is located in the South Bridge a PIIX4 device - * with two internal 82C95 interrupt controllers. + * Malta board. The interrupt controller is located in the South Bridge + * a PIIX4 device with two internal 82C95 interrupt controllers. */ #include <linux/init.h> #include <linux/irq.h> @@ -44,6 +35,7 @@ #include <asm/gic.h> #include <asm/gcmpregs.h> #include <asm/setup.h> +#include <asm/rtlx.h> int gcmp_present = -1; static unsigned long _msc01_biu_base; @@ -90,7 +82,7 @@ static inline int mips_pcibios_iack(void) BONITO_PCIMAP_CFG = 0; break; default: - printk(KERN_WARNING "Unknown system controller.\n"); + pr_emerg("Unknown system controller.\n"); return -1; } return irq; @@ -126,6 +118,11 @@ static void malta_hw0_irqdispatch(void) } do_IRQ(MALTA_INT_BASE + irq); + +#ifdef MIPS_VPE_APSP_API + if (aprp_hook) + aprp_hook(); +#endif } static void malta_ipi_irqdispatch(void) @@ -149,11 +146,11 @@ static void corehi_irqdispatch(void) unsigned int intrcause, datalo, datahi; struct pt_regs *regs = get_irq_regs(); - printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!\n"); - printk(KERN_EMERG "epc : %08lx\nStatus: %08lx\n" - "Cause : %08lx\nbadVaddr : %08lx\n", - regs->cp0_epc, regs->cp0_status, - regs->cp0_cause, regs->cp0_badvaddr); + pr_emerg("CoreHI interrupt, shouldn't happen, we die here!\n"); + pr_emerg("epc : %08lx\nStatus: %08lx\n" + "Cause : %08lx\nbadVaddr : %08lx\n", + regs->cp0_epc, regs->cp0_status, + regs->cp0_cause, regs->cp0_badvaddr); /* Read all the registers and then print them as there is a problem with interspersed printk's upsetting the Bonito controller. @@ -171,8 +168,8 @@ static void corehi_irqdispatch(void) intrcause = GT_READ(GT_INTRCAUSE_OFS); datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); - printk(KERN_EMERG "GT_INTRCAUSE = %08x\n", intrcause); - printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x\n", + pr_emerg("GT_INTRCAUSE = %08x\n", intrcause); + pr_emerg("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); break; case MIPS_REVISION_SCON_BONITO: @@ -184,14 +181,14 @@ static void corehi_irqdispatch(void) intedge = BONITO_INTEDGE; intsteer = BONITO_INTSTEER; pcicmd = BONITO_PCICMD; - printk(KERN_EMERG "BONITO_INTISR = %08x\n", intisr); - printk(KERN_EMERG "BONITO_INTEN = %08x\n", inten); - printk(KERN_EMERG "BONITO_INTPOL = %08x\n", intpol); - printk(KERN_EMERG "BONITO_INTEDGE = %08x\n", intedge); - printk(KERN_EMERG "BONITO_INTSTEER = %08x\n", intsteer); - printk(KERN_EMERG "BONITO_PCICMD = %08x\n", pcicmd); - printk(KERN_EMERG "BONITO_PCIBADADDR = %08x\n", pcibadaddr); - printk(KERN_EMERG "BONITO_PCIMSTAT = %08x\n", pcimstat); + pr_emerg("BONITO_INTISR = %08x\n", intisr); + pr_emerg("BONITO_INTEN = %08x\n", inten); + pr_emerg("BONITO_INTPOL = %08x\n", intpol); + pr_emerg("BONITO_INTEDGE = %08x\n", intedge); + pr_emerg("BONITO_INTSTEER = %08x\n", intsteer); + pr_emerg("BONITO_PCICMD = %08x\n", pcicmd); + pr_emerg("BONITO_PCIBADADDR = %08x\n", pcibadaddr); + pr_emerg("BONITO_PCIMSTAT = %08x\n", pcimstat); break; } @@ -313,6 +310,11 @@ static void ipi_call_dispatch(void) static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) { +#ifdef MIPS_VPE_APSP_API + if (aprp_hook) + aprp_hook(); +#endif + scheduler_ipi(); return IRQ_HANDLED; @@ -365,13 +367,13 @@ static struct irqaction corehi_irqaction = { .flags = IRQF_NO_THREAD, }; -static msc_irqmap_t __initdata msc_irqmap[] = { +static msc_irqmap_t msc_irqmap[] __initdata = { {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, }; -static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); +static int msc_nr_irqs __initdata = ARRAY_SIZE(msc_irqmap); -static msc_irqmap_t __initdata msc_eicirqmap[] = { +static msc_irqmap_t msc_eicirqmap[] __initdata = { {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, @@ -384,7 +386,7 @@ static msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} }; -static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); +static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); /* * This GIC specific tabular array defines the association between External @@ -431,9 +433,12 @@ int __init gcmp_probe(unsigned long addr, unsigned long size) if (gcmp_present >= 0) return gcmp_present; - _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); - _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); - gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR; + _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, + GCMP_ADDRSPACE_SZ); + _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, + MSC01_BIU_ADDRSPACE_SZ); + gcmp_present = ((GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == + GCMP_BASE_ADDR); if (gcmp_present) pr_debug("GCMP present\n"); @@ -443,9 +448,8 @@ int __init gcmp_probe(unsigned long addr, unsigned long size) /* Return the number of IOCU's present */ int __init gcmp_niocu(void) { - return gcmp_present ? - (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF : - 0; + return gcmp_present ? ((GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> + GCMP_GCB_GC_NUMIOCU_SHF) : 0; } /* Set GCMP region attributes */ @@ -594,11 +598,14 @@ void __init arch_init_irq(void) set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); } /* Argh.. this really needs sorting out.. */ - printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status()); + pr_info("CPU%d: status register was %08x\n", + smp_processor_id(), read_c0_status()); write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); - printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status()); + pr_info("CPU%d: status register now %08x\n", + smp_processor_id(), read_c0_status()); write_c0_status(0x1100dc00); - printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status()); + pr_info("CPU%d: status register frc %08x\n", + smp_processor_id(), read_c0_status()); for (i = 0; i < nr_cpu_ids; i++) { arch_init_ipiirq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched); @@ -616,11 +623,15 @@ void __init arch_init_irq(void) cpu_ipi_call_irq = MSC01E_INT_SW1; } else { if (cpu_has_vint) { - set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); - set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); + set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, + ipi_resched_dispatch); + set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, + ipi_call_dispatch); } - cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; - cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; + cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + + MIPS_CPU_IPI_RESCHED_IRQ; + cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + + MIPS_CPU_IPI_CALL_IRQ; } arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); @@ -630,9 +641,7 @@ void __init arch_init_irq(void) void malta_be_init(void) { - if (gcmp_present) { - /* Could change CM error mask register */ - } + /* Could change CM error mask register. */ } @@ -712,14 +721,14 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) if (cause < 16) { unsigned long cca_bits = (cm_error >> 15) & 7; unsigned long tr_bits = (cm_error >> 12) & 7; - unsigned long mcmd_bits = (cm_error >> 7) & 0x1f; + unsigned long cmd_bits = (cm_error >> 7) & 0x1f; unsigned long stag_bits = (cm_error >> 3) & 15; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "CCA=%lu TR=%s MCmd=%s STag=%lu " "SPort=%lu\n", - cca_bits, tr[tr_bits], mcmd[mcmd_bits], + cca_bits, tr[tr_bits], mcmd[cmd_bits], stag_bits, sport_bits); } else { /* glob state & sresp together */ @@ -728,7 +737,7 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) unsigned long c1_bits = (cm_error >> 12) & 7; unsigned long c0_bits = (cm_error >> 9) & 7; unsigned long sc_bit = (cm_error >> 8) & 1; - unsigned long mcmd_bits = (cm_error >> 3) & 0x1f; + unsigned long cmd_bits = (cm_error >> 3) & 0x1f; unsigned long sport_bits = (cm_error >> 0) & 7; snprintf(buf, sizeof(buf), "C3=%s C2=%s C1=%s C0=%s SC=%s " @@ -736,16 +745,16 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) core[c3_bits], core[c2_bits], core[c1_bits], core[c0_bits], sc_bit ? "True" : "False", - mcmd[mcmd_bits], sport_bits); + mcmd[cmd_bits], sport_bits); } ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >> GCMP_GCB_GMEO_ERROR_2ND_SHF; - printk("CM_ERROR=%08lx %s <%s>\n", cm_error, + pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error, causes[cause], buf); - printk("CM_ADDR =%08lx\n", cm_addr); - printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]); + pr_err("CM_ADDR =%08lx\n", cm_addr); + pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]); /* reprime cause register */ GCMPGCB(GCMEC) = 0; diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c index 132f8663825e..e1dd1c1d3fde 100644 --- a/arch/mips/mti-malta/malta-platform.c +++ b/arch/mips/mti-malta/malta-platform.c @@ -47,6 +47,7 @@ static struct plat_serial8250_port uart8250_data[] = { SMC_PORT(0x3F8, 4), SMC_PORT(0x2F8, 3), +#ifndef CONFIG_MIPS_CMP { .mapbase = 0x1f000900, /* The CBUS UART */ .irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2, @@ -55,6 +56,7 @@ static struct plat_serial8250_port uart8250_data[] = { .flags = CBUS_UART_FLAGS, .regshift = 3, }, +#endif { }, }; diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index a18af5fce67e..319009912142 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -42,8 +42,6 @@ #include <asm/mips-boards/generic.h> #include <asm/mips-boards/maltaint.h> -unsigned long cpu_khz; - static int mips_cpu_timer_irq; static int mips_cpu_perf_irq; extern int cp0_perfcount_irq; @@ -168,11 +166,24 @@ unsigned int get_c0_compare_int(void) return mips_cpu_timer_irq; } +static void __init init_rtc(void) +{ + /* stop the clock whilst setting it up */ + CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL); + + /* 32KHz time base */ + CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT); + + /* start the clock */ + CMOS_WRITE(RTC_24H, RTC_CONTROL); +} + void __init plat_time_init(void) { unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK); unsigned int freq; + init_rtc(); estimate_frequencies(); freq = mips_hpt_frequency; @@ -182,7 +193,6 @@ void __init plat_time_init(void) freq = freqround(freq, 5000); printk("CPU frequency %d.%02d MHz\n", freq/1000000, (freq%1000000)*100/1000000); - cpu_khz = freq / 1000; mips_scroll_message(); diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index be114209217c..071786fa234b 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -21,5 +21,7 @@ obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o obj-$(CONFIG_OF) += sead3.dtb.o +CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt + $(obj)/%.dtb: $(obj)/%.dts $(call if_changed,dtc) diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c index eb2bf936d102..3b12aa5a7c88 100644 --- a/arch/mips/mti-sead3/sead3-pic32-bus.c +++ b/arch/mips/mti-sead3/sead3-pic32-bus.c @@ -8,7 +8,6 @@ #include <linux/delay.h> #include <linux/kernel.h> #include <linux/spinlock.h> -#include <linux/init.h> #include <linux/io.h> #include <linux/errno.h> diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c index 928ba84c8a78..bf7fe48bf2f9 100644 --- a/arch/mips/mti-sead3/sead3-setup.c +++ b/arch/mips/mti-sead3/sead3-setup.c @@ -4,13 +4,15 @@ * for more details. * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 2013 Imagination Technologies Ltd. */ #include <linux/init.h> +#include <linux/libfdt.h> #include <linux/of_platform.h> #include <linux/of_fdt.h> -#include <linux/bootmem.h> #include <asm/prom.h> +#include <asm/fw/fw.h> #include <asm/mips-boards/generic.h> @@ -19,8 +21,73 @@ const char *get_system_type(void) return "MIPS SEAD3"; } +static uint32_t get_memsize_from_cmdline(void) +{ + int memsize = 0; + char *p = arcs_cmdline; + char *s = "memsize="; + + p = strstr(p, s); + if (p) { + p += strlen(s); + memsize = memparse(p, NULL); + } + + return memsize; +} + +static uint32_t get_memsize_from_env(void) +{ + int memsize = 0; + char *p; + + p = fw_getenv("memsize"); + if (p) + memsize = memparse(p, NULL); + + return memsize; +} + +static uint32_t get_memsize(void) +{ + uint32_t memsize; + + memsize = get_memsize_from_cmdline(); + if (memsize) + return memsize; + + return get_memsize_from_env(); +} + +static void __init parse_memsize_param(void) +{ + int offset; + const uint64_t *prop_value; + int prop_len; + uint32_t memsize = get_memsize(); + + if (!memsize) + return; + + offset = fdt_path_offset(&__dtb_start, "/memory"); + if (offset > 0) { + uint64_t new_value; + /* + * reg contains 2 32-bits BE values, offset and size. We just + * want to replace the size value without affecting the offset + */ + prop_value = fdt_getprop(&__dtb_start, offset, "reg", &prop_len); + new_value = be64_to_cpu(*prop_value); + new_value = (new_value & ~0xffffffffllu) | memsize; + fdt_setprop_inplace_u64(&__dtb_start, offset, "reg", new_value); + } +} + void __init plat_mem_setup(void) { + /* allow command line/bootloader env to override memory size in DT */ + parse_memsize_param(); + /* * Load the builtin devicetree. This causes the chosen node to be * parsed resulting in our memory appearing @@ -30,16 +97,15 @@ void __init plat_mem_setup(void) void __init device_tree_init(void) { - unsigned long base, size; - if (!initial_boot_params) return; - base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); - - /* Before we do anything, lets reserve the dt blob */ - reserve_bootmem(base, size, BOOTMEM_DEFAULT); + unflatten_and_copy_device_tree(); +} - unflatten_device_tree(); +static int __init customize_machine(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + return 0; } +arch_initcall(customize_machine); diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c index 552d26c34386..678d03d53c60 100644 --- a/arch/mips/mti-sead3/sead3-time.c +++ b/arch/mips/mti-sead3/sead3-time.c @@ -13,8 +13,6 @@ #include <asm/irq.h> #include <asm/mips-boards/generic.h> -unsigned long cpu_khz; - static int mips_cpu_timer_irq; static int mips_cpu_perf_irq; @@ -109,8 +107,6 @@ void __init plat_time_init(void) pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000), (est_freq % 1000000) * 100 / 1000000); - cpu_khz = est_freq / 1000; - mips_scroll_message(); plat_perf_setup(); diff --git a/arch/mips/mti-sead3/sead3.dts b/arch/mips/mti-sead3/sead3.dts index 658f43787056..e4b317d414f1 100644 --- a/arch/mips/mti-sead3/sead3.dts +++ b/arch/mips/mti-sead3/sead3.dts @@ -15,10 +15,6 @@ }; }; - chosen { - bootargs = "console=ttyS1,38400 rootdelay=10 root=/dev/sda3"; - }; - memory { device_type = "memory"; reg = <0x0 0x08000000>; diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index 852a4ee09954..4eb683aef7d7 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -28,6 +28,15 @@ config DT_XLP_FVP pointer to the kernel. The corresponding DTS file is at arch/mips/netlogic/dts/xlp_fvp.dts +config DT_XLP_GVP + bool "Built-in device tree for XLP GVP boards" + default y + help + Add an FDT blob for XLP GVP 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_gvp.dts + config NLM_MULTINODE bool "Support for multi-chip boards" depends on NLM_XLP_BOARD diff --git a/arch/mips/netlogic/common/earlycons.c b/arch/mips/netlogic/common/earlycons.c index 1902fa22d277..769f93032c53 100644 --- a/arch/mips/netlogic/common/earlycons.c +++ b/arch/mips/netlogic/common/earlycons.c @@ -37,9 +37,11 @@ #include <asm/mipsregs.h> #include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h> #if defined(CONFIG_CPU_XLP) #include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> #include <asm/netlogic/xlp-hal/uart.h> #elif defined(CONFIG_CPU_XLR) #include <asm/netlogic/xlr/iomap.h> diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 1c7e3a1b81ab..5afc4b7fce0f 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void) #endif } + void nlm_setup_pic_irq(int node, int picirq, int irq, int irt) { struct nlm_pic_irq *pic_data; @@ -207,32 +208,32 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *)) static void nlm_init_node_irqs(int node) { - int i, irt; - uint64_t irqmask; struct nlm_soc_info *nodep; + int i, irt; pr_info("Init IRQ for node %d\n", node); nodep = nlm_get_node(node); - irqmask = PERCPU_IRQ_MASK; + nodep->irqmask = PERCPU_IRQ_MASK; for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) { irt = nlm_irq_to_irt(i); - if (irt == -1) + if (irt == -1) /* unused irq */ continue; - nlm_setup_pic_irq(node, i, i, irt); - /* set interrupts to first cpu in node */ + nodep->irqmask |= 1ull << i; + if (irt == -2) /* not a direct PIC irq */ + continue; + nlm_pic_init_irt(nodep->picbase, irt, i, - node * NLM_CPUS_PER_NODE, 0); - irqmask |= (1ull << i); + node * nlm_threads_per_node(), 0); + nlm_setup_pic_irq(node, i, i, irt); } - nodep->irqmask = irqmask; } void nlm_smp_irq_init(int hwcpuid) { int node, cpu; - node = hwcpuid / NLM_CPUS_PER_NODE; - cpu = hwcpuid % NLM_CPUS_PER_NODE; + node = nlm_cpuid_to_node(hwcpuid); + cpu = hwcpuid % nlm_threads_per_node(); if (cpu == 0 && node != 0) nlm_init_node_irqs(node); @@ -256,13 +257,23 @@ asmlinkage void plat_irq_dispatch(void) return; } +#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP) + /* PCI interrupts need a second level dispatch for MSI bits */ + if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) { + nlm_dispatch_msi(node, i); + return; + } + if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) { + nlm_dispatch_msix(node, i); + return; + } + +#endif /* top level irq handling */ do_IRQ(nlm_irq_to_xirq(node, i)); } #ifdef CONFIG_OF -static struct irq_domain *xlp_pic_domain; - static const struct irq_domain_ops xlp_pic_irq_domain_ops = { .xlate = irq_domain_xlate_onetwocell, }; @@ -271,8 +282,9 @@ static int __init xlp_of_pic_init(struct device_node *node, struct device_node *parent) { const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1; + struct irq_domain *xlp_pic_domain; struct resource res; - int socid, ret; + int socid, ret, bus; /* we need a hack to get the PIC's SoC chip id */ ret = of_address_to_resource(node, 0, &res); @@ -280,7 +292,34 @@ static int __init xlp_of_pic_init(struct device_node *node, pr_err("PIC %s: reg property not found!\n", node->name); return -EINVAL; } - socid = (res.start >> 18) & 0x3; + + if (cpu_is_xlp9xx()) { + bus = (res.start >> 20) & 0xf; + for (socid = 0; socid < NLM_NR_NODES; socid++) { + if (!nlm_node_present(socid)) + continue; + if (nlm_get_node(socid)->socbus == bus) + break; + } + if (socid == NLM_NR_NODES) { + pr_err("PIC %s: Node mapping for bus %d not found!\n", + node->name, bus); + return -EINVAL; + } + } else { + socid = (res.start >> 18) & 0x3; + if (!nlm_node_present(socid)) { + pr_err("PIC %s: node %d does not exist!\n", + node->name, socid); + return -EINVAL; + } + } + + if (!nlm_node_present(socid)) { + pr_err("PIC %s: node %d does not exist!\n", node->name, socid); + return -EINVAL; + } + xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs, nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE, &xlp_pic_irq_domain_ops, NULL); @@ -288,8 +327,7 @@ static int __init xlp_of_pic_init(struct device_node *node, pr_err("PIC %s: Creating legacy domain failed!\n", node->name); return -EINVAL; } - pr_info("Node %d: IRQ domain created for PIC@%pa\n", socid, - &res.start); + pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res); return 0; } diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index adb18288a6c0..b231fe1e7a09 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -32,10 +32,10 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> #include <asm/asm.h> #include <asm/asm-offsets.h> +#include <asm/cacheops.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> @@ -50,8 +50,8 @@ #include <asm/netlogic/xlp-hal/cpucontrol.h> #define CP0_EBASE $15 -#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ - XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ +#define SYS_CPU_COHERENT_BASE CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ + XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \ SYS_CPU_NONCOHERENT_MODE * 4 /* Enable XLP features and workarounds in the LSU */ @@ -74,35 +74,55 @@ .endm /* - * Low level flush for L1D cache on XLP, the normal cache ops does - * not do the complete and correct cache flush. + * L1D cache has to be flushed before enabling threads in XLP. + * On XLP8xx/XLP3xx, we do a low level flush using processor control + * registers. On XLPII CPUs, usual cache instructions work. */ .macro xlp_flush_l1_dcache + mfc0 t0, CP0_EBASE, 0 + andi t0, t0, 0xff00 + slt t1, t0, 0x1200 + beqz t1, 15f + nop + + /* XLP8xx low level cache flush */ li t0, LSU_DEBUG_DATA0 li t1, LSU_DEBUG_ADDR li t2, 0 /* index */ li t3, 0x1000 /* loop count */ -1: +11: sll v0, t2, 5 mtcr zero, t0 ori v1, v0, 0x3 /* way0 | write_enable | write_active */ mtcr v1, t1 -2: +12: mfcr v1, t1 andi v1, 0x1 /* wait for write_active == 0 */ - bnez v1, 2b + bnez v1, 12b nop mtcr zero, t0 ori v1, v0, 0x7 /* way1 | write_enable | write_active */ mtcr v1, t1 -3: +13: mfcr v1, t1 andi v1, 0x1 /* wait for write_active == 0 */ - bnez v1, 3b + bnez v1, 13b nop addi t2, 1 - bne t3, t2, 1b + bne t3, t2, 11b + nop + b 17f + nop + + /* XLPII CPUs, Invalidate all 64k of L1 D-cache */ +15: + li t0, 0x80000000 + li t1, 0x80010000 +16: cache Index_Writeback_Inv_D, 0(t0) + addiu t0, t0, 32 + bne t0, t1, 16b nop +17: .endm /* @@ -138,6 +158,13 @@ FEXPORT(nlm_reset_entry) nop 1: /* Entry point on core wakeup */ + mfc0 t0, CP0_EBASE, 0 /* processor ID */ + andi t0, 0xff00 + li t1, 0x1500 /* XLP 9xx */ + beq t0, t1, 2f /* does not need to set coherent */ + nop + + /* set bit in SYS coherent register for the core */ mfc0 t0, CP0_EBASE, 1 mfc0 t1, CP0_EBASE, 1 srl t1, 5 @@ -149,7 +176,7 @@ FEXPORT(nlm_reset_entry) li t1, 0x1 sll t0, t1, t0 nor t0, t0, zero /* t0 <- ~(1 << core) */ - li t2, SYS_CPU_COHERENT_BASE(0) + li t2, SYS_CPU_COHERENT_BASE add t2, t2, t3 /* t2 <- SYS offset for node */ lw t1, 0(t2) and t1, t1, t0 @@ -159,13 +186,13 @@ FEXPORT(nlm_reset_entry) lw t1, 0(t2) sync +2: /* Configure LSU on Non-0 Cores. */ xlp_config_lsu /* FALL THROUGH */ /* - * Wake up sibling threads from the initial thread in - * a core. + * Wake up sibling threads from the initial thread in a core. */ EXPORT(nlm_boot_siblings) /* core L1D flush before enable threads */ @@ -181,8 +208,10 @@ EXPORT(nlm_boot_siblings) /* * The new hardware thread starts at the next instruction * For all the cases other than core 0 thread 0, we will - * jump to the secondary wait function. - */ + * jump to the secondary wait function. + + * NOTE: All GPR contents are lost after the mtcr above! + */ mfc0 v0, CP0_EBASE, 1 andi v0, 0x3ff /* v0 <- node/core */ @@ -196,7 +225,7 @@ EXPORT(nlm_boot_siblings) #endif mtc0 t1, CP0_STATUS - /* mark CPU ready, careful here, previous mtcr trashed registers */ + /* mark CPU ready */ li t3, CKSEG1ADDR(RESET_DATA_PHYS) ADDIU t1, t3, BOOT_CPU_READY sll v1, v0, 2 diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index c0eded01fde9..6baae15cc7b1 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -63,7 +63,7 @@ void nlm_send_ipi_single(int logical_cpu, unsigned int action) uint64_t picbase; cpu = cpu_logical_map(logical_cpu); - node = cpu / NLM_CPUS_PER_NODE; + node = nlm_cpuid_to_node(cpu); picbase = nlm_get_node(node)->picbase; if (action & SMP_CALL_FUNCTION) @@ -152,7 +152,7 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) int cpu, node; cpu = cpu_logical_map(logical_cpu); - node = cpu / NLM_CPUS_PER_NODE; + node = nlm_cpuid_to_node(logical_cpu); nlm_next_sp = (unsigned long)__KSTK_TOS(idle); nlm_next_gp = (unsigned long)task_thread_info(idle); @@ -164,7 +164,7 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) void __init nlm_smp_setup(void) { unsigned int boot_cpu; - int num_cpus, i, ncore; + int num_cpus, i, ncore, node; volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); char buf[64]; @@ -187,6 +187,8 @@ 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); + cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask); ++num_cpus; } } diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index aa6cff0a229b..8597657c27fc 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -32,7 +32,6 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> #include <asm/asm.h> #include <asm/asm-offsets.h> @@ -98,7 +97,7 @@ END(nlm_boot_secondary_cpus) * In case of RMIboot bootloader which is used on XLR boards, the CPUs * be already woken up and waiting in bootloader code. * This will get them out of the bootloader code and into linux. Needed - * because the bootloader area will be taken and initialized by linux. + * because the bootloader area will be taken and initialized by linux. */ NESTED(nlm_rmiboot_preboot, 16, sp) mfc0 t0, $15, 1 /* read ebase */ @@ -133,6 +132,7 @@ NESTED(nlm_rmiboot_preboot, 16, sp) or t1, t2, v1 /* put in new value */ mtcr t1, t0 /* update core control */ + /* wait for NMI to hit */ 1: wait b 1b nop diff --git a/arch/mips/netlogic/dts/Makefile b/arch/mips/netlogic/dts/Makefile index 0b9be5fd2e46..25c8e873ee25 100644 --- a/arch/mips/netlogic/dts/Makefile +++ b/arch/mips/netlogic/dts/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o obj-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb.o obj-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb.o +obj-$(CONFIG_DT_XLP_GVP) += xlp_gvp.dtb.o diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts new file mode 100644 index 000000000000..047d27f54487 --- /dev/null +++ b/arch/mips/netlogic/dts/xlp_gvp.dts @@ -0,0 +1,76 @@ +/* + * XLP9XX Device Tree Source for GVP boards + */ + +/dts-v1/; +/ { + model = "netlogic,XLP-GVP"; + 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@4000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0 0x110000 0x200>; + }; + + 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/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index 8316d5454b17..5754097b9cde 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -42,13 +42,18 @@ #include <asm/prom.h> extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], - __dtb_xlp_fvp_begin[], __dtb_start[]; + __dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[], __dtb_start[]; static void *xlp_fdt_blob; void __init *xlp_dt_init(void *fdtp) { if (!fdtp) { switch (current_cpu_data.processor_id & 0xff00) { +#ifdef CONFIG_DT_XLP_GVP + case PRID_IMP_NETLOGIC_XLP9XX: + fdtp = __dtb_xlp_gvp_begin; + break; +#endif #ifdef CONFIG_DT_XLP_FVP case PRID_IMP_NETLOGIC_XLP2XX: fdtp = __dtb_xlp_fvp_begin; diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 56c50ba43c9b..997cd9ee10de 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -57,6 +57,10 @@ void nlm_node_init(int node) nodep->sysbase = nlm_get_sys_regbase(node); nodep->picbase = nlm_get_pic_regbase(node); nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + if (cpu_is_xlp9xx()) + nodep->socbus = xlp9xx_get_socbus(node); + else + nodep->socbus = 0; spin_lock_init(&nodep->piclock); } @@ -65,6 +69,26 @@ int nlm_irq_to_irt(int irq) uint64_t pcibase; int devoff, irt; + /* bypass for 9xx */ + if (cpu_is_xlp9xx()) { + switch (irq) { + case PIC_9XX_XHCI_0_IRQ: + return 114; + case PIC_9XX_XHCI_1_IRQ: + return 115; + case PIC_UART_0_IRQ: + return 133; + case PIC_UART_1_IRQ: + return 134; + case PIC_PCIE_LINK_LEGACY_IRQ(0): + case PIC_PCIE_LINK_LEGACY_IRQ(1): + case PIC_PCIE_LINK_LEGACY_IRQ(2): + case PIC_PCIE_LINK_LEGACY_IRQ(3): + return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE; + } + return -1; + } + devoff = 0; switch (irq) { case PIC_UART_0_IRQ: @@ -135,9 +159,17 @@ int nlm_irq_to_irt(int irq) case PIC_I2C_3_IRQ: irt = irt + 3; break; } - } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { + } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) && + irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) { /* HW bug, PCI IRT entries are bad on early silicon, fix */ - irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); + irt = PIC_IRT_PCIE_LINK_INDEX(irq - + PIC_PCIE_LINK_LEGACY_IRQ_BASE); + } else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && + irq <= PIC_PCIE_LINK_MSI_IRQ(3)) { + irt = -2; + } else if (irq >= PIC_PCIE_MSIX_IRQ(0) && + irq <= PIC_PCIE_MSIX_IRQ(3)) { + irt = -2; } else { irt = -1; } @@ -151,7 +183,10 @@ unsigned int nlm_get_core_frequency(int node, int core) uint64_t num, sysbase; sysbase = nlm_get_node(node)->sysbase; - rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); + if (cpu_is_xlp9xx()) + rstval = nlm_read_sys_reg(sysbase, SYS_9XX_POWER_ON_RESET_CFG); + else + rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); if (cpu_is_xlpii()) { num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26)); denom = 3; @@ -265,6 +300,10 @@ static unsigned int nlm_2xx_get_pic_frequency(int node) unsigned int nlm_get_pic_frequency(int node) { + /* TODO Has to calculate freq as like 2xx */ + if (cpu_is_xlp9xx()) + return 250000000; + if (cpu_is_xlpii()) return nlm_2xx_get_pic_frequency(node); else @@ -284,21 +323,33 @@ int xlp_get_dram_map(int n, uint64_t *dram_map) { uint64_t bridgebase, base, lim; uint32_t val; + unsigned int barreg, limreg, xlatreg; int i, node, 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++) { - val = nlm_read_bridge_reg(bridgebase, - BRIDGE_DRAM_NODE_TRANSLN(i)); - node = (val >> 1) & 0x3; - if (n >= 0 && n != node) - continue; - val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i)); + if (cpu_is_xlp9xx()) { + barreg = BRIDGE_9XX_DRAM_BAR(i); + limreg = BRIDGE_9XX_DRAM_LIMIT(i); + xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i); + } else { + barreg = BRIDGE_DRAM_BAR(i); + limreg = BRIDGE_DRAM_LIMIT(i); + xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i); + } + if (n >= 0) { + /* node specified, get node mapping of BAR */ + val = nlm_read_bridge_reg(bridgebase, xlatreg); + node = (val >> 1) & 0x3; + if (n != node) + continue; + } + val = nlm_read_bridge_reg(bridgebase, barreg); val = (val >> 12) & 0xfffff; base = (uint64_t) val << 20; - val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i)); + val = nlm_read_bridge_reg(bridgebase, limreg); val = (val >> 12) & 0xfffff; if (val == 0) /* BAR not used */ continue; diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 54e75c77184b..8c60a2dd9ef6 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -51,12 +51,16 @@ 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) { uint64_t sysbase = nlm_get_node(0)->sysbase; - nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1); + if (cpu_is_xlp9xx()) + nlm_write_sys_reg(sysbase, SYS_9XX_CHIP_RESET, 1); + else + nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1); for ( ; ; ) cpu_wait(); } @@ -92,6 +96,14 @@ static void __init xlp_init_mem_from_bars(void) void __init plat_mem_setup(void) { +#ifdef CONFIG_SMP + nlm_wakeup_secondary_cpus(); + + /* update TLB size after waking up threads */ + current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1; + + register_smp_ops(&nlm_smp_ops); +#endif _machine_restart = (void (*)(char *))nlm_linux_exit; _machine_halt = nlm_linux_exit; pm_power_off = nlm_linux_exit; @@ -110,6 +122,7 @@ void __init plat_mem_setup(void) const char *get_system_type(void) { switch (read_c0_prid() & 0xff00) { + case PRID_IMP_NETLOGIC_XLP9XX: case PRID_IMP_NETLOGIC_XLP2XX: return "Broadcom XLPII Series"; default: @@ -149,6 +162,10 @@ 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); @@ -162,11 +179,5 @@ void __init prom_init(void) #ifdef CONFIG_SMP cpumask_setall(&nlm_cpumask); - nlm_wakeup_secondary_cpus(); - - /* update TLB size after waking up threads */ - current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1; - - register_smp_ops(&nlm_smp_ops); #endif } diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c index 36e9c22afc46..17ade1ce5dfd 100644 --- a/arch/mips/netlogic/xlp/usb-init-xlp2.c +++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c @@ -37,6 +37,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/pci_ids.h> #include <linux/platform_device.h> #include <linux/irq.h> @@ -83,12 +84,14 @@ #define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) #define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) -#define nlm_xlpii_get_usb_pcibase(node, inst) \ - nlm_pcicfg_base(XLP2XX_IO_USB_OFFSET(node, inst)) +#define nlm_xlpii_get_usb_pcibase(node, inst) \ + nlm_pcicfg_base(cpu_is_xlp9xx() ? \ + XLP9XX_IO_USB_OFFSET(node, inst) : \ + XLP2XX_IO_USB_OFFSET(node, inst)) #define nlm_xlpii_get_usb_regbase(node, inst) \ (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) -static void xlpii_usb_ack(struct irq_data *data) +static void xlp2xx_usb_ack(struct irq_data *data) { u64 port_addr; @@ -109,6 +112,29 @@ static void xlpii_usb_ack(struct irq_data *data) nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); } +static void xlp9xx_usb_ack(struct irq_data *data) +{ + u64 port_addr; + int node, irq; + + /* Find the node and irq on the node */ + irq = data->irq % NLM_IRQS_PER_NODE; + node = data->irq / NLM_IRQS_PER_NODE; + + switch (irq) { + case PIC_9XX_XHCI_0_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(node, 1); + break; + case PIC_9XX_XHCI_1_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(node, 2); + break; + default: + pr_err("No matching USB irq %d node %d!\n", irq, node); + return; + } + nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); +} + static void nlm_xlpii_usb_hw_reset(int node, int port) { u64 port_addr, xhci_base, pci_base; @@ -178,17 +204,33 @@ static void nlm_xlpii_usb_hw_reset(int node, int port) static int __init nlm_platform_xlpii_usb_init(void) { + int node; + if (!cpu_is_xlpii()) return 0; - pr_info("Initializing 2XX USB Interface\n"); - nlm_xlpii_usb_hw_reset(0, 1); - nlm_xlpii_usb_hw_reset(0, 2); - nlm_xlpii_usb_hw_reset(0, 3); - nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlpii_usb_ack); - nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlpii_usb_ack); - nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlpii_usb_ack); + if (!cpu_is_xlp9xx()) { + /* XLP 2XX single node */ + pr_info("Initializing 2XX USB Interface\n"); + nlm_xlpii_usb_hw_reset(0, 1); + nlm_xlpii_usb_hw_reset(0, 2); + nlm_xlpii_usb_hw_reset(0, 3); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack); + return 0; + } + /* XLP 9XX, multi-node */ + pr_info("Initializing 9XX 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_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); + } return 0; } @@ -196,8 +238,26 @@ arch_initcall(nlm_platform_xlpii_usb_init); static u64 xlp_usb_dmamask = ~(u32)0; -/* Fixup IRQ for USB devices on XLP the SoC PCIe bus */ -static void nlm_usb_fixup_final(struct pci_dev *dev) +/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */ +static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev) +{ + int node; + + node = xlp_socdev_to_node(dev); + dev->dev.dma_mask = &xlp_usb_dmamask; + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + switch (dev->devfn) { + case 0x21: + dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ); + break; + case 0x22: + dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ); + break; + } +} + +/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */ +static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev) { dev->dev.dma_mask = &xlp_usb_dmamask; dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); @@ -214,5 +274,7 @@ static void nlm_usb_fixup_final(struct pci_dev *dev) } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI, + nlm_xlp9xx_usb_fixup_final); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI, - nlm_usb_fixup_final); + nlm_xlp2xx_usb_fixup_final); diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 682d5638dc01..9a92617a2af5 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -32,7 +32,6 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/threads.h> @@ -47,14 +46,14 @@ #include <asm/netlogic/mips-extns.h> #include <asm/netlogic/xlp-hal/iomap.h> -#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/sys.h> static int xlp_wakeup_core(uint64_t sysbase, int node, int core) { uint32_t coremask, value; - int count; + int count, resetreg; coremask = (1 << core); @@ -65,12 +64,24 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core) nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); } + /* On 9XX, mark coherent first */ + if (cpu_is_xlp9xx()) { + value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE); + value &= ~coremask; + nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value); + } + /* Remove CPU Reset */ - value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); + resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET; + value = nlm_read_sys_reg(sysbase, resetreg); value &= ~coremask; - nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value); + nlm_write_sys_reg(sysbase, resetreg, value); + + /* We are done on 9XX */ + if (cpu_is_xlp9xx()) + return 1; - /* Poll for CPU to mark itself coherent */ + /* Poll for CPU to mark itself coherent on other type of XLP */ count = 100000; do { value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE); @@ -84,7 +95,7 @@ static int wait_for_cpus(int cpu, int bootcpu) volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); int i, count, notready; - count = 0x20000000; + count = 0x800000; do { notready = nlm_threads_per_core; for (i = 0; i < nlm_threads_per_core; i++) @@ -98,27 +109,62 @@ static int wait_for_cpus(int cpu, int bootcpu) static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) { struct nlm_soc_info *nodep; - uint64_t syspcibase; - uint32_t syscoremask; + uint64_t syspcibase, fusebase; + uint32_t syscoremask, mask, fusemask; int core, n, cpu; for (n = 0; n < NLM_NR_NODES; n++) { - syspcibase = nlm_get_sys_pcibase(n); - if (nlm_read_reg(syspcibase, 0) == 0xffffffff) - break; + if (n != 0) { + /* check if node exists and is online */ + if (cpu_is_xlp9xx()) { + int b = xlp9xx_get_socbus(n); + pr_info("Node %d SoC PCI bus %d.\n", n, b); + if (b == 0) + break; + } else { + syspcibase = nlm_get_sys_pcibase(n); + if (nlm_read_reg(syspcibase, 0) == 0xffffffff) + break; + } + nlm_node_init(n); + } /* read cores in reset from SYS */ - if (n != 0) - nlm_node_init(n); nodep = nlm_get_node(n); - syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); + + if (cpu_is_xlp9xx()) { + fusebase = nlm_get_fuse_regbase(n); + fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6); + mask = 0xfffff; + } else { + fusemask = nlm_read_sys_reg(nodep->sysbase, + SYS_EFUSE_DEVICE_CFG_STATUS0); + switch (read_c0_prid() & 0xff00) { + case PRID_IMP_NETLOGIC_XLP3XX: + mask = 0xf; + break; + case PRID_IMP_NETLOGIC_XLP2XX: + mask = 0x3; + break; + case PRID_IMP_NETLOGIC_XLP8XX: + default: + mask = 0xff; + break; + } + } + + /* + * Fused out cores are set in the fusemask, and the remaining + * cores are renumbered to range 0 .. nactive-1 + */ + syscoremask = (1 << hweight32(~fusemask & mask)) - 1; + /* The boot cpu */ - if (n == 0) { - syscoremask |= 1; + if (n == 0) nodep->coremask = 1; - } - for (core = 0; core < NLM_CORES_PER_NODE; core++) { + pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask); + for (core = 0; core < nlm_cores_per_node(); core++) { /* we will be on node 0 core 0 */ if (n == 0 && core == 0) continue; @@ -128,7 +174,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) + cpu = (n * nlm_cores_per_node() + core) * NLM_THREADS_PER_CORE; if (!cpumask_test_cpu(cpu, wakeup_mask)) continue; @@ -141,7 +187,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) nodep->coremask |= 1u << core; /* spin until the hw threads sets their ready */ - wait_for_cpus(cpu, 0); + if (!wait_for_cpus(cpu, 0)) + pr_err("Node %d : timeout core %d\n", n, core); } } } @@ -153,7 +200,8 @@ void xlp_wakeup_secondary_cpus() * first wakeup core 0 threads */ xlp_boot_core0_siblings(); - wait_for_cpus(0, 0); + if (!wait_for_cpus(0, 0)) + pr_err("Node 0 : timeout core 0\n"); /* now get other cores out of reset */ xlp_enable_secondary_cores(&nlm_cpumask); diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c index 7b96a91f4773..4785932af248 100644 --- a/arch/mips/netlogic/xlr/platform.c +++ b/arch/mips/netlogic/xlr/platform.c @@ -23,7 +23,7 @@ #include <asm/netlogic/xlr/pic.h> #include <asm/netlogic/xlr/xlr.h> -unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) +static unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) { uint64_t uartbase; unsigned int value; @@ -41,7 +41,7 @@ unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset) return value; } -void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) +static void nlm_xlr_uart_out(struct uart_port *p, int offset, int value) { uint64_t uartbase; diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index 921be5f77797..d118b9aa7647 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -60,25 +60,6 @@ unsigned int nlm_threads_per_core = 1; struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; cpumask_t nlm_cpumask = CPU_MASK_CPU0; -static void __init nlm_early_serial_setup(void) -{ - struct uart_port s; - unsigned long uart_base; - - uart_base = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); - memset(&s, 0, sizeof(s)); - s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; - s.iotype = UPIO_MEM32; - s.regshift = 2; - s.irq = PIC_UART_0_IRQ; - s.uartclk = PIC_CLK_HZ; - s.serial_in = nlm_xlr_uart_in; - s.serial_out = nlm_xlr_uart_out; - s.mapbase = uart_base; - s.membase = (unsigned char __iomem *)uart_base; - early_serial_setup(&s); -} - static void nlm_linux_exit(void) { uint64_t gpiobase; @@ -214,7 +195,6 @@ void __init prom_init(void) memcpy(reset_vec, (void *)nlm_reset_entry, (nlm_reset_entry_end - nlm_reset_entry)); - nlm_early_serial_setup(); build_arcs_cmdline(argv); prom_add_memory(); diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c index 9fb81fa6272a..d61cba1e9c65 100644 --- a/arch/mips/netlogic/xlr/wakeup.c +++ b/arch/mips/netlogic/xlr/wakeup.c @@ -32,7 +32,6 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> #include <linux/delay.h> #include <linux/threads.h> @@ -70,7 +69,7 @@ int xlr_wakeup_secondary_cpus(void) /* Fill up the coremask early */ nodep->coremask = 1; - for (i = 1; i < NLM_CORES_PER_NODE; i++) { + for (i = 1; i < nlm_cores_per_node(); i++) { for (j = 1000000; j > 0; j--) { if (cpu_ready[i * NLM_THREADS_PER_CORE]) break; diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index 4d1736fc1955..2a86e38872a7 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -86,6 +86,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_34K: case CPU_1004K: case CPU_74K: + case CPU_INTERAPTIV: + case CPU_PROAPTIV: case CPU_LOONGSON1: case CPU_SB1: case CPU_SB1A: diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 3a2b6e9f25cf..4d94d75ec6f9 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -376,6 +376,14 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/74K"; break; + case CPU_INTERAPTIV: + op_model_mipsxx_ops.cpu_type = "mips/interAptiv"; + break; + + case CPU_PROAPTIV: + op_model_mipsxx_ops.cpu_type = "mips/proAptiv"; + break; + case CPU_5KC: op_model_mipsxx_ops.cpu_type = "mips/5K"; break; diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 719e4557e22e..137f2a6feb25 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -60,4 +60,5 @@ obj-$(CONFIG_CPU_XLP) += pci-xlp.o ifdef CONFIG_PCI_MSI obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o +obj-$(CONFIG_CPU_XLP) += msi-xlp.o endif diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c index df36e2327c54..7a0eda782e35 100644 --- a/arch/mips/pci/fixup-malta.c +++ b/arch/mips/pci/fixup-malta.c @@ -54,6 +54,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) static void malta_piix_func0_fixup(struct pci_dev *pdev) { unsigned char reg_val; + u32 reg_val32; /* PIIX PIRQC[A:D] irq mappings */ static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = { 0, 0, 0, 3, @@ -83,6 +84,16 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev) pci_write_config_byte(pdev, PIIX4_FUNC0_TOM, reg_val | PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK); } + + /* Mux SERIRQ to its pin */ + pci_read_config_dword(pdev, PIIX4_FUNC0_GENCFG, ®_val32); + pci_write_config_dword(pdev, PIIX4_FUNC0_GENCFG, + reg_val32 | PIIX4_FUNC0_GENCFG_SERIRQ); + + /* Enable SERIRQ */ + pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_val); + reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT; + pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, diff --git a/arch/mips/pci/fixup-rc32434.c b/arch/mips/pci/fixup-rc32434.c index d0f6ecbf35f7..7fcafd5da7da 100644 --- a/arch/mips/pci/fixup-rc32434.c +++ b/arch/mips/pci/fixup-rc32434.c @@ -27,7 +27,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mach-rc32434/rc32434.h> #include <asm/mach-rc32434/irq.h> diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c index 1441becdcb6c..8feae9154baf 100644 --- a/arch/mips/pci/fixup-sb1250.c +++ b/arch/mips/pci/fixup-sb1250.c @@ -8,7 +8,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/init.h> #include <linux/pci.h> /* diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c new file mode 100644 index 000000000000..afd8405e0188 --- /dev/null +++ b/arch/mips/pci/msi-xlp.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/msi.h> +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/irqdesc.h> +#include <linux/console.h> + +#include <asm/io.h> + +#include <asm/netlogic/interrupt.h> +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h> +#include <asm/netlogic/mips-extns.h> + +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> +#include <asm/netlogic/xlp-hal/pcibus.h> +#include <asm/netlogic/xlp-hal/bridge.h> + +#define XLP_MSIVEC_PER_LINK 32 +#define XLP_MSIXVEC_TOTAL 32 +#define XLP_MSIXVEC_PER_LINK 8 + +/* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ +static inline int nlm_link_msiirq(int link, int msivec) +{ + return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; +} + +static inline int nlm_irq_msivec(int irq) +{ + return irq % XLP_MSIVEC_PER_LINK; +} + +static inline int nlm_irq_msilink(int irq) +{ + return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) / + XLP_MSIVEC_PER_LINK; +} + +/* + * Only 32 MSI-X vectors are possible because there are only 32 PIC + * interrupts for MSI. We split them statically and use 8 MSI-X vectors + * per link - this keeps the allocation and lookup simple. + */ +static inline int nlm_link_msixirq(int link, int bit) +{ + return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; +} + +static inline int nlm_irq_msixvec(int irq) +{ + return irq % XLP_MSIXVEC_TOTAL; /* works when given xirq */ +} + +static inline int nlm_irq_msixlink(int irq) +{ + return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK; +} + +/* + * Per link MSI and MSI-X information, set as IRQ handler data for + * MSI and MSI-X interrupts. + */ +struct xlp_msi_data { + struct nlm_soc_info *node; + uint64_t lnkbase; + uint32_t msi_enabled_mask; + uint32_t msi_alloc_mask; + uint32_t msix_alloc_mask; + spinlock_t msi_lock; +}; + +/* + * MSI Chip definitions + * + * On XLP, there is a PIC interrupt associated with each PCIe link on the + * chip (which appears as a PCI bridge to us). This gives us 32 MSI irqa + * per link and 128 overall. + * + * When a device connected to the link raises a MSI interrupt, we get a + * link interrupt and we then have to look at PCIE_MSI_STATUS register at + * the bridge to map it to the IRQ + */ +static void xlp_msi_enable(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + unsigned long flags; + int vec; + + vec = nlm_irq_msivec(d->irq); + spin_lock_irqsave(&md->msi_lock, flags); + md->msi_enabled_mask |= 1u << vec; + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + spin_unlock_irqrestore(&md->msi_lock, flags); +} + +static void xlp_msi_disable(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + unsigned long flags; + int vec; + + vec = nlm_irq_msivec(d->irq); + spin_lock_irqsave(&md->msi_lock, flags); + md->msi_enabled_mask &= ~(1u << vec); + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + spin_unlock_irqrestore(&md->msi_lock, flags); +} + +static void xlp_msi_mask_ack(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + int link, vec; + + link = nlm_irq_msilink(d->irq); + vec = nlm_irq_msivec(d->irq); + xlp_msi_disable(d); + + /* Ack MSI on bridge */ + nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); + + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); + nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); +} + +static struct irq_chip xlp_msi_chip = { + .name = "XLP-MSI", + .irq_enable = xlp_msi_enable, + .irq_disable = xlp_msi_disable, + .irq_mask_ack = xlp_msi_mask_ack, + .irq_unmask = xlp_msi_enable, +}; + +/* + * The MSI-X interrupt handling is different from MSI, there are 32 + * MSI-X interrupts generated by the PIC and each of these correspond + * to a MSI-X vector (0-31) that can be assigned. + * + * We divide the MSI-X vectors to 8 per link and do a per-link + * allocation + * + * Enable and disable done using standard MSI functions. + */ +static void xlp_msix_mask_ack(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + int link, msixvec; + + msixvec = nlm_irq_msixvec(d->irq); + link = nlm_irq_msixlink(d->irq); + mask_msi_irq(d); + + /* Ack MSI on bridge */ + nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec); + + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); + nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); +} + +static struct irq_chip xlp_msix_chip = { + .name = "XLP-MSIX", + .irq_enable = unmask_msi_irq, + .irq_disable = mask_msi_irq, + .irq_mask_ack = xlp_msix_mask_ack, + .irq_unmask = unmask_msi_irq, +}; + +void destroy_irq(unsigned int irq) +{ + /* nothing to do yet */ +} + +void arch_teardown_msi_irq(unsigned int irq) +{ + destroy_irq(irq); +} + +/* + * Setup a PCIe link for MSI. By default, the links are in + * legacy interrupt mode. We will switch them to MSI mode + * at the first MSI request. + */ +static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr) +{ + u32 val; + + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } + + val = nlm_read_reg(lnkbase, 0x1); /* CMD */ + if ((val & 0x0400) == 0) { + val |= 0x0400; + nlm_write_reg(lnkbase, 0x1, val); + } + + /* Update IRQ in the PCI irq reg */ + val = nlm_read_pci_reg(lnkbase, 0xf); + val &= ~0x1fu; + val |= (1 << 8) | lirq; + nlm_write_pci_reg(lnkbase, 0xf, val); + + /* MSI addr */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRH, msiaddr >> 32); + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRL, msiaddr & 0xffffffff); + + /* MSI cap for bridge */ + val = nlm_read_reg(lnkbase, PCIE_BRIDGE_MSI_CAP); + if ((val & (1 << 16)) == 0) { + val |= 0xb << 16; /* mmc32, msi enable */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_CAP, val); + } +} + +/* + * Allocate a MSI vector on a link + */ +static int xlp_setup_msi(uint64_t lnkbase, int node, int link, + struct msi_desc *desc) +{ + struct xlp_msi_data *md; + struct msi_msg msg; + unsigned long flags; + int msivec, irt, lirq, xirq, ret; + uint64_t msiaddr; + + /* Get MSI data for the link */ + lirq = PIC_PCIE_LINK_MSI_IRQ(link); + xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + md = irq_get_handler_data(xirq); + msiaddr = MSI_LINK_ADDR(node, link); + + spin_lock_irqsave(&md->msi_lock, flags); + if (md->msi_alloc_mask == 0) { + /* switch the link IRQ to MSI range */ + xlp_config_link_msi(lnkbase, lirq, msiaddr); + irt = PIC_IRT_PCIE_LINK_INDEX(link); + nlm_setup_pic_irq(node, lirq, lirq, irt); + nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, + node * nlm_threads_per_node(), 1 /*en */); + } + + /* allocate a MSI vec, and tell the bridge about it */ + msivec = fls(md->msi_alloc_mask); + if (msivec == XLP_MSIVEC_PER_LINK) { + spin_unlock_irqrestore(&md->msi_lock, flags); + return -ENOMEM; + } + md->msi_alloc_mask |= (1u << msivec); + spin_unlock_irqrestore(&md->msi_lock, flags); + + msg.address_hi = msiaddr >> 32; + msg.address_lo = msiaddr & 0xffffffff; + msg.data = 0xc00 | msivec; + + xirq = xirq + msivec; /* msi mapped to global irq space */ + ret = irq_set_msi_desc(xirq, desc); + if (ret < 0) { + destroy_irq(xirq); + return ret; + } + + write_msi_msg(xirq, &msg); + return 0; +} + +/* + * Switch a link to MSI-X mode + */ +static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) +{ + u32 val; + + val = nlm_read_reg(lnkbase, 0x2C); + if ((val & 0x80000000U) == 0) { + val |= 0x80000000U; + nlm_write_reg(lnkbase, 0x2C, val); + } + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } + + val = nlm_read_reg(lnkbase, 0x1); /* CMD */ + if ((val & 0x0400) == 0) { + val |= 0x0400; + nlm_write_reg(lnkbase, 0x1, val); + } + + /* Update IRQ in the PCI irq reg */ + val = nlm_read_pci_reg(lnkbase, 0xf); + val &= ~0x1fu; + val |= (1 << 8) | lirq; + nlm_write_pci_reg(lnkbase, 0xf, val); + + /* MSI-X addresses */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8); + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, + (msixaddr + MSI_ADDR_SZ) >> 8); +} + +/* + * Allocate a MSI-X vector + */ +static int xlp_setup_msix(uint64_t lnkbase, int node, int link, + struct msi_desc *desc) +{ + struct xlp_msi_data *md; + struct msi_msg msg; + unsigned long flags; + int t, msixvec, lirq, xirq, ret; + uint64_t msixaddr; + + /* Get MSI data for the link */ + lirq = PIC_PCIE_MSIX_IRQ(link); + xirq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); + md = irq_get_handler_data(xirq); + msixaddr = MSIX_LINK_ADDR(node, link); + + spin_lock_irqsave(&md->msi_lock, flags); + /* switch the PCIe link to MSI-X mode at the first alloc */ + if (md->msix_alloc_mask == 0) + xlp_config_link_msix(lnkbase, lirq, msixaddr); + + /* allocate a MSI-X vec, and tell the bridge about it */ + t = fls(md->msix_alloc_mask); + if (t == XLP_MSIXVEC_PER_LINK) { + spin_unlock_irqrestore(&md->msi_lock, flags); + return -ENOMEM; + } + md->msix_alloc_mask |= (1u << t); + spin_unlock_irqrestore(&md->msi_lock, flags); + + xirq += t; + msixvec = nlm_irq_msixvec(xirq); + msg.address_hi = msixaddr >> 32; + msg.address_lo = msixaddr & 0xffffffff; + msg.data = 0xc00 | msixvec; + + ret = irq_set_msi_desc(xirq, desc); + if (ret < 0) { + destroy_irq(xirq); + return ret; + } + + write_msi_msg(xirq, &msg); + return 0; +} + +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ + struct pci_dev *lnkdev; + uint64_t lnkbase; + int node, link, slot; + + lnkdev = xlp_get_pcie_link(dev); + if (lnkdev == NULL) { + dev_err(&dev->dev, "Could not find bridge\n"); + return 1; + } + slot = PCI_SLOT(lnkdev->devfn); + link = PCI_FUNC(lnkdev->devfn); + node = slot / 8; + lnkbase = nlm_get_pcie_base(node, link); + + if (desc->msi_attrib.is_msix) + return xlp_setup_msix(lnkbase, node, link, desc); + else + return xlp_setup_msi(lnkbase, node, link, desc); +} + +void __init xlp_init_node_msi_irqs(int node, int link) +{ + struct nlm_soc_info *nodep; + struct xlp_msi_data *md; + int irq, i, irt, msixvec; + + pr_info("[%d %d] Init node PCI IRT\n", node, link); + nodep = nlm_get_node(node); + + /* Alloc an MSI block for the link */ + md = kzalloc(sizeof(*md), GFP_KERNEL); + spin_lock_init(&md->msi_lock); + md->msi_enabled_mask = 0; + md->msi_alloc_mask = 0; + md->msix_alloc_mask = 0; + md->node = nodep; + md->lnkbase = nlm_get_pcie_base(node, link); + + /* extended space for MSI interrupts */ + irq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + for (i = irq; i < irq + XLP_MSIVEC_PER_LINK; i++) { + irq_set_chip_and_handler(i, &xlp_msi_chip, handle_level_irq); + irq_set_handler_data(i, md); + } + + for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) { + /* Initialize MSI-X irts to generate one interrupt per link */ + msixvec = link * XLP_MSIXVEC_PER_LINK + i; + irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); + nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link), + node * nlm_threads_per_node(), 1 /* enable */); + + /* Initialize MSI-X extended irq space for the link */ + irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); + irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); + irq_set_handler_data(irq, md); + } + +} + +void nlm_dispatch_msi(int node, int lirq) +{ + struct xlp_msi_data *md; + int link, i, irqbase; + u32 status; + + link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; + irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + md = irq_get_handler_data(irqbase); + status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & + md->msi_enabled_mask; + while (status) { + i = __ffs(status); + do_IRQ(irqbase + i); + status &= status - 1; + } +} + +void nlm_dispatch_msix(int node, int lirq) +{ + struct xlp_msi_data *md; + int link, i, irqbase; + u32 status; + + link = lirq - PIC_PCIE_MSIX_IRQ_BASE; + irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); + md = irq_get_handler_data(irqbase); + status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); + + /* narrow it down to the MSI-x vectors for our link */ + status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & + ((1 << XLP_MSIXVEC_PER_LINK) - 1); + + while (status) { + i = __ffs(status); + do_IRQ(irqbase + i); + status &= status - 1; + } +} diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c index 6144bb337e44..13eea696bbe7 100644 --- a/arch/mips/pci/ops-bcm63xx.c +++ b/arch/mips/pci/ops-bcm63xx.c @@ -9,7 +9,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/io.h> diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c index 830352e3aeda..c06205a87348 100644 --- a/arch/mips/pci/ops-bonito64.c +++ b/arch/mips/pci/ops-bonito64.c @@ -22,7 +22,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mips-boards/bonito64.h> diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c index 16e7c2526d77..e5738ee26f4f 100644 --- a/arch/mips/pci/ops-lantiq.c +++ b/arch/mips/pci/ops-lantiq.c @@ -9,7 +9,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/mm.h> #include <asm/addrspace.h> diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c index 98254afa0287..24138bb0cbe1 100644 --- a/arch/mips/pci/ops-loongson2.c +++ b/arch/mips/pci/ops-loongson2.c @@ -14,7 +14,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/export.h> #include <loongson.h> diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c index 1cfb5588699f..6b5821febc38 100644 --- a/arch/mips/pci/ops-mace.c +++ b/arch/mips/pci/ops-mace.c @@ -6,7 +6,6 @@ * Copyright (C) 2000, 2001 Keith M Wesolowski */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/pci.h> #include <linux/types.h> #include <asm/pci.h> diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c index 92a8543361bb..dbbf3657896c 100644 --- a/arch/mips/pci/ops-msc.c +++ b/arch/mips/pci/ops-msc.c @@ -24,7 +24,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mips-boards/msc01_pci.h> diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c index 499e35c3eb35..a1a7c9f4096e 100644 --- a/arch/mips/pci/ops-nile4.c +++ b/arch/mips/pci/ops-nile4.c @@ -1,5 +1,4 @@ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/pci.h> #include <asm/bootinfo.h> diff --git a/arch/mips/pci/ops-rc32434.c b/arch/mips/pci/ops-rc32434.c index 7c7182e2350a..874ed6df9768 100644 --- a/arch/mips/pci/ops-rc32434.c +++ b/arch/mips/pci/ops-rc32434.c @@ -26,7 +26,6 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/delay.h> -#include <linux/init.h> #include <linux/io.h> #include <linux/pci.h> #include <linux/types.h> diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 162b4cb29dba..0f09eafa5e3a 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -7,7 +7,6 @@ * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/export.h> #include <linux/pci.h> diff --git a/arch/mips/pci/pci-malta.c b/arch/mips/pci/pci-malta.c index 37134ddfeaa5..f1a73890dd4f 100644 --- a/arch/mips/pci/pci-malta.c +++ b/arch/mips/pci/pci-malta.c @@ -241,9 +241,9 @@ void __init mips_pcibios_init(void) return; } - /* Change start address to avoid conflicts with ACPI and SMB devices */ - if (controller->io_resource->start < 0x00002000UL) - controller->io_resource->start = 0x00002000UL; + /* PIIX4 ACPI starts at 0x1000 */ + if (controller->io_resource->start < 0x00001000UL) + controller->io_resource->start = 0x00001000UL; iomem_resource.end &= 0xfffffffffULL; /* 64 GB */ ioport_resource.end = controller->io_resource->end; diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c index adeff2bfe4cd..72919aeef42b 100644 --- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c @@ -436,9 +436,6 @@ static int rt3883_pci_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - rpc->base = devm_ioremap_resource(dev, res); if (IS_ERR(rpc->base)) return PTR_ERR(rpc->base); diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c index 653d2db9e0c5..7babf01600cb 100644 --- a/arch/mips/pci/pci-xlp.c +++ b/arch/mips/pci/pci-xlp.c @@ -47,10 +47,11 @@ #include <asm/netlogic/interrupt.h> #include <asm/netlogic/haldefs.h> #include <asm/netlogic/common.h> +#include <asm/netlogic/mips-extns.h> #include <asm/netlogic/xlp-hal/iomap.h> -#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/pcibus.h> #include <asm/netlogic/xlp-hal/bridge.h> @@ -66,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn, u32 *cfgaddr; where &= ~3; - if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) + if (cpu_is_xlp9xx()) { + /* be very careful on SoC buses */ + if (bus->number == 0) { + /* Scan only existing nodes - uboot bug? */ + if (PCI_SLOT(devfn) != 0 || + !nlm_node_present(PCI_FUNC(devfn))) + return 0xffffffff; + } else if (bus->parent->number == 0) { /* SoC bus */ + if (PCI_SLOT(devfn) == 0) /* b.0.0 hangs */ + return 0xffffffff; + if (devfn == 44) /* b.5.4 hangs */ + return 0xffffffff; + } + } else if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) { return 0xffffffff; - + } cfgaddr = (u32 *)(pci_config_base + pci_cfg_addr(bus->number, devfn, where)); data = *cfgaddr; @@ -162,27 +176,39 @@ struct pci_controller nlm_pci_controller = { .io_offset = 0x00000000UL, }; -static struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev) +struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev) { struct pci_bus *bus, *p; - /* Find the bridge on bus 0 */ bus = dev->bus; - for (p = bus->parent; p && p->number != 0; p = p->parent) - bus = p; - return p ? bus->self : NULL; + if (cpu_is_xlp9xx()) { + /* find bus with grand parent number == 0 */ + for (p = bus->parent; p && p->parent && p->parent->number != 0; + p = p->parent) + bus = p; + return (p && p->parent) ? bus->self : NULL; + } else { + /* Find the bridge on bus 0 */ + for (p = bus->parent; p && p->number != 0; p = p->parent) + bus = p; + + return p ? bus->self : NULL; + } } -static inline int nlm_pci_link_to_irq(int link) +int xlp_socdev_to_node(const struct pci_dev *lnkdev) { - return PIC_PCIE_LINK_0_IRQ + link; + if (cpu_is_xlp9xx()) + return PCI_FUNC(lnkdev->bus->self->devfn); + else + return PCI_SLOT(lnkdev->devfn) / 8; } int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pci_dev *lnkdev; - int lnkslot, lnkfunc; + int lnkfunc, node; /* * For XLP PCIe, there is an IRQ per Link, find out which @@ -191,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) lnkdev = xlp_get_pcie_link(dev); if (lnkdev == NULL) return 0; + lnkfunc = PCI_FUNC(lnkdev->devfn); - lnkslot = PCI_SLOT(lnkdev->devfn); - return nlm_irq_to_xirq(lnkslot / 8, nlm_pci_link_to_irq(lnkfunc)); + node = xlp_socdev_to_node(lnkdev); + + return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc)); } /* Do platform specific device initialization at pci_enable_device() time */ @@ -220,17 +248,38 @@ static void xlp_config_pci_bswap(int node, int link) * Enable byte swap in hardware. Program each link's PCIe SWAP regions * from the link's address ranges. */ - reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); - nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); - - reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link); - nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); - - reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); - nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); - - reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); - nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); + if (cpu_is_xlp9xx()) { + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEMEM_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEMEM_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, + PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEIO_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_IO_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEIO_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, + PCIE_9XX_BYTE_SWAP_IO_LIM, reg | 0xfff); + } else { + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_PCIEMEM_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); + + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); + } } #else /* Swap configuration not needed in little-endian mode */ @@ -239,7 +288,6 @@ static inline void xlp_config_pci_bswap(int node, int link) {} static int __init pcibios_init(void) { - struct nlm_soc_info *nodep; uint64_t pciebase; int link, n; u32 reg; @@ -253,20 +301,20 @@ static int __init pcibios_init(void) ioport_resource.end = ~0; for (n = 0; n < NLM_NR_NODES; n++) { - nodep = nlm_get_node(n); - if (!nodep->coremask) - continue; /* node does not exist */ + if (!nlm_node_present(n)) + continue; - for (link = 0; link < 4; link++) { + for (link = 0; link < PCIE_NLINKS; link++) { pciebase = nlm_get_pcie_base(n, link); if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) continue; xlp_config_pci_bswap(n, link); + xlp_init_node_msi_irqs(n, link); /* put in intpin and irq - u-boot does not */ reg = nlm_read_pci_reg(pciebase, 0xf); - reg &= ~0x1fu; - reg |= (1 << 8) | nlm_pci_link_to_irq(link); + reg &= ~0x1ffu; + reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link); nlm_write_pci_reg(pciebase, 0xf, reg); pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link); } diff --git a/arch/mips/pmcs-msp71xx/Kconfig b/arch/mips/pmcs-msp71xx/Kconfig index 3482b8c8640c..6073ca456d11 100644 --- a/arch/mips/pmcs-msp71xx/Kconfig +++ b/arch/mips/pmcs-msp71xx/Kconfig @@ -6,6 +6,7 @@ config PMC_MSP4200_EVAL bool "PMC-Sierra MSP4200 Eval Board" select IRQ_MSP_SLP select HW_HAS_PCI + select MIPS_L1_CACHE_SHIFT_4 config PMC_MSP4200_GW bool "PMC-Sierra MSP4200 VoIP Gateway" diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index 424f03496d14..1bfd1c17b3c2 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -15,6 +15,7 @@ choice config SOC_RT288X bool "RT288x" + select MIPS_L1_CACHE_SHIFT_4 config SOC_RT305X bool "RT305x" diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c index b952d5b1af86..45fdfbcbd4c6 100644 --- a/arch/mips/sgi-ip27/ip27-console.c +++ b/arch/mips/sgi-ip27/ip27-console.c @@ -5,7 +5,6 @@ * * Copyright (C) 2001, 2002 Ralf Baechle */ -#include <linux/init.h> #include <asm/page.h> #include <asm/sn/addrs.h> diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c index ec22ec5600f3..2a1c40784bd9 100644 --- a/arch/mips/sgi-ip27/ip27-irq-pci.c +++ b/arch/mips/sgi-ip27/ip27-irq-pci.c @@ -8,7 +8,6 @@ #undef DEBUG -#include <linux/init.h> #include <linux/irq.h> #include <linux/errno.h> #include <linux/signal.h> diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c index 7afe14688003..c873d62ff083 100644 --- a/arch/mips/sgi-ip27/ip27-klconfig.c +++ b/arch/mips/sgi-ip27/ip27-klconfig.c @@ -2,7 +2,6 @@ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/interrupt.h> diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index d59b820f528d..20f582a2137a 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -7,7 +7,6 @@ * Generic XTALK initialization code */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/smp.h> #include <asm/sn/types.h> diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 7c081b38ef3e..0ee48be23837 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -75,6 +75,7 @@ config BCMA_DRIVER_GMAC_CMN config BCMA_DRIVER_GPIO bool "BCMA GPIO driver" depends on BCMA && GPIOLIB + select IRQ_DOMAIN if BCMA_HOST_SOC help Driver to provide access to the GPIO pins of the bcma bus. diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 45f0996a3752..25f9887a35d0 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -9,6 +9,9 @@ */ #include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/irqdomain.h> #include <linux/export.h> #include <linux/bcma/bcma.h> @@ -73,19 +76,136 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); } +#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) - return bcma_core_irq(cc->core); + return irq_find_mapping(cc->irq_domain, gpio); else return -EINVAL; } +static void bcma_gpio_irq_unmask(struct irq_data *d) +{ + struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = bcma_chipco_gpio_in(cc, BIT(gpio)); + + bcma_chipco_gpio_polarity(cc, BIT(gpio), val); + bcma_chipco_gpio_intmask(cc, BIT(gpio), BIT(gpio)); +} + +static void bcma_gpio_irq_mask(struct irq_data *d) +{ + struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + + bcma_chipco_gpio_intmask(cc, BIT(gpio), 0); +} + +static struct irq_chip bcma_gpio_irq_chip = { + .name = "BCMA-GPIO", + .irq_mask = bcma_gpio_irq_mask, + .irq_unmask = bcma_gpio_irq_unmask, +}; + +static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id) +{ + struct bcma_drv_cc *cc = dev_id; + u32 val = bcma_cc_read32(cc, BCMA_CC_GPIOIN); + u32 mask = bcma_cc_read32(cc, BCMA_CC_GPIOIRQ); + u32 pol = bcma_cc_read32(cc, BCMA_CC_GPIOPOL); + unsigned long irqs = (val ^ pol) & mask; + int gpio; + + if (!irqs) + return IRQ_NONE; + + for_each_set_bit(gpio, &irqs, cc->gpio.ngpio) + generic_handle_irq(bcma_gpio_to_irq(&cc->gpio, gpio)); + bcma_chipco_gpio_polarity(cc, irqs, val & irqs); + + return IRQ_HANDLED; +} + +static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc) +{ + struct gpio_chip *chip = &cc->gpio; + int gpio, hwirq, err; + + if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) + return 0; + + cc->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, + &irq_domain_simple_ops, cc); + if (!cc->irq_domain) { + err = -ENODEV; + goto err_irq_domain; + } + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_create_mapping(cc->irq_domain, gpio); + + irq_set_chip_data(irq, cc); + irq_set_chip_and_handler(irq, &bcma_gpio_irq_chip, + handle_simple_irq); + } + + hwirq = bcma_core_irq(cc->core); + err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio", + cc); + if (err) + goto err_req_irq; + + bcma_chipco_gpio_intmask(cc, ~0, 0); + bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO); + + return 0; + +err_req_irq: + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(cc->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(cc->irq_domain); +err_irq_domain: + return err; +} + +static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc) +{ + struct gpio_chip *chip = &cc->gpio; + int gpio; + + if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) + return; + + bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO); + free_irq(bcma_core_irq(cc->core), cc); + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(cc->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(cc->irq_domain); +} +#else +static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc) +{ + return 0; +} + +static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc) +{ +} +#endif + int bcma_gpio_init(struct bcma_drv_cc *cc) { struct gpio_chip *chip = &cc->gpio; + int err; chip->label = "bcma_gpio"; chip->owner = THIS_MODULE; @@ -95,7 +215,9 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) chip->set = bcma_gpio_set_value; chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; +#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) chip->to_irq = bcma_gpio_to_irq; +#endif chip->ngpio = 16; /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get @@ -105,10 +227,21 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) else chip->base = -1; - return gpiochip_add(chip); + err = bcma_gpio_irq_domain_init(cc); + if (err) + return err; + + err = gpiochip_add(chip); + if (err) { + bcma_gpio_irq_domain_exit(cc); + return err; + } + + return 0; } int bcma_gpio_unregister(struct bcma_drv_cc *cc) { + bcma_gpio_irq_domain_exit(cc); return gpiochip_remove(&cc->gpio); } diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 2cd9b0e44a41..75b3603906c1 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -168,6 +168,7 @@ config SSB_DRIVER_GIGE config SSB_DRIVER_GPIO bool "SSB GPIO driver" depends on SSB && GPIOLIB + select IRQ_DOMAIN if SSB_EMBEDDED help Driver to provide access to the GPIO pins on the bus. diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index dc109de228c6..ba350d2035c0 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c @@ -9,16 +9,40 @@ */ #include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/irqdomain.h> #include <linux/export.h> #include <linux/ssb/ssb.h> #include "ssb_private.h" + +/************************************************** + * Shared + **************************************************/ + static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) { return container_of(chip, struct ssb_bus, gpio); } +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + struct ssb_bus *bus = ssb_gpio_get_bus(chip); + + if (bus->bustype == SSB_BUSTYPE_SSB) + return irq_find_mapping(bus->irq_domain, gpio); + else + return -EINVAL; +} +#endif + +/************************************************** + * ChipCommon + **************************************************/ + static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) { struct ssb_bus *bus = ssb_gpio_get_bus(chip); @@ -74,19 +98,129 @@ static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); } -static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio) +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static void ssb_gpio_irq_chipco_mask(struct irq_data *d) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); - if (bus->bustype == SSB_BUSTYPE_SSB) - return ssb_mips_irq(bus->chipco.dev) + 2; - else - return -EINVAL; + ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0); +} + +static void ssb_gpio_irq_chipco_unmask(struct irq_data *d) +{ + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio)); + + ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val); + ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio)); +} + +static struct irq_chip ssb_gpio_irq_chipco_chip = { + .name = "SSB-GPIO-CC", + .irq_mask = ssb_gpio_irq_chipco_mask, + .irq_unmask = ssb_gpio_irq_chipco_unmask, +}; + +static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id) +{ + struct ssb_bus *bus = dev_id; + struct ssb_chipcommon *chipco = &bus->chipco; + u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN); + u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ); + u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL); + unsigned long irqs = (val ^ pol) & mask; + int gpio; + + if (!irqs) + return IRQ_NONE; + + for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) + generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); + ssb_chipco_gpio_polarity(chipco, irqs, val & irqs); + + return IRQ_HANDLED; +} + +static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) +{ + struct ssb_chipcommon *chipco = &bus->chipco; + struct gpio_chip *chip = &bus->gpio; + int gpio, hwirq, err; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return 0; + + bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, + &irq_domain_simple_ops, chipco); + if (!bus->irq_domain) { + err = -ENODEV; + goto err_irq_domain; + } + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_create_mapping(bus->irq_domain, gpio); + + irq_set_chip_data(irq, bus); + irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip, + handle_simple_irq); + } + + hwirq = ssb_mips_irq(bus->chipco.dev) + 2; + err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED, + "gpio", bus); + if (err) + goto err_req_irq; + + ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0); + chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO); + + return 0; + +err_req_irq: + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +err_irq_domain: + return err; +} + +static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) +{ + struct ssb_chipcommon *chipco = &bus->chipco; + struct gpio_chip *chip = &bus->gpio; + int gpio; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return; + + chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO); + free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco); + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +} +#else +static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) +{ + return 0; } +static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) +{ +} +#endif + static int ssb_gpio_chipco_init(struct ssb_bus *bus) { struct gpio_chip *chip = &bus->gpio; + int err; chip->label = "ssb_chipco_gpio"; chip->owner = THIS_MODULE; @@ -96,7 +230,9 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) chip->set = ssb_gpio_chipco_set_value; chip->direction_input = ssb_gpio_chipco_direction_input; chip->direction_output = ssb_gpio_chipco_direction_output; - chip->to_irq = ssb_gpio_chipco_to_irq; +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) + chip->to_irq = ssb_gpio_to_irq; +#endif chip->ngpio = 16; /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get @@ -106,9 +242,23 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) else chip->base = -1; - return gpiochip_add(chip); + err = ssb_gpio_irq_chipco_domain_init(bus); + if (err) + return err; + + err = gpiochip_add(chip); + if (err) { + ssb_gpio_irq_chipco_domain_exit(bus); + return err; + } + + return 0; } +/************************************************** + * EXTIF + **************************************************/ + #ifdef CONFIG_SSB_DRIVER_EXTIF static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) @@ -145,19 +295,127 @@ static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, return 0; } -static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio) +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static void ssb_gpio_irq_extif_mask(struct irq_data *d) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); - if (bus->bustype == SSB_BUSTYPE_SSB) - return ssb_mips_irq(bus->extif.dev) + 2; - else - return -EINVAL; + ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0); +} + +static void ssb_gpio_irq_extif_unmask(struct irq_data *d) +{ + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio)); + + ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val); + ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio)); +} + +static struct irq_chip ssb_gpio_irq_extif_chip = { + .name = "SSB-GPIO-EXTIF", + .irq_mask = ssb_gpio_irq_extif_mask, + .irq_unmask = ssb_gpio_irq_extif_unmask, +}; + +static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id) +{ + struct ssb_bus *bus = dev_id; + struct ssb_extif *extif = &bus->extif; + u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN); + u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK); + u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL); + unsigned long irqs = (val ^ pol) & mask; + int gpio; + + if (!irqs) + return IRQ_NONE; + + for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) + generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); + ssb_extif_gpio_polarity(extif, irqs, val & irqs); + + return IRQ_HANDLED; +} + +static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) +{ + struct ssb_extif *extif = &bus->extif; + struct gpio_chip *chip = &bus->gpio; + int gpio, hwirq, err; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return 0; + + bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, + &irq_domain_simple_ops, extif); + if (!bus->irq_domain) { + err = -ENODEV; + goto err_irq_domain; + } + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_create_mapping(bus->irq_domain, gpio); + + irq_set_chip_data(irq, bus); + irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip, + handle_simple_irq); + } + + hwirq = ssb_mips_irq(bus->extif.dev) + 2; + err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED, + "gpio", bus); + if (err) + goto err_req_irq; + + ssb_extif_gpio_intmask(&bus->extif, ~0, 0); + + return 0; + +err_req_irq: + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +err_irq_domain: + return err; +} + +static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) +{ + struct ssb_extif *extif = &bus->extif; + struct gpio_chip *chip = &bus->gpio; + int gpio; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return; + + free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif); + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); } +#else +static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) +{ + return 0; +} + +static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) +{ +} +#endif static int ssb_gpio_extif_init(struct ssb_bus *bus) { struct gpio_chip *chip = &bus->gpio; + int err; chip->label = "ssb_extif_gpio"; chip->owner = THIS_MODULE; @@ -165,7 +423,9 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) chip->set = ssb_gpio_extif_set_value; chip->direction_input = ssb_gpio_extif_direction_input; chip->direction_output = ssb_gpio_extif_direction_output; - chip->to_irq = ssb_gpio_extif_to_irq; +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) + chip->to_irq = ssb_gpio_to_irq; +#endif chip->ngpio = 5; /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get @@ -175,7 +435,17 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) else chip->base = -1; - return gpiochip_add(chip); + err = ssb_gpio_irq_extif_domain_init(bus); + if (err) + return err; + + err = gpiochip_add(chip); + if (err) { + ssb_gpio_irq_extif_domain_exit(bus); + return err; + } + + return 0; } #else @@ -185,6 +455,10 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) } #endif +/************************************************** + * Init + **************************************************/ + int ssb_gpio_init(struct ssb_bus *bus) { if (ssb_chipco_available(&bus->chipco)) diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 32a811d11c25..2fead3820849 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -593,6 +593,13 @@ static int ssb_attach_queued_buses(void) ssb_pcicore_init(&bus->pcicore); if (bus->bustype == SSB_BUSTYPE_SSB) ssb_watchdog_register(bus); + + err = ssb_gpio_init(bus); + if (err == -ENOTSUPP) + ssb_dbg("GPIO driver not activated\n"); + else if (err) + ssb_dbg("Error registering GPIO driver: %i\n", err); + ssb_bus_may_powerdown(bus); err = ssb_devices_register(bus); @@ -830,11 +837,6 @@ static int ssb_bus_register(struct ssb_bus *bus, ssb_chipcommon_init(&bus->chipco); ssb_extif_init(&bus->extif); ssb_mipscore_init(&bus->mipscore); - err = ssb_gpio_init(bus); - if (err == -ENOTSUPP) - ssb_dbg("GPIO driver not activated\n"); - else if (err) - ssb_dbg("Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 649d5129c4b4..78e82b017b92 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -29,10 +29,7 @@ #include <linux/sysrq.h> #include <linux/serial.h> #include <linux/serial_core.h> - -#include <bcm63xx_irq.h> -#include <bcm63xx_regs.h> -#include <bcm63xx_io.h> +#include <linux/serial_bcm63xx.h> #define BCM63XX_NR_UARTS 2 @@ -81,13 +78,13 @@ static struct uart_port ports[BCM63XX_NR_UARTS]; static inline unsigned int bcm_uart_readl(struct uart_port *port, unsigned int offset) { - return bcm_readl(port->membase + offset); + return __raw_readl(port->membase + offset); } static inline void bcm_uart_writel(struct uart_port *port, unsigned int value, unsigned int offset) { - bcm_writel(value, port->membase + offset); + __raw_writel(value, port->membase + offset); } /* diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index c49e1a159e6e..63d105cd14a3 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -640,6 +640,7 @@ struct bcma_drv_cc { spinlock_t gpio_lock; #ifdef CONFIG_BCMA_DRIVER_GPIO struct gpio_chip gpio; + struct irq_domain *irq_domain; #endif }; diff --git a/include/linux/serial_bcm63xx.h b/include/linux/serial_bcm63xx.h new file mode 100644 index 000000000000..570e964dc899 --- /dev/null +++ b/include/linux/serial_bcm63xx.h @@ -0,0 +1,119 @@ +#ifndef _LINUX_SERIAL_BCM63XX_H +#define _LINUX_SERIAL_BCM63XX_H + +/* UART Control Register */ +#define UART_CTL_REG 0x0 +#define UART_CTL_RXTMOUTCNT_SHIFT 0 +#define UART_CTL_RXTMOUTCNT_MASK (0x1f << UART_CTL_RXTMOUTCNT_SHIFT) +#define UART_CTL_RSTTXDN_SHIFT 5 +#define UART_CTL_RSTTXDN_MASK (1 << UART_CTL_RSTTXDN_SHIFT) +#define UART_CTL_RSTRXFIFO_SHIFT 6 +#define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT) +#define UART_CTL_RSTTXFIFO_SHIFT 7 +#define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT) +#define UART_CTL_STOPBITS_SHIFT 8 +#define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT) +#define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT) +#define UART_CTL_STOPBITS_2 (0xf << UART_CTL_STOPBITS_SHIFT) +#define UART_CTL_BITSPERSYM_SHIFT 12 +#define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT) +#define UART_CTL_XMITBRK_SHIFT 14 +#define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT) +#define UART_CTL_RSVD_SHIFT 15 +#define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT) +#define UART_CTL_RXPAREVEN_SHIFT 16 +#define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT) +#define UART_CTL_RXPAREN_SHIFT 17 +#define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT) +#define UART_CTL_TXPAREVEN_SHIFT 18 +#define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT) +#define UART_CTL_TXPAREN_SHIFT 18 +#define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT) +#define UART_CTL_LOOPBACK_SHIFT 20 +#define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT) +#define UART_CTL_RXEN_SHIFT 21 +#define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT) +#define UART_CTL_TXEN_SHIFT 22 +#define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT) +#define UART_CTL_BRGEN_SHIFT 23 +#define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT) + +/* UART Baudword register */ +#define UART_BAUD_REG 0x4 + +/* UART Misc Control register */ +#define UART_MCTL_REG 0x8 +#define UART_MCTL_DTR_SHIFT 0 +#define UART_MCTL_DTR_MASK (1 << UART_MCTL_DTR_SHIFT) +#define UART_MCTL_RTS_SHIFT 1 +#define UART_MCTL_RTS_MASK (1 << UART_MCTL_RTS_SHIFT) +#define UART_MCTL_RXFIFOTHRESH_SHIFT 8 +#define UART_MCTL_RXFIFOTHRESH_MASK (0xf << UART_MCTL_RXFIFOTHRESH_SHIFT) +#define UART_MCTL_TXFIFOTHRESH_SHIFT 12 +#define UART_MCTL_TXFIFOTHRESH_MASK (0xf << UART_MCTL_TXFIFOTHRESH_SHIFT) +#define UART_MCTL_RXFIFOFILL_SHIFT 16 +#define UART_MCTL_RXFIFOFILL_MASK (0x1f << UART_MCTL_RXFIFOFILL_SHIFT) +#define UART_MCTL_TXFIFOFILL_SHIFT 24 +#define UART_MCTL_TXFIFOFILL_MASK (0x1f << UART_MCTL_TXFIFOFILL_SHIFT) + +/* UART External Input Configuration register */ +#define UART_EXTINP_REG 0xc +#define UART_EXTINP_RI_SHIFT 0 +#define UART_EXTINP_RI_MASK (1 << UART_EXTINP_RI_SHIFT) +#define UART_EXTINP_CTS_SHIFT 1 +#define UART_EXTINP_CTS_MASK (1 << UART_EXTINP_CTS_SHIFT) +#define UART_EXTINP_DCD_SHIFT 2 +#define UART_EXTINP_DCD_MASK (1 << UART_EXTINP_DCD_SHIFT) +#define UART_EXTINP_DSR_SHIFT 3 +#define UART_EXTINP_DSR_MASK (1 << UART_EXTINP_DSR_SHIFT) +#define UART_EXTINP_IRSTAT(x) (1 << (x + 4)) +#define UART_EXTINP_IRMASK(x) (1 << (x + 8)) +#define UART_EXTINP_IR_RI 0 +#define UART_EXTINP_IR_CTS 1 +#define UART_EXTINP_IR_DCD 2 +#define UART_EXTINP_IR_DSR 3 +#define UART_EXTINP_RI_NOSENSE_SHIFT 16 +#define UART_EXTINP_RI_NOSENSE_MASK (1 << UART_EXTINP_RI_NOSENSE_SHIFT) +#define UART_EXTINP_CTS_NOSENSE_SHIFT 17 +#define UART_EXTINP_CTS_NOSENSE_MASK (1 << UART_EXTINP_CTS_NOSENSE_SHIFT) +#define UART_EXTINP_DCD_NOSENSE_SHIFT 18 +#define UART_EXTINP_DCD_NOSENSE_MASK (1 << UART_EXTINP_DCD_NOSENSE_SHIFT) +#define UART_EXTINP_DSR_NOSENSE_SHIFT 19 +#define UART_EXTINP_DSR_NOSENSE_MASK (1 << UART_EXTINP_DSR_NOSENSE_SHIFT) + +/* UART Interrupt register */ +#define UART_IR_REG 0x10 +#define UART_IR_MASK(x) (1 << (x + 16)) +#define UART_IR_STAT(x) (1 << (x)) +#define UART_IR_EXTIP 0 +#define UART_IR_TXUNDER 1 +#define UART_IR_TXOVER 2 +#define UART_IR_TXTRESH 3 +#define UART_IR_TXRDLATCH 4 +#define UART_IR_TXEMPTY 5 +#define UART_IR_RXUNDER 6 +#define UART_IR_RXOVER 7 +#define UART_IR_RXTIMEOUT 8 +#define UART_IR_RXFULL 9 +#define UART_IR_RXTHRESH 10 +#define UART_IR_RXNOTEMPTY 11 +#define UART_IR_RXFRAMEERR 12 +#define UART_IR_RXPARERR 13 +#define UART_IR_RXBRK 14 +#define UART_IR_TXDONE 15 + +/* UART Fifo register */ +#define UART_FIFO_REG 0x14 +#define UART_FIFO_VALID_SHIFT 0 +#define UART_FIFO_VALID_MASK 0xff +#define UART_FIFO_FRAMEERR_SHIFT 8 +#define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT) +#define UART_FIFO_PARERR_SHIFT 9 +#define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT) +#define UART_FIFO_BRKDET_SHIFT 10 +#define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT) +#define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | \ + UART_FIFO_PARERR_MASK | \ + UART_FIFO_BRKDET_MASK) + +#endif /* _LINUX_SERIAL_BCM63XX_H */ diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index c64999fd1660..07ef9b82b66d 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -486,6 +486,7 @@ struct ssb_bus { #endif /* EMBEDDED */ #ifdef CONFIG_SSB_DRIVER_GPIO struct gpio_chip gpio; + struct irq_domain *irq_domain; #endif /* DRIVER_GPIO */ /* Internal-only stuff follows. Do not touch. */ |