summaryrefslogtreecommitdiffstats
path: root/kernel/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/arch/mips')
-rw-r--r--kernel/arch/mips/Kbuild1
-rw-r--r--kernel/arch/mips/Kbuild.platforms5
-rw-r--r--kernel/arch/mips/Kconfig294
-rw-r--r--kernel/arch/mips/Kconfig.debug81
-rw-r--r--kernel/arch/mips/Makefile11
-rw-r--r--kernel/arch/mips/alchemy/Kconfig7
-rw-r--r--kernel/arch/mips/alchemy/board-gpr.c1
-rw-r--r--kernel/arch/mips/alchemy/board-mtx1.c1
-rw-r--r--kernel/arch/mips/alchemy/common/Makefile7
-rw-r--r--kernel/arch/mips/alchemy/common/clock.c82
-rw-r--r--kernel/arch/mips/alchemy/common/irq.c8
-rw-r--r--kernel/arch/mips/alchemy/common/time.c6
-rw-r--r--kernel/arch/mips/alchemy/devboards/bcsr.c8
-rw-r--r--kernel/arch/mips/alchemy/devboards/db1000.c1
-rw-r--r--kernel/arch/mips/alchemy/devboards/db1300.c1
-rw-r--r--kernel/arch/mips/alchemy/devboards/db1550.c1
-rw-r--r--kernel/arch/mips/alchemy/devboards/pm.c2
-rw-r--r--kernel/arch/mips/ar7/gpio.c5
-rw-r--r--kernel/arch/mips/ar7/platform.c6
-rw-r--r--kernel/arch/mips/ar7/setup.c1
-rw-r--r--kernel/arch/mips/ath25/ar2315.c8
-rw-r--r--kernel/arch/mips/ath25/ar5312.c8
-rw-r--r--kernel/arch/mips/ath25/board.c2
-rw-r--r--kernel/arch/mips/ath79/Kconfig12
-rw-r--r--kernel/arch/mips/ath79/Makefile2
-rw-r--r--kernel/arch/mips/ath79/clock.c86
-rw-r--r--kernel/arch/mips/ath79/common.c35
-rw-r--r--kernel/arch/mips/ath79/common.h4
-rw-r--r--kernel/arch/mips/ath79/dev-common.c51
-rw-r--r--kernel/arch/mips/ath79/gpio.c244
-rw-r--r--kernel/arch/mips/ath79/irq.c235
-rw-r--r--kernel/arch/mips/ath79/machtypes.h1
-rw-r--r--kernel/arch/mips/ath79/setup.c37
-rw-r--r--kernel/arch/mips/bcm47xx/Kconfig2
-rw-r--r--kernel/arch/mips/bcm47xx/Makefile2
-rw-r--r--kernel/arch/mips/bcm47xx/board.c1
-rw-r--r--kernel/arch/mips/bcm47xx/buttons.c14
-rw-r--r--kernel/arch/mips/bcm47xx/leds.c14
-rw-r--r--kernel/arch/mips/bcm47xx/nvram.c223
-rw-r--r--kernel/arch/mips/bcm47xx/prom.c2
-rw-r--r--kernel/arch/mips/bcm47xx/setup.c24
-rw-r--r--kernel/arch/mips/bcm47xx/sprom.c152
-rw-r--r--kernel/arch/mips/bcm63xx/boards/board_bcm963xx.c14
-rw-r--r--kernel/arch/mips/bcm63xx/cpu.c12
-rw-r--r--kernel/arch/mips/bcm63xx/dev-pcmcia.c2
-rw-r--r--kernel/arch/mips/bcm63xx/dev-spi.c42
-rw-r--r--kernel/arch/mips/bcm63xx/irq.c8
-rw-r--r--kernel/arch/mips/bcm63xx/setup.c8
-rw-r--r--kernel/arch/mips/bcm63xx/timer.c2
-rw-r--r--kernel/arch/mips/bmips/Kconfig4
-rw-r--r--kernel/arch/mips/bmips/irq.c2
-rw-r--r--kernel/arch/mips/bmips/setup.c3
-rw-r--r--kernel/arch/mips/boot/compressed/Makefile2
-rw-r--r--kernel/arch/mips/boot/compressed/head.S16
-rw-r--r--kernel/arch/mips/boot/compressed/ld.script6
-rw-r--r--kernel/arch/mips/boot/compressed/uart-16550.c2
-rw-r--r--kernel/arch/mips/boot/dts/Makefile6
-rw-r--r--kernel/arch/mips/boot/dts/brcm/Makefile14
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7346.dtsi140
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7358.dtsi88
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7360.dtsi88
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7362.dtsi120
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7425.dtsi42
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm7435.dtsi239
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts36
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm97358svmb.dts24
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm97360svmb.dts24
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm97362svmb.dts28
-rw-r--r--kernel/arch/mips/boot/dts/brcm/bcm97435svmb.dts60
-rw-r--r--kernel/arch/mips/boot/dts/ingenic/Makefile10
-rw-r--r--kernel/arch/mips/boot/dts/ingenic/ci20.dts44
-rw-r--r--kernel/arch/mips/boot/dts/ingenic/jz4740.dtsi68
-rw-r--r--kernel/arch/mips/boot/dts/ingenic/jz4780.dtsi111
-rw-r--r--kernel/arch/mips/boot/dts/ingenic/qi_lb60.dts15
-rw-r--r--kernel/arch/mips/boot/dts/mti/Makefile1
-rw-r--r--kernel/arch/mips/boot/dts/mti/malta.dts11
-rw-r--r--kernel/arch/mips/boot/dts/netlogic/xlp_evp.dts12
-rw-r--r--kernel/arch/mips/boot/dts/netlogic/xlp_fvp.dts12
-rw-r--r--kernel/arch/mips/boot/dts/netlogic/xlp_gvp.dts11
-rw-r--r--kernel/arch/mips/boot/dts/netlogic/xlp_rvp.dts11
-rw-r--r--kernel/arch/mips/boot/dts/netlogic/xlp_svp.dts12
-rw-r--r--kernel/arch/mips/boot/dts/qca/Makefile11
-rw-r--r--kernel/arch/mips/boot/dts/qca/ar9132.dtsi141
-rw-r--r--kernel/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts112
-rw-r--r--kernel/arch/mips/boot/dts/xilfpga/Makefile9
-rw-r--r--kernel/arch/mips/boot/dts/xilfpga/microAptiv.dtsi21
-rw-r--r--kernel/arch/mips/boot/dts/xilfpga/nexys4ddr.dts46
-rw-r--r--kernel/arch/mips/cavium-octeon/Makefile3
-rw-r--r--kernel/arch/mips/cavium-octeon/crypto/octeon-md5.c8
-rw-r--r--kernel/arch/mips/cavium-octeon/dma-octeon.c8
-rw-r--r--kernel/arch/mips/cavium-octeon/executive/cvmx-helper-board.c6
-rw-r--r--kernel/arch/mips/cavium-octeon/executive/cvmx-helper-util.c20
-rw-r--r--kernel/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c14
-rw-r--r--kernel/arch/mips/cavium-octeon/executive/cvmx-helper.c17
-rw-r--r--kernel/arch/mips/cavium-octeon/executive/cvmx-pko.c149
-rw-r--r--kernel/arch/mips/cavium-octeon/octeon-irq.c40
-rw-r--r--kernel/arch/mips/cavium-octeon/setup.c13
-rw-r--r--kernel/arch/mips/cavium-octeon/smp.c2
-rw-r--r--kernel/arch/mips/cobalt/mtd.c3
-rw-r--r--kernel/arch/mips/configs/bigsur_defconfig12
-rw-r--r--kernel/arch/mips/configs/bmips_be_defconfig3
-rw-r--r--kernel/arch/mips/configs/bmips_stb_defconfig3
-rw-r--r--kernel/arch/mips/configs/capcella_defconfig6
-rw-r--r--kernel/arch/mips/configs/ci20_defconfig162
-rw-r--r--kernel/arch/mips/configs/e55_defconfig6
-rw-r--r--kernel/arch/mips/configs/fuloong2e_defconfig16
-rw-r--r--kernel/arch/mips/configs/lasat_defconfig10
-rw-r--r--kernel/arch/mips/configs/lemote2f_defconfig13
-rw-r--r--kernel/arch/mips/configs/loongson3_defconfig2
-rw-r--r--kernel/arch/mips/configs/ls1b_defconfig2
-rw-r--r--kernel/arch/mips/configs/malta_defconfig6
-rw-r--r--kernel/arch/mips/configs/malta_kvm_defconfig16
-rw-r--r--kernel/arch/mips/configs/malta_kvm_guest_defconfig16
-rw-r--r--kernel/arch/mips/configs/malta_qemu_32r6_defconfig11
-rw-r--r--kernel/arch/mips/configs/maltaaprp_defconfig11
-rw-r--r--kernel/arch/mips/configs/maltasmvp_defconfig17
-rw-r--r--kernel/arch/mips/configs/maltasmvp_eva_defconfig11
-rw-r--r--kernel/arch/mips/configs/maltaup_defconfig11
-rw-r--r--kernel/arch/mips/configs/maltaup_xpa_defconfig16
-rw-r--r--kernel/arch/mips/configs/mpc30x_defconfig6
-rw-r--r--kernel/arch/mips/configs/pistachio_defconfig3
-rw-r--r--kernel/arch/mips/configs/qi_lb60_defconfig3
-rw-r--r--kernel/arch/mips/configs/xilfpga_defconfig40
-rw-r--r--kernel/arch/mips/include/asm/Kbuild4
-rw-r--r--kernel/arch/mips/include/asm/abi.h9
-rw-r--r--kernel/arch/mips/include/asm/asmmacro.h125
-rw-r--r--kernel/arch/mips/include/asm/atomic.h17
-rw-r--r--kernel/arch/mips/include/asm/barrier.h8
-rw-r--r--kernel/arch/mips/include/asm/bcache.h27
-rw-r--r--kernel/arch/mips/include/asm/bitops.h2
-rw-r--r--kernel/arch/mips/include/asm/bmips-spaces.h7
-rw-r--r--kernel/arch/mips/include/asm/cdmm.h15
-rw-r--r--kernel/arch/mips/include/asm/cevt-r4k.h1
-rw-r--r--kernel/arch/mips/include/asm/clocksource.h29
-rw-r--r--kernel/arch/mips/include/asm/cmpxchg.h2
-rw-r--r--kernel/arch/mips/include/asm/compat.h62
-rw-r--r--kernel/arch/mips/include/asm/cpu-features.h16
-rw-r--r--kernel/arch/mips/include/asm/cpu-type.h6
-rw-r--r--kernel/arch/mips/include/asm/cpu.h11
-rw-r--r--kernel/arch/mips/include/asm/debug.h50
-rw-r--r--kernel/arch/mips/include/asm/dma-mapping.h69
-rw-r--r--kernel/arch/mips/include/asm/edac.h4
-rw-r--r--kernel/arch/mips/include/asm/elf.h11
-rw-r--r--kernel/arch/mips/include/asm/fpu.h21
-rw-r--r--kernel/arch/mips/include/asm/fw/fw.h16
-rw-r--r--kernel/arch/mips/include/asm/gpio.h6
-rw-r--r--kernel/arch/mips/include/asm/hazards.h52
-rw-r--r--kernel/arch/mips/include/asm/highmem.h1
-rw-r--r--kernel/arch/mips/include/asm/hugetlb.h13
-rw-r--r--kernel/arch/mips/include/asm/i8259.h1
-rw-r--r--kernel/arch/mips/include/asm/io.h1
-rw-r--r--kernel/arch/mips/include/asm/irq.h2
-rw-r--r--kernel/arch/mips/include/asm/irqflags.h4
-rw-r--r--kernel/arch/mips/include/asm/jump_label.h19
-rw-r--r--kernel/arch/mips/include/asm/kdebug.h4
-rw-r--r--kernel/arch/mips/include/asm/kgdb.h1
-rw-r--r--kernel/arch/mips/include/asm/kvm_host.h6
-rw-r--r--kernel/arch/mips/include/asm/linkage.h1
-rw-r--r--kernel/arch/mips/include/asm/maar.h11
-rw-r--r--kernel/arch/mips/include/asm/mach-ar7/ar7.h4
-rw-r--r--kernel/arch/mips/include/asm/mach-ar7/gpio.h41
-rw-r--r--kernel/arch/mips/include/asm/mach-ath25/gpio.h16
-rw-r--r--kernel/arch/mips/include/asm/mach-ath79/ar71xx_regs.h12
-rw-r--r--kernel/arch/mips/include/asm/mach-ath79/ath79.h3
-rw-r--r--kernel/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h4
-rw-r--r--kernel/arch/mips/include/asm/mach-ath79/gpio.h26
-rw-r--r--kernel/arch/mips/include/asm/mach-au1x00/gpio-au1000.h148
-rw-r--r--kernel/arch/mips/include/asm/mach-au1x00/gpio.h86
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h9
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h2
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm47xx/gpio.h17
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h44
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm63xx/gpio.h15
-rw-r--r--kernel/arch/mips/include/asm/mach-bcm63xx/spaces.h2
-rw-r--r--kernel/arch/mips/include/asm/mach-bmips/spaces.h2
-rw-r--r--kernel/arch/mips/include/asm/mach-cavium-octeon/gpio.h21
-rw-r--r--kernel/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h16
-rw-r--r--kernel/arch/mips/include/asm/mach-generic/gpio.h21
-rw-r--r--kernel/arch/mips/include/asm/mach-generic/irq.h4
-rw-r--r--kernel/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h92
-rw-r--r--kernel/arch/mips/include/asm/mach-jz4740/clock.h3
-rw-r--r--kernel/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h3
-rw-r--r--kernel/arch/mips/include/asm/mach-jz4740/gpio.h2
-rw-r--r--kernel/arch/mips/include/asm/mach-jz4740/irq.h14
-rw-r--r--kernel/arch/mips/include/asm/mach-jz4740/platform.h2
-rw-r--r--kernel/arch/mips/include/asm/mach-lantiq/gpio.h13
-rw-r--r--kernel/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h14
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson/gpio.h36
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson/workarounds.h7
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/cpufreq.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/cpufreq.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/irq.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/irq.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/loongson1.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/loongson1.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/platform.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/platform.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/prom.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/prom.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/regs-clk.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/regs-clk.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/regs-mux.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/regs-mux.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/regs-pwm.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/regs-pwm.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson32/regs-wdt.h (renamed from kernel/arch/mips/include/asm/mach-loongson1/regs-wdt.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/boot_param.h (renamed from kernel/arch/mips/include/asm/mach-loongson/boot_param.h)4
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h (renamed from kernel/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536.h (renamed from kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_mfgpt.h (renamed from kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_pci.h (renamed from kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_vsm.h (renamed from kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/dma-coherence.h (renamed from kernel/arch/mips/include/asm/mach-loongson/dma-coherence.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/irq.h (renamed from kernel/arch/mips/include/asm/mach-loongson/irq.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h (renamed from kernel/arch/mips/include/asm/mach-loongson/kernel-entry-init.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/loongson.h (renamed from kernel/arch/mips/include/asm/mach-loongson/loongson.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h (renamed from kernel/arch/mips/include/asm/mach-loongson/loongson_hwmon.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/machine.h (renamed from kernel/arch/mips/include/asm/mach-loongson/machine.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/mc146818rtc.h (renamed from kernel/arch/mips/include/asm/mach-loongson/mc146818rtc.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/mem.h (renamed from kernel/arch/mips/include/asm/mach-loongson/mem.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/mmzone.h (renamed from kernel/arch/mips/include/asm/mach-loongson/mmzone.h)2
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/pci.h (renamed from kernel/arch/mips/include/asm/mach-loongson/pci.h)6
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/spaces.h (renamed from kernel/arch/mips/include/asm/mach-loongson/spaces.h)4
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/topology.h (renamed from kernel/arch/mips/include/asm/mach-loongson/topology.h)0
-rw-r--r--kernel/arch/mips/include/asm/mach-loongson64/workarounds.h7
-rw-r--r--kernel/arch/mips/include/asm/mach-malta/malta-dtshim.h29
-rw-r--r--kernel/arch/mips/include/asm/mach-pistachio/gpio.h21
-rw-r--r--kernel/arch/mips/include/asm/mach-ralink/mt7620.h8
-rw-r--r--kernel/arch/mips/include/asm/mach-ralink/ralink_regs.h17
-rw-r--r--kernel/arch/mips/include/asm/mach-ralink/rt305x.h21
-rw-r--r--kernel/arch/mips/include/asm/mach-rc32434/gpio.h12
-rw-r--r--kernel/arch/mips/include/asm/mach-sibyte/war.h3
-rw-r--r--kernel/arch/mips/include/asm/mach-xilfpga/irq.h18
-rw-r--r--kernel/arch/mips/include/asm/mips-cm.h197
-rw-r--r--kernel/arch/mips/include/asm/mips-cpc.h13
-rw-r--r--kernel/arch/mips/include/asm/mipsregs.h53
-rw-r--r--kernel/arch/mips/include/asm/msa.h80
-rw-r--r--kernel/arch/mips/include/asm/netlogic/common.h4
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-bootinfo.h2
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-pip.h2
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-pko.h3
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-pow-defs.h29
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-pow.h9
-rw-r--r--kernel/arch/mips/include/asm/octeon/cvmx-wqe.h308
-rw-r--r--kernel/arch/mips/include/asm/page.h3
-rw-r--r--kernel/arch/mips/include/asm/pci.h12
-rw-r--r--kernel/arch/mips/include/asm/pgtable-32.h2
-rw-r--r--kernel/arch/mips/include/asm/pgtable-bits.h25
-rw-r--r--kernel/arch/mips/include/asm/pgtable.h14
-rw-r--r--kernel/arch/mips/include/asm/processor.h10
-rw-r--r--kernel/arch/mips/include/asm/prom.h2
-rw-r--r--kernel/arch/mips/include/asm/ptrace.h80
-rw-r--r--kernel/arch/mips/include/asm/signal.h3
-rw-r--r--kernel/arch/mips/include/asm/smp.h2
-rw-r--r--kernel/arch/mips/include/asm/spinlock.h9
-rw-r--r--kernel/arch/mips/include/asm/switch_to.h67
-rw-r--r--kernel/arch/mips/include/asm/syscall.h4
-rw-r--r--kernel/arch/mips/include/asm/thread_info.h5
-rw-r--r--kernel/arch/mips/include/asm/time.h2
-rw-r--r--kernel/arch/mips/include/asm/tlbdebug.h1
-rw-r--r--kernel/arch/mips/include/asm/topology.h2
-rw-r--r--kernel/arch/mips/include/asm/txx9irq.h2
-rw-r--r--kernel/arch/mips/include/asm/uaccess.h99
-rw-r--r--kernel/arch/mips/include/asm/uprobes.h58
-rw-r--r--kernel/arch/mips/include/asm/vdso.h139
-rw-r--r--kernel/arch/mips/include/asm/vpe.h2
-rw-r--r--kernel/arch/mips/include/asm/xtalk/xwidget.h112
-rw-r--r--kernel/arch/mips/include/uapi/asm/Kbuild2
-rw-r--r--kernel/arch/mips/include/uapi/asm/auxvec.h17
-rw-r--r--kernel/arch/mips/include/uapi/asm/break.h2
-rw-r--r--kernel/arch/mips/include/uapi/asm/hwcap.h8
-rw-r--r--kernel/arch/mips/include/uapi/asm/inst.h40
-rw-r--r--kernel/arch/mips/include/uapi/asm/mman.h6
-rw-r--r--kernel/arch/mips/include/uapi/asm/sigcontext.h16
-rw-r--r--kernel/arch/mips/include/uapi/asm/swab.h7
-rw-r--r--kernel/arch/mips/include/uapi/asm/ucontext.h65
-rw-r--r--kernel/arch/mips/include/uapi/asm/unistd.h21
-rw-r--r--kernel/arch/mips/jazz/irq.c7
-rw-r--r--kernel/arch/mips/jz4740/Kconfig17
-rw-r--r--kernel/arch/mips/jz4740/Makefile8
-rw-r--r--kernel/arch/mips/jz4740/Platform8
-rw-r--r--kernel/arch/mips/jz4740/board-qi_lb60.c21
-rw-r--r--kernel/arch/mips/jz4740/clock-debugfs.c108
-rw-r--r--kernel/arch/mips/jz4740/clock.c924
-rw-r--r--kernel/arch/mips/jz4740/clock.h76
-rw-r--r--kernel/arch/mips/jz4740/gpio.c34
-rw-r--r--kernel/arch/mips/jz4740/irq.c162
-rw-r--r--kernel/arch/mips/jz4740/irq.h23
-rw-r--r--kernel/arch/mips/jz4740/platform.c38
-rw-r--r--kernel/arch/mips/jz4740/pm.c2
-rw-r--r--kernel/arch/mips/jz4740/prom.c13
-rw-r--r--kernel/arch/mips/jz4740/reset.c13
-rw-r--r--kernel/arch/mips/jz4740/serial.c33
-rw-r--r--kernel/arch/mips/jz4740/serial.h23
-rw-r--r--kernel/arch/mips/jz4740/setup.c36
-rw-r--r--kernel/arch/mips/jz4740/time.c65
-rw-r--r--kernel/arch/mips/kernel/Makefile5
-rw-r--r--kernel/arch/mips/kernel/asm-offsets.c14
-rw-r--r--kernel/arch/mips/kernel/branch.c4
-rw-r--r--kernel/arch/mips/kernel/cevt-bcm1480.c44
-rw-r--r--kernel/arch/mips/kernel/cevt-ds1287.c37
-rw-r--r--kernel/arch/mips/kernel/cevt-gt641xx.c57
-rw-r--r--kernel/arch/mips/kernel/cevt-r4k.c18
-rw-r--r--kernel/arch/mips/kernel/cevt-sb1250.c45
-rw-r--r--kernel/arch/mips/kernel/cevt-txx9.c81
-rw-r--r--kernel/arch/mips/kernel/cps-vec-ns16550.S202
-rw-r--r--kernel/arch/mips/kernel/cps-vec.S146
-rw-r--r--kernel/arch/mips/kernel/cpu-probe.c82
-rw-r--r--kernel/arch/mips/kernel/csrc-r4k.c44
-rw-r--r--kernel/arch/mips/kernel/genex.S2
-rw-r--r--kernel/arch/mips/kernel/head.S16
-rw-r--r--kernel/arch/mips/kernel/i8259.c345
-rw-r--r--kernel/arch/mips/kernel/idle.c16
-rw-r--r--kernel/arch/mips/kernel/irq.c52
-rw-r--r--kernel/arch/mips/kernel/irq_cpu.c169
-rw-r--r--kernel/arch/mips/kernel/jump_label.c2
-rw-r--r--kernel/arch/mips/kernel/kgdb.c4
-rw-r--r--kernel/arch/mips/kernel/mips-cm.c309
-rw-r--r--kernel/arch/mips/kernel/mips-cpc.c17
-rw-r--r--kernel/arch/mips/kernel/mips-r2-to-r6-emul.c2
-rw-r--r--kernel/arch/mips/kernel/mips_ksyms.c2
-rw-r--r--kernel/arch/mips/kernel/octeon_switch.S26
-rw-r--r--kernel/arch/mips/kernel/perf_event_mipsxx.c6
-rw-r--r--kernel/arch/mips/kernel/pm-cps.c2
-rw-r--r--kernel/arch/mips/kernel/prom.c3
-rw-r--r--kernel/arch/mips/kernel/ptrace.c88
-rw-r--r--kernel/arch/mips/kernel/r2300_switch.S28
-rw-r--r--kernel/arch/mips/kernel/r4k_fpu.S436
-rw-r--r--kernel/arch/mips/kernel/r4k_switch.S41
-rw-r--r--kernel/arch/mips/kernel/scall32-o32.S79
-rw-r--r--kernel/arch/mips/kernel/scall64-64.S41
-rw-r--r--kernel/arch/mips/kernel/scall64-n32.S22
-rw-r--r--kernel/arch/mips/kernel/scall64-o32.S57
-rw-r--r--kernel/arch/mips/kernel/segment.c2
-rw-r--r--kernel/arch/mips/kernel/setup.c36
-rw-r--r--kernel/arch/mips/kernel/signal-common.h9
-rw-r--r--kernel/arch/mips/kernel/signal.c445
-rw-r--r--kernel/arch/mips/kernel/signal32.c212
-rw-r--r--kernel/arch/mips/kernel/signal_n32.c11
-rw-r--r--kernel/arch/mips/kernel/smp-bmips.c4
-rw-r--r--kernel/arch/mips/kernel/smp-cps.c39
-rw-r--r--kernel/arch/mips/kernel/smp-gic.c2
-rw-r--r--kernel/arch/mips/kernel/smp.c13
-rw-r--r--kernel/arch/mips/kernel/spinlock_test.c4
-rw-r--r--kernel/arch/mips/kernel/spram.c1
-rw-r--r--kernel/arch/mips/kernel/stacktrace.c27
-rw-r--r--kernel/arch/mips/kernel/sysrq.c65
-rw-r--r--kernel/arch/mips/kernel/traps.c101
-rw-r--r--kernel/arch/mips/kernel/unaligned.c76
-rw-r--r--kernel/arch/mips/kernel/uprobes.c341
-rw-r--r--kernel/arch/mips/kernel/vdso.c207
-rw-r--r--kernel/arch/mips/kernel/vmlinux.lds.S23
-rw-r--r--kernel/arch/mips/kernel/vpe.c7
-rw-r--r--kernel/arch/mips/kvm/emulate.c2
-rw-r--r--kernel/arch/mips/kvm/locore.S24
-rw-r--r--kernel/arch/mips/kvm/mips.c31
-rw-r--r--kernel/arch/mips/lantiq/clk.c17
-rw-r--r--kernel/arch/mips/lantiq/clk.h13
-rw-r--r--kernel/arch/mips/lantiq/irq.c10
-rw-r--r--kernel/arch/mips/lantiq/prom.c2
-rw-r--r--kernel/arch/mips/lantiq/xway/clk.c180
-rw-r--r--kernel/arch/mips/lantiq/xway/prom.c35
-rw-r--r--kernel/arch/mips/lantiq/xway/reset.c196
-rw-r--r--kernel/arch/mips/lantiq/xway/sysctrl.c301
-rw-r--r--kernel/arch/mips/lasat/sysctl.c2
-rw-r--r--kernel/arch/mips/lib/Makefile2
-rw-r--r--kernel/arch/mips/lib/bswapdi.c15
-rw-r--r--kernel/arch/mips/lib/bswapsi.c11
-rw-r--r--kernel/arch/mips/lib/dump_tlb.c137
-rw-r--r--kernel/arch/mips/lib/memset.S2
-rw-r--r--kernel/arch/mips/lib/r3k_dump_tlb.c24
-rw-r--r--kernel/arch/mips/loongson32/Kconfig (renamed from kernel/arch/mips/loongson1/Kconfig)6
-rw-r--r--kernel/arch/mips/loongson32/Makefile (renamed from kernel/arch/mips/loongson1/Makefile)2
-rw-r--r--kernel/arch/mips/loongson32/Platform (renamed from kernel/arch/mips/loongson1/Platform)4
-rw-r--r--kernel/arch/mips/loongson32/common/Makefile (renamed from kernel/arch/mips/loongson1/common/Makefile)0
-rw-r--r--kernel/arch/mips/loongson32/common/irq.c (renamed from kernel/arch/mips/loongson1/common/irq.c)0
-rw-r--r--kernel/arch/mips/loongson32/common/platform.c (renamed from kernel/arch/mips/loongson1/common/platform.c)0
-rw-r--r--kernel/arch/mips/loongson32/common/prom.c (renamed from kernel/arch/mips/loongson1/common/prom.c)0
-rw-r--r--kernel/arch/mips/loongson32/common/reset.c (renamed from kernel/arch/mips/loongson1/common/reset.c)0
-rw-r--r--kernel/arch/mips/loongson32/common/setup.c (renamed from kernel/arch/mips/loongson1/common/setup.c)0
-rw-r--r--kernel/arch/mips/loongson32/common/time.c (renamed from kernel/arch/mips/loongson1/common/time.c)57
-rw-r--r--kernel/arch/mips/loongson32/ls1b/Makefile (renamed from kernel/arch/mips/loongson1/ls1b/Makefile)0
-rw-r--r--kernel/arch/mips/loongson32/ls1b/board.c (renamed from kernel/arch/mips/loongson1/ls1b/board.c)0
-rw-r--r--kernel/arch/mips/loongson64/Kconfig (renamed from kernel/arch/mips/loongson/Kconfig)15
-rw-r--r--kernel/arch/mips/loongson64/Makefile (renamed from kernel/arch/mips/loongson/Makefile)2
-rw-r--r--kernel/arch/mips/loongson64/Platform (renamed from kernel/arch/mips/loongson/Platform)4
-rw-r--r--kernel/arch/mips/loongson64/common/Makefile (renamed from kernel/arch/mips/loongson/common/Makefile)2
-rw-r--r--kernel/arch/mips/loongson64/common/bonito-irq.c (renamed from kernel/arch/mips/loongson/common/bonito-irq.c)2
-rw-r--r--kernel/arch/mips/loongson64/common/cmdline.c (renamed from kernel/arch/mips/loongson/common/cmdline.c)2
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/Makefile (renamed from kernel/arch/mips/loongson/common/cs5536/Makefile)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_acc.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_acc.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_ehci.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_ehci.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_ide.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_ide.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_isa.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_isa.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c)48
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_ohci.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_ohci.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/cs5536/cs5536_pci.c (renamed from kernel/arch/mips/loongson/common/cs5536/cs5536_pci.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/dma-swiotlb.c (renamed from kernel/arch/mips/loongson/common/dma-swiotlb.c)11
-rw-r--r--kernel/arch/mips/loongson64/common/early_printk.c (renamed from kernel/arch/mips/loongson/common/early_printk.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/env.c (renamed from kernel/arch/mips/loongson/common/env.c)5
-rw-r--r--kernel/arch/mips/loongson64/common/init.c (renamed from kernel/arch/mips/loongson/common/init.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/irq.c (renamed from kernel/arch/mips/loongson/common/irq.c)2
-rw-r--r--kernel/arch/mips/loongson64/common/machtype.c (renamed from kernel/arch/mips/loongson/common/machtype.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/mem.c (renamed from kernel/arch/mips/loongson/common/mem.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/pci.c (renamed from kernel/arch/mips/loongson/common/pci.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/platform.c (renamed from kernel/arch/mips/loongson/common/platform.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/pm.c (renamed from kernel/arch/mips/loongson/common/pm.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/reset.c (renamed from kernel/arch/mips/loongson/common/reset.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/rtc.c (renamed from kernel/arch/mips/loongson/common/rtc.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/serial.c (renamed from kernel/arch/mips/loongson/common/serial.c)9
-rw-r--r--kernel/arch/mips/loongson64/common/setup.c (renamed from kernel/arch/mips/loongson/common/setup.c)2
-rw-r--r--kernel/arch/mips/loongson64/common/time.c (renamed from kernel/arch/mips/loongson/common/time.c)0
-rw-r--r--kernel/arch/mips/loongson64/common/uart_base.c (renamed from kernel/arch/mips/loongson/common/uart_base.c)0
-rw-r--r--kernel/arch/mips/loongson64/fuloong-2e/Makefile (renamed from kernel/arch/mips/loongson/fuloong-2e/Makefile)0
-rw-r--r--kernel/arch/mips/loongson64/fuloong-2e/irq.c (renamed from kernel/arch/mips/loongson/fuloong-2e/irq.c)2
-rw-r--r--kernel/arch/mips/loongson64/fuloong-2e/reset.c (renamed from kernel/arch/mips/loongson/fuloong-2e/reset.c)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/Makefile (renamed from kernel/arch/mips/loongson/lemote-2f/Makefile)2
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/clock.c (renamed from kernel/arch/mips/loongson/lemote-2f/clock.c)4
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.c (renamed from kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.c)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.h (renamed from kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.h)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/irq.c (renamed from kernel/arch/mips/loongson/lemote-2f/irq.c)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/machtype.c (renamed from kernel/arch/mips/loongson/lemote-2f/machtype.c)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/pm.c (renamed from kernel/arch/mips/loongson/lemote-2f/pm.c)0
-rw-r--r--kernel/arch/mips/loongson64/lemote-2f/reset.c (renamed from kernel/arch/mips/loongson/lemote-2f/reset.c)0
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/Makefile (renamed from kernel/arch/mips/loongson/loongson-3/Makefile)0
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/cop2-ex.c (renamed from kernel/arch/mips/loongson/loongson-3/cop2-ex.c)0
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/hpet.c (renamed from kernel/arch/mips/loongson/loongson-3/hpet.c)127
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/irq.c (renamed from kernel/arch/mips/loongson/loongson-3/irq.c)0
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/numa.c (renamed from kernel/arch/mips/loongson/loongson-3/numa.c)2
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/platform.c (renamed from kernel/arch/mips/loongson/loongson-3/platform.c)0
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/smp.c (renamed from kernel/arch/mips/loongson/loongson-3/smp.c)27
-rw-r--r--kernel/arch/mips/loongson64/loongson-3/smp.h (renamed from kernel/arch/mips/loongson/loongson-3/smp.h)0
-rw-r--r--kernel/arch/mips/math-emu/Makefile4
-rw-r--r--kernel/arch/mips/math-emu/cp1emu.c380
-rw-r--r--kernel/arch/mips/math-emu/dp_2008class.c55
-rw-r--r--kernel/arch/mips/math-emu/dp_fmax.c213
-rw-r--r--kernel/arch/mips/math-emu/dp_fmin.c213
-rw-r--r--kernel/arch/mips/math-emu/dp_maddf.c265
-rw-r--r--kernel/arch/mips/math-emu/dp_msubf.c269
-rw-r--r--kernel/arch/mips/math-emu/dsemul.c1
-rw-r--r--kernel/arch/mips/math-emu/ieee754.h19
-rw-r--r--kernel/arch/mips/math-emu/ieee754int.h8
-rw-r--r--kernel/arch/mips/math-emu/me-debugfs.c4
-rw-r--r--kernel/arch/mips/math-emu/sp_2008class.c55
-rw-r--r--kernel/arch/mips/math-emu/sp_fmax.c213
-rw-r--r--kernel/arch/mips/math-emu/sp_fmin.c213
-rw-r--r--kernel/arch/mips/math-emu/sp_maddf.c255
-rw-r--r--kernel/arch/mips/math-emu/sp_msubf.c258
-rw-r--r--kernel/arch/mips/mm/Makefile1
-rw-r--r--kernel/arch/mips/mm/c-r4k.c7
-rw-r--r--kernel/arch/mips/mm/c-tx39.c4
-rw-r--r--kernel/arch/mips/mm/cache.c8
-rw-r--r--kernel/arch/mips/mm/dma-default.c90
-rw-r--r--kernel/arch/mips/mm/fault.c11
-rw-r--r--kernel/arch/mips/mm/highmem.c13
-rw-r--r--kernel/arch/mips/mm/hugetlbpage.c5
-rw-r--r--kernel/arch/mips/mm/init.c147
-rw-r--r--kernel/arch/mips/mm/sc-debugfs.c81
-rw-r--r--kernel/arch/mips/mm/sc-mips.c112
-rw-r--r--kernel/arch/mips/mm/tlb-r3k.c37
-rw-r--r--kernel/arch/mips/mm/tlb-r4k.c2
-rw-r--r--kernel/arch/mips/mm/tlbex.c132
-rw-r--r--kernel/arch/mips/mti-malta/Makefile15
-rw-r--r--kernel/arch/mips/mti-malta/malta-dt.c34
-rw-r--r--kernel/arch/mips/mti-malta/malta-dtshim.c162
-rw-r--r--kernel/arch/mips/mti-malta/malta-init.c8
-rw-r--r--kernel/arch/mips/mti-malta/malta-int.c114
-rw-r--r--kernel/arch/mips/mti-malta/malta-memory.c156
-rw-r--r--kernel/arch/mips/mti-malta/malta-setup.c7
-rw-r--r--kernel/arch/mips/mti-malta/malta-time.c20
-rw-r--r--kernel/arch/mips/mti-sead3/Makefile4
-rw-r--r--kernel/arch/mips/mti-sead3/leds-sead3.c77
-rw-r--r--kernel/arch/mips/net/Makefile2
-rw-r--r--kernel/arch/mips/net/bpf_jit.c280
-rw-r--r--kernel/arch/mips/net/bpf_jit.h42
-rw-r--r--kernel/arch/mips/net/bpf_jit_asm.S283
-rw-r--r--kernel/arch/mips/netlogic/common/irq.c12
-rw-r--r--kernel/arch/mips/netlogic/common/nlm-dma.c10
-rw-r--r--kernel/arch/mips/netlogic/common/smp.c8
-rw-r--r--kernel/arch/mips/netlogic/xlp/ahci-init-xlp2.c2
-rw-r--r--kernel/arch/mips/netlogic/xlp/dt.c1
-rw-r--r--kernel/arch/mips/netlogic/xlp/nlm_hal.c2
-rw-r--r--kernel/arch/mips/netlogic/xlr/platform-flash.c3
-rw-r--r--kernel/arch/mips/oprofile/common.c1
-rw-r--r--kernel/arch/mips/oprofile/op_model_mipsxx.c4
-rw-r--r--kernel/arch/mips/paravirt/paravirt-smp.c2
-rw-r--r--kernel/arch/mips/pci/fixup-cobalt.c1
-rw-r--r--kernel/arch/mips/pci/msi-octeon.c2
-rw-r--r--kernel/arch/mips/pci/msi-xlp.c20
-rw-r--r--kernel/arch/mips/pci/ops-emma2rh.c6
-rw-r--r--kernel/arch/mips/pci/ops-mace.c1
-rw-r--r--kernel/arch/mips/pci/pci-ar2315.c8
-rw-r--r--kernel/arch/mips/pci/pci-ar71xx.c20
-rw-r--r--kernel/arch/mips/pci/pci-ar724x.c8
-rw-r--r--kernel/arch/mips/pci/pci-lantiq.c2
-rw-r--r--kernel/arch/mips/pci/pci-rt2880.c5
-rw-r--r--kernel/arch/mips/pci/pci-rt3883.c15
-rw-r--r--kernel/arch/mips/pistachio/Kconfig13
-rw-r--r--kernel/arch/mips/pistachio/init.c9
-rw-r--r--kernel/arch/mips/pistachio/time.c7
-rw-r--r--kernel/arch/mips/pmcs-msp71xx/msp_irq_cic.c3
-rw-r--r--kernel/arch/mips/pmcs-msp71xx/msp_setup.c5
-rw-r--r--kernel/arch/mips/pmcs-msp71xx/msp_smp.c2
-rw-r--r--kernel/arch/mips/ralink/cevt-rt3352.c61
-rw-r--r--kernel/arch/mips/ralink/clk.c2
-rw-r--r--kernel/arch/mips/ralink/early_printk.c26
-rw-r--r--kernel/arch/mips/ralink/irq.c7
-rw-r--r--kernel/arch/mips/ralink/mt7620.c63
-rw-r--r--kernel/arch/mips/ralink/of.c2
-rw-r--r--kernel/arch/mips/ralink/prom.c5
-rw-r--r--kernel/arch/mips/ralink/reset.c13
-rw-r--r--kernel/arch/mips/ralink/rt288x.c1
-rw-r--r--kernel/arch/mips/ralink/rt305x.c13
-rw-r--r--kernel/arch/mips/ralink/rt3883.c2
-rw-r--r--kernel/arch/mips/rb532/devices.c1
-rw-r--r--kernel/arch/mips/rb532/gpio.c6
-rw-r--r--kernel/arch/mips/sgi-ip27/Makefile6
-rw-r--r--kernel/arch/mips/sgi-ip27/ip27-irq.c8
-rw-r--r--kernel/arch/mips/sgi-ip27/ip27-irqno.c48
-rw-r--r--kernel/arch/mips/sgi-ip27/ip27-timer.c7
-rw-r--r--kernel/arch/mips/sibyte/Kconfig21
-rw-r--r--kernel/arch/mips/sibyte/bcm1480/smp.c9
-rw-r--r--kernel/arch/mips/sibyte/common/bus_watcher.c7
-rw-r--r--kernel/arch/mips/sibyte/sb1250/setup.c2
-rw-r--r--kernel/arch/mips/sibyte/sb1250/smp.c7
-rw-r--r--kernel/arch/mips/sni/reset.c8
-rw-r--r--kernel/arch/mips/sni/time.c49
-rw-r--r--kernel/arch/mips/txx9/Kconfig2
-rw-r--r--kernel/arch/mips/txx9/generic/setup.c16
-rw-r--r--kernel/arch/mips/txx9/generic/spi_eeprom.c1
-rw-r--r--kernel/arch/mips/vdso/.gitignore4
-rw-r--r--kernel/arch/mips/vdso/Makefile160
-rw-r--r--kernel/arch/mips/vdso/elf.S68
-rw-r--r--kernel/arch/mips/vdso/genvdso.c293
-rw-r--r--kernel/arch/mips/vdso/genvdso.h187
-rw-r--r--kernel/arch/mips/vdso/gettimeofday.c232
-rw-r--r--kernel/arch/mips/vdso/sigreturn.S49
-rw-r--r--kernel/arch/mips/vdso/vdso.h89
-rw-r--r--kernel/arch/mips/vdso/vdso.lds.S105
-rw-r--r--kernel/arch/mips/vr41xx/Kconfig10
-rw-r--r--kernel/arch/mips/xilfpga/Kconfig9
-rw-r--r--kernel/arch/mips/xilfpga/Makefile7
-rw-r--r--kernel/arch/mips/xilfpga/Platform3
-rw-r--r--kernel/arch/mips/xilfpga/init.c57
-rw-r--r--kernel/arch/mips/xilfpga/intc.c25
-rw-r--r--kernel/arch/mips/xilfpga/time.c41
538 files changed, 13816 insertions, 6657 deletions
diff --git a/kernel/arch/mips/Kbuild b/kernel/arch/mips/Kbuild
index dd2953358..5c3f688a5 100644
--- a/kernel/arch/mips/Kbuild
+++ b/kernel/arch/mips/Kbuild
@@ -17,6 +17,7 @@ obj- := $(platform-)
obj-y += kernel/
obj-y += mm/
obj-y += net/
+obj-y += vdso/
ifdef CONFIG_KVM
obj-y += kvm/
diff --git a/kernel/arch/mips/Kbuild.platforms b/kernel/arch/mips/Kbuild.platforms
index 39cf40da5..a96c81d1d 100644
--- a/kernel/arch/mips/Kbuild.platforms
+++ b/kernel/arch/mips/Kbuild.platforms
@@ -15,8 +15,8 @@ platforms += jazz
platforms += jz4740
platforms += lantiq
platforms += lasat
-platforms += loongson
-platforms += loongson1
+platforms += loongson32
+platforms += loongson64
platforms += mti-malta
platforms += mti-sead3
platforms += netlogic
@@ -33,6 +33,7 @@ platforms += sibyte
platforms += sni
platforms += txx9
platforms += vr41xx
+platforms += xilfpga
# include the platform specific files
include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
diff --git a/kernel/arch/mips/Kconfig b/kernel/arch/mips/Kconfig
index 9b95c9b7e..bd8be6a0e 100644
--- a/kernel/arch/mips/Kconfig
+++ b/kernel/arch/mips/Kconfig
@@ -1,8 +1,11 @@
config MIPS
bool
default y
+ select ARCH_SUPPORTS_UPROBES
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
+ select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
+ select ARCH_USE_BUILTIN_BSWAP
select HAVE_CONTEXT_TRACKING
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IDE
@@ -13,7 +16,6 @@ config MIPS
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_BPF_JIT if !CPU_MICROMIPS
- select ARCH_HAVE_CUSTOM_GPIO_H
select HAVE_FUNCTION_TRACER
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
@@ -21,11 +23,12 @@ config MIPS
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_KPROBES
select HAVE_KRETPROBES
+ select HAVE_SYSCALL_TRACEPOINTS
select HAVE_DEBUG_KMEMLEAK
select HAVE_SYSCALL_TRACEPOINTS
select ARCH_HAS_ELF_RANDOMIZE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
- select RTC_LIB if !MACH_LOONGSON
+ select RTC_LIB if !MACH_LOONGSON64
select GENERIC_ATOMIC64 if !64BIT
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_DMA_ATTRS
@@ -58,6 +61,8 @@ config MIPS
select SYSCTL_EXCEPTION_TRACE
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select HAVE_IRQ_TIME_ACCOUNTING
+ select GENERIC_TIME_VSYSCALL
+ select ARCH_CLOCKSOURCE_DATA
menu "Machine selection"
@@ -70,7 +75,7 @@ config MIPS_ALCHEMY
select ARCH_PHYS_ADDR_T_64BIT
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select DMA_MAYBE_COHERENT # Au1000,1500,1100 aren't, rest is
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
@@ -85,7 +90,7 @@ config AR7
select DMA_NONCOHERENT
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select NO_EXCEPT_FILL
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
@@ -106,7 +111,7 @@ config ATH25
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select IRQ_DOMAIN
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_BIG_ENDIAN
@@ -117,20 +122,24 @@ config ATH25
config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
+ select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select HAVE_CLK
+ select COMMON_CLK
select CLKDEV_LOOKUP
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select MIPS_MACHINE
select SYS_HAS_CPU_MIPS32_R2
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_MIPS16
+ select SYS_SUPPORTS_ZBOOT
+ select USE_OF
help
Support for the Atheros AR71XX/AR724X/AR913X SoCs.
@@ -146,8 +155,7 @@ config BMIPS_GENERIC
select BCM7038_L1_IRQ
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
- select IRQ_CPU
- select RAW_IRQ_ACCESSORS
+ select IRQ_MIPS_CPU
select DMA_NONCOHERENT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -176,7 +184,7 @@ config BCM47XX
select CSRC_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_HAS_CPU_MIPS32_R1
select NO_EXCEPT_FILL
select SYS_SUPPORTS_32BIT_KERNEL
@@ -186,6 +194,7 @@ config BCM47XX
select USE_GENERIC_EARLY_PRINTK_8250
select GPIOLIB
select LEDS_GPIO_REGISTER
+ select BCM47XX_NVRAM
help
Support for BCM47XX based boards
@@ -196,7 +205,7 @@ config BCM63XX
select CSRC_R4K
select SYNC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
@@ -216,7 +225,7 @@ config MIPS_COBALT
select HW_HAS_PCI
select I8253
select I8259
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select IRQ_GT641XX
select PCI_GT64XXX_PCI0
select PCI
@@ -239,7 +248,7 @@ config MACH_DECSTATION
select CPU_R4400_WORKAROUNDS if 64BIT
select DMA_NONCOHERENT
select NO_IOPORT_MAP
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_HAS_CPU_R3000
select SYS_HAS_CPU_R4X00
select SYS_SUPPORTS_32BIT_KERNEL
@@ -274,7 +283,7 @@ config MACH_JAZZ
select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
select GENERIC_ISA_DMA
select HAVE_PCSPKR_PLATFORM
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select I8253
select I8259
select ISA
@@ -288,23 +297,24 @@ config MACH_JAZZ
Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
Olivetti M700-10 workstations.
-config MACH_JZ4740
- bool "Ingenic JZ4740 based machines"
- select SYS_HAS_CPU_MIPS32_R1
+config MACH_INGENIC
+ bool "Ingenic SoC based machines"
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_ZBOOT_UART16550
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ARCH_REQUIRE_GPIOLIB
- select SYS_HAS_EARLY_PRINTK
- select HAVE_CLK
+ select COMMON_CLK
select GENERIC_IRQ_CHIP
+ select BUILTIN_DTB
+ select USE_OF
+ select LIBFDT
config LANTIQ
bool "Lantiq based platforms"
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select CEVT_R4K
select CSRC_R4K
select SYS_HAS_CPU_MIPS32_R1
@@ -333,7 +343,7 @@ config LASAT
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select PCI_GT64XXX_PCI0
select MIPS_NILE4
select R5000_CPU_SCACHE
@@ -342,26 +352,28 @@ config LASAT
select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
select SYS_SUPPORTS_LITTLE_ENDIAN
-config MACH_LOONGSON
- bool "Loongson family of machines"
+config MACH_LOONGSON32
+ bool "Loongson-1 family of machines"
select SYS_SUPPORTS_ZBOOT
help
- This enables the support of Loongson family of machines.
+ This enables support for the Loongson-1 family of machines.
- Loongson is a family of general-purpose MIPS-compatible CPUs.
- developed at Institute of Computing Technology (ICT),
- Chinese Academy of Sciences (CAS) in the People's Republic
- of China. The chief architect is Professor Weiwu Hu.
+ Loongson-1 is a family of 32-bit MIPS-compatible SoCs developed by
+ the Institute of Computing Technology (ICT), Chinese Academy of
+ Sciences (CAS).
-config MACH_LOONGSON1
- bool "Loongson 1 family of machines"
+config MACH_LOONGSON64
+ bool "Loongson-2/3 family of machines"
select SYS_SUPPORTS_ZBOOT
help
- This enables support for the Loongson 1 based machines.
+ This enables the support of Loongson-2/3 family of machines.
- Loongson 1 is a family of 32-bit MIPS-compatible SoCs developed by
- the ICT (Institute of Computing Technology) and the Chinese Academy
- of Sciences.
+ Loongson-2 is a family of single-core CPUs and Loongson-3 is a
+ family of multi-core CPUs. They are both 64-bit general-purpose
+ MIPS-compatible CPUs. Loongson-2/3 are developed by the Institute
+ of Computing Technology (ICT), Chinese Academy of Sciences (CAS)
+ in the People's Republic of China. The chief architect is Professor
+ Weiwu Hu.
config MACH_PISTACHIO
bool "IMG Pistachio SoC based boards"
@@ -373,7 +385,7 @@ config MACH_PISTACHIO
select COMMON_CLK
select CSRC_R4K
select DMA_MAYBE_COHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select LIBFDT
select MFD_SYSCON
select MIPS_CPU_SCACHE
@@ -386,22 +398,48 @@ config MACH_PISTACHIO
select SYS_SUPPORTS_MIPS_CPS
select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_ZBOOT
+ select SYS_HAS_EARLY_PRINTK
+ select USE_GENERIC_EARLY_PRINTK_8250
select USE_OF
help
This enables support for the IMG Pistachio SoC platform.
+config MACH_XILFPGA
+ bool "MIPSfpga Xilinx based boards"
+ select ARCH_REQUIRE_GPIOLIB
+ select BOOT_ELF32
+ select BOOT_RAW
+ select BUILTIN_DTB
+ select CEVT_R4K
+ select COMMON_CLK
+ select CSRC_R4K
+ select IRQ_MIPS_CPU
+ select LIBFDT
+ select MIPS_CPU_SCACHE
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_ZBOOT_UART16550
+ select USE_OF
+ select USE_GENERIC_EARLY_PRINTK_8250
+ help
+ This enables support for the IMG University Program MIPSfpga platform.
+
config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
select BOOT_RAW
+ select BUILTIN_DTB
select CEVT_R4K
select CSRC_R4K
select CLKSRC_MIPS_GIC
+ select COMMON_CLK
select DMA_MAYBE_COHERENT
select GENERIC_ISA_DMA
select HAVE_PCSPKR_PLATFORM
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select MIPS_GIC
select HW_HAS_PCI
select I8253
@@ -411,6 +449,7 @@ config MIPS_MALTA
select MIPS_L1_CACHE_SHIFT_6
select PCI_GT64XXX_PCI0
select MIPS_MSC
+ select SMP_UP if SMP
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
@@ -434,6 +473,10 @@ config MIPS_MALTA
select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_SMARTMIPS
select SYS_SUPPORTS_ZBOOT
+ select USE_OF
+ select ZONE_DMA32 if 64BIT
+ select BUILTIN_DTB
+ select LIBFDT
help
This enables support for the MIPS Technologies Malta evaluation
board.
@@ -446,10 +489,11 @@ config MIPS_SEAD3
select CEVT_R4K
select CSRC_R4K
select CLKSRC_MIPS_GIC
+ select COMMON_CLK
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select MIPS_GIC
select LIBFDT
select MIPS_MSC
@@ -512,7 +556,7 @@ config PMC_MSP
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_MIPS16
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SERIAL_8250
select SERIAL_8250_CONSOLE
select USB_EHCI_BIG_ENDIAN_MMIO
@@ -529,7 +573,7 @@ config RALINK
select CSRC_R4K
select BOOT_RAW
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select USE_OF
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
@@ -555,7 +599,7 @@ config SGI_IP22
select I8253
select I8259
select IP22_CPU_SCACHE
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select GENERIC_ISA_DMA_SUPPORT_BROKEN
select SGI_HAS_I8042
select SGI_HAS_INDYDOG
@@ -614,7 +658,7 @@ config SGI_IP28
select DEFAULT_SGI_PARTITION
select DMA_NONCOHERENT
select GENERIC_ISA_DMA_SUPPORT_BROKEN
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select HW_HAS_EISA
select I8253
select I8259
@@ -650,7 +694,7 @@ config SGI_IP32
select CSRC_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select R5000_CPU_SCACHE
select RM7000_CPU_SCACHE
select SYS_HAS_CPU_R5000
@@ -766,7 +810,7 @@ config SNI_RM
select HAVE_PCSPKR_PLATFORM
select HW_HAS_EISA
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select I8253
select I8259
select ISA
@@ -799,7 +843,7 @@ config MIKROTIK_RB532
select CSRC_R4K
select DMA_NONCOHERENT
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -819,6 +863,7 @@ config CAVIUM_OCTEON_SOC
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select EDAC_SUPPORT
+ select EDAC_ATOMIC_SCRUB
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HOTPLUG_CPU if CPU_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
@@ -865,7 +910,7 @@ config NLM_XLR_BOARD
select NR_CPUS_DEFAULT_32
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
@@ -885,6 +930,7 @@ config NLM_XLP_BOARD
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select ARCH_PHYS_ADDR_T_64BIT
+ select ARCH_REQUIRE_GPIOLIB
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
@@ -892,7 +938,7 @@ config NLM_XLP_BOARD
select NR_CPUS_DEFAULT_32
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ZONE_DMA32 if 64BIT
select SYNC_R4K
select SYS_HAS_EARLY_PRINTK
@@ -934,6 +980,7 @@ source "arch/mips/jazz/Kconfig"
source "arch/mips/jz4740/Kconfig"
source "arch/mips/lantiq/Kconfig"
source "arch/mips/lasat/Kconfig"
+source "arch/mips/pistachio/Kconfig"
source "arch/mips/pmcs-msp71xx/Kconfig"
source "arch/mips/ralink/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
@@ -941,10 +988,11 @@ source "arch/mips/sibyte/Kconfig"
source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
-source "arch/mips/loongson/Kconfig"
-source "arch/mips/loongson1/Kconfig"
+source "arch/mips/loongson32/Kconfig"
+source "arch/mips/loongson64/Kconfig"
source "arch/mips/netlogic/Kconfig"
source "arch/mips/paravirt/Kconfig"
+source "arch/mips/xilfpga/Kconfig"
endmenu
@@ -1017,6 +1065,9 @@ config CSRC_R4K
config CSRC_SB1250
bool
+config MIPS_CLOCK_VSYSCALL
+ def_bool CSRC_R4K || CLKSRC_MIPS_GIC
+
config GPIO_TXX9
select ARCH_REQUIRE_GPIOLIB
bool
@@ -1027,6 +1078,9 @@ config FW_CFE
config ARCH_DMA_ADDR_T_64BIT
def_bool (HIGHMEM && ARCH_PHYS_ADDR_T_64BIT) || 64BIT
+config ARCH_SUPPORTS_UPROBES
+ bool
+
config DMA_MAYBE_COHERENT
select DMA_NONCOHERENT
bool
@@ -1057,10 +1111,6 @@ config HOTPLUG_CPU
config SYS_SUPPORTS_HOTPLUG_CPU
bool
-config I8259
- bool
- select IRQ_DOMAIN
-
config MIPS_BONITO64
bool
@@ -1141,10 +1191,6 @@ config SYS_SUPPORTS_HUGETLBFS
config MIPS_HUGE_TLB_SUPPORT
def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE
-config IRQ_CPU
- bool
- select IRQ_DOMAIN
-
config IRQ_CPU_RM7K
bool
@@ -1171,7 +1217,7 @@ config SOC_EMMA2RH
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SWAP_IO_SPACE
select SYS_HAS_CPU_R5500
select SYS_SUPPORTS_32BIT_KERNEL
@@ -1182,7 +1228,7 @@ config SOC_PNX833X
bool
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select DMA_NONCOHERENT
select SYS_HAS_CPU_MIPS32_R2
select SYS_SUPPORTS_32BIT_KERNEL
@@ -1358,7 +1404,7 @@ config CPU_MIPS32_R2
otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
config CPU_MIPS32_R6
- bool "MIPS32 Release 6 (EXPERIMENTAL)"
+ bool "MIPS32 Release 6"
depends on SYS_HAS_CPU_MIPS32_R6
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
@@ -1409,7 +1455,7 @@ config CPU_MIPS64_R2
otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
config CPU_MIPS64_R6
- bool "MIPS64 Release 6 (EXPERIMENTAL)"
+ bool "MIPS64 Release 6"
depends on SYS_HAS_CPU_MIPS64_R6
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
@@ -1569,7 +1615,8 @@ config CPU_CAVIUM_OCTEON
select WEAK_ORDERING
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
- select USB_EHCI_BIG_ENDIAN_MMIO
+ select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
+ select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select MIPS_L1_CACHE_SHIFT_7
help
The Cavium Octeon processor is a highly integrated chip containing
@@ -1587,7 +1634,7 @@ config CPU_BMIPS
select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000
select CPU_SUPPORTS_32BIT_KERNEL
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SWAP_IO_SPACE
select WEAK_ORDERING
select CPU_SUPPORTS_HIGHMEM
@@ -1958,6 +2005,7 @@ config 32BIT
select TRAD_SIGNALS
help
Select this option if you want to build a 32-bit kernel.
+
config 64BIT
bool "64-bit kernel"
depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
@@ -2103,11 +2151,11 @@ config CPU_R4K_CACHE_TLB
config MIPS_MT_SMP
bool "MIPS MT SMP support (1 TC on each available VPE)"
- depends on SYS_SUPPORTS_MULTITHREADING
+ depends on SYS_SUPPORTS_MULTITHREADING && !CPU_MIPSR6
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
select SYNC_R4K
- select MIPS_GIC_IPI
+ select MIPS_GIC_IPI if MIPS_GIC
select MIPS_MT
select SMP
select SMP_UP
@@ -2204,8 +2252,8 @@ config MIPS_VPE_APSP_API_MT
config MIPS_CMP
bool "MIPS CMP framework support (DEPRECATED)"
- depends on SYS_SUPPORTS_MIPS_CMP
- select MIPS_GIC_IPI
+ depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
+ select MIPS_GIC_IPI if MIPS_GIC
select SMP
select SYNC_R4K
select SYS_SUPPORTS_SMP
@@ -2221,11 +2269,11 @@ config MIPS_CMP
config MIPS_CPS
bool "MIPS Coherent Processing System support"
- depends on SYS_SUPPORTS_MIPS_CPS && !64BIT
+ depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6
select MIPS_CM
select MIPS_CPC
select MIPS_CPS_PM if HOTPLUG_CPU
- select MIPS_GIC_IPI
+ select MIPS_GIC_IPI if MIPS_GIC
select SMP
select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
select SYS_SUPPORTS_HOTPLUG_CPU
@@ -2244,6 +2292,7 @@ config MIPS_CPS_PM
bool
config MIPS_GIC_IPI
+ depends on MIPS_GIC
bool
config MIPS_CM
@@ -2252,11 +2301,6 @@ config MIPS_CM
config MIPS_CPC
bool
-config SB1_PASS_1_WORKAROUNDS
- bool
- depends on CPU_SB1_PASS_1
- default y
-
config SB1_PASS_2_WORKAROUNDS
bool
depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2)
@@ -2301,7 +2345,7 @@ config CPU_MICROMIPS
endchoice
config CPU_HAS_MSA
- bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
+ bool "Support for the MIPS SIMD Architecture"
depends on CPU_SUPPORTS_MSA
depends on 64BIT || MIPS_O32_FP64_SUPPORT
help
@@ -2518,6 +2562,9 @@ choice
help
Allows the configuration of the timer frequency.
+ config HZ_24
+ bool "24 HZ" if SYS_SUPPORTS_24HZ || SYS_SUPPORTS_ARBIT_HZ
+
config HZ_48
bool "48 HZ" if SYS_SUPPORTS_48HZ || SYS_SUPPORTS_ARBIT_HZ
@@ -2541,6 +2588,9 @@ choice
endchoice
+config SYS_SUPPORTS_24HZ
+ bool
+
config SYS_SUPPORTS_48HZ
bool
@@ -2564,13 +2614,18 @@ config SYS_SUPPORTS_1024HZ
config SYS_SUPPORTS_ARBIT_HZ
bool
- default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \
- !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \
- !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \
+ default y if !SYS_SUPPORTS_24HZ && \
+ !SYS_SUPPORTS_48HZ && \
+ !SYS_SUPPORTS_100HZ && \
+ !SYS_SUPPORTS_128HZ && \
+ !SYS_SUPPORTS_250HZ && \
+ !SYS_SUPPORTS_256HZ && \
+ !SYS_SUPPORTS_1000HZ && \
!SYS_SUPPORTS_1024HZ
config HZ
int
+ default 24 if HZ_24
default 48 if HZ_48
default 100 if HZ_100
default 128 if HZ_128
@@ -2586,6 +2641,7 @@ source "kernel/Kconfig.preempt"
config KEXEC
bool "Kexec system call"
+ select KEXEC_CORE
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -2641,7 +2697,7 @@ 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 (EXPERIMENTAL)"
+ bool "Support for O32 binaries using 64-bit FP"
depends on 32BIT || MIPS32_O32
help
When this is enabled, the kernel will support use of 64-bit floating
@@ -2672,6 +2728,84 @@ config USE_OF
config BUILTIN_DTB
bool
+choice
+ prompt "Kernel appended dtb support" if USE_OF
+ default MIPS_NO_APPENDED_DTB
+
+ config MIPS_NO_APPENDED_DTB
+ bool "None"
+ help
+ Do not enable appended dtb support.
+
+ config MIPS_ELF_APPENDED_DTB
+ bool "vmlinux"
+ help
+ With this option, the boot code will look for a device tree binary
+ DTB) included in the vmlinux ELF section .appended_dtb. By default
+ it is empty and the DTB can be appended using binutils command
+ objcopy:
+
+ objcopy --update-section .appended_dtb=<filename>.dtb vmlinux
+
+ This is meant as a backward compatiblity convenience for those
+ systems with a bootloader that can't be upgraded to accommodate
+ the documented boot protocol using a device tree.
+
+ config MIPS_RAW_APPENDED_DTB
+ bool "vmlinux.bin"
+ help
+ With this option, the boot code will look for a device tree binary
+ DTB) appended to raw vmlinux.bin (without decompressor).
+ (e.g. cat vmlinux.bin <filename>.dtb > vmlinux_w_dtb).
+
+ This is meant as a backward compatibility convenience for those
+ systems with a bootloader that can't be upgraded to accommodate
+ the documented boot protocol using a device tree.
+
+ Beware that there is very little in terms of protection against
+ this option being confused by leftover garbage in memory that might
+ look like a DTB header after a reboot if no actual DTB is appended
+ to vmlinux.bin. Do not leave this option active in a production kernel
+ if you don't intend to always append a DTB.
+
+ config MIPS_ZBOOT_APPENDED_DTB
+ bool "vmlinuz.bin"
+ depends on SYS_SUPPORTS_ZBOOT
+ help
+ With this option, the boot code will look for a device tree binary
+ DTB) appended to raw vmlinuz.bin (with decompressor).
+ (e.g. cat vmlinuz.bin <filename>.dtb > vmlinuz_w_dtb).
+
+ This is meant as a backward compatibility convenience for those
+ systems with a bootloader that can't be upgraded to accommodate
+ the documented boot protocol using a device tree.
+
+ Beware that there is very little in terms of protection against
+ this option being confused by leftover garbage in memory that might
+ look like a DTB header after a reboot if no actual DTB is appended
+ to vmlinuz.bin. Do not leave this option active in a production kernel
+ if you don't intend to always append a DTB.
+endchoice
+
+choice
+ prompt "Kernel command line type" if !CMDLINE_OVERRIDE
+ default MIPS_CMDLINE_FROM_DTB if USE_OF && !ATH79 && !MACH_INGENIC && \
+ !MIPS_MALTA && !MIPS_SEAD3 && \
+ !CAVIUM_OCTEON_SOC
+ default MIPS_CMDLINE_FROM_BOOTLOADER
+
+ config MIPS_CMDLINE_FROM_DTB
+ depends on USE_OF
+ bool "Dtb kernel arguments if available"
+
+ config MIPS_CMDLINE_DTB_EXTEND
+ depends on USE_OF
+ bool "Extend dtb kernel arguments with bootloader arguments"
+
+ config MIPS_CMDLINE_FROM_BOOTLOADER
+ bool "Bootloader kernel arguments if available"
+endchoice
+
endmenu
config LOCKDEP_SUPPORT
@@ -2682,6 +2816,10 @@ config STACKTRACE_SUPPORT
bool
default y
+config HAVE_LATENCYTOP_SUPPORT
+ bool
+ default y
+
config PGTABLE_LEVELS
int
default 3 if 64BIT && !PAGE_SIZE_64KB
diff --git a/kernel/arch/mips/Kconfig.debug b/kernel/arch/mips/Kconfig.debug
index 3a2b775e8..f0e314ceb 100644
--- a/kernel/arch/mips/Kconfig.debug
+++ b/kernel/arch/mips/Kconfig.debug
@@ -87,15 +87,6 @@ config SB1XXX_CORELIS
Select compile flags that produce code that can be processed by the
Corelis mksym utility and UDB Emulator.
-config RUNTIME_DEBUG
- bool "Enable run-time debugging"
- depends on DEBUG_KERNEL
- help
- If you say Y here, some debugging macros will do run-time checking.
- If you say N here, those macros will mostly turn to no-ops. See
- arch/mips/include/asm/debug.h for debugging macros.
- If unsure, say N.
-
config DEBUG_ZBOOT
bool "Enable compressed kernel support debugging"
depends on DEBUG_KERNEL && SYS_SUPPORTS_ZBOOT
@@ -122,4 +113,76 @@ config SPINLOCK_TEST
help
Add several files to the debugfs to test spinlock speed.
+if CPU_MIPSR6
+
+choice
+ prompt "Compact branch policy"
+ default MIPS_COMPACT_BRANCHES_OPTIMAL
+
+config MIPS_COMPACT_BRANCHES_NEVER
+ bool "Never (force delay slot branches)"
+ help
+ Pass the -mcompact-branches=never flag to the compiler in order to
+ force it to always emit branches with delay slots, and make no use
+ of the compact branch instructions introduced by MIPSr6. This is
+ useful if you suspect there may be an issue with compact branches in
+ either the compiler or the CPU.
+
+config MIPS_COMPACT_BRANCHES_OPTIMAL
+ bool "Optimal (use where beneficial)"
+ help
+ Pass the -mcompact-branches=optimal flag to the compiler in order for
+ it to make use of compact branch instructions where it deems them
+ beneficial, and use branches with delay slots elsewhere. This is the
+ default compiler behaviour, and should be used unless you have a
+ reason to choose otherwise.
+
+config MIPS_COMPACT_BRANCHES_ALWAYS
+ bool "Always (force compact branches)"
+ help
+ Pass the -mcompact-branches=always flag to the compiler in order to
+ force it to always emit compact branches, making no use of branch
+ instructions with delay slots. This can result in more compact code
+ which may be beneficial in some scenarios.
+
+endchoice
+
+endif # CPU_MIPSR6
+
+config SCACHE_DEBUGFS
+ bool "L2 cache debugfs entries"
+ depends on DEBUG_FS
+ help
+ Enable this to allow parts of the L2 cache configuration, such as
+ whether or not prefetching is enabled, to be exposed to userland
+ via debugfs.
+
+ If unsure, say N.
+
+menuconfig MIPS_CPS_NS16550
+ bool "CPS SMP NS16550 UART output"
+ depends on MIPS_CPS
+ help
+ Output debug information via an ns16550 compatible UART if exceptions
+ occur early in the boot process of a secondary core.
+
+if MIPS_CPS_NS16550
+
+config MIPS_CPS_NS16550_BASE
+ hex "UART Base Address"
+ default 0x1b0003f8 if MIPS_MALTA
+ help
+ The base address of the ns16550 compatible UART on which to output
+ debug information from the early stages of core startup.
+
+config MIPS_CPS_NS16550_SHIFT
+ int "UART Register Shift"
+ default 0 if MIPS_MALTA
+ help
+ The number of bits to shift ns16550 register indices by in order to
+ form their addresses. That is, log base 2 of the span between
+ adjacent ns16550 registers in the system.
+
+endif # MIPS_CPS_NS16550
+
endmenu
diff --git a/kernel/arch/mips/Makefile b/kernel/arch/mips/Makefile
index ae2dd5905..3f70ba54a 100644
--- a/kernel/arch/mips/Makefile
+++ b/kernel/arch/mips/Makefile
@@ -181,13 +181,6 @@ cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS) += $(call cc-option,-mno-daddi,)
-ifdef CONFIG_CPU_SB1
-ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
-KBUILD_AFLAGS_MODULE += -msb1-pass1-workarounds
-KBUILD_CFLAGS_MODULE += -msb1-pass1-workarounds
-endif
-endif
-
# For smartmips configurations, there are hundreds of warnings due to ISA overrides
# in assembly and header files. smartmips is only supported for MIPS32r1 onwards
# and there is no support for 64-bit. Various '.set mips2' or '.set mips3' or
@@ -211,6 +204,10 @@ toolchain-msa := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(
cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA
endif
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER) += -mcompact-branches=never
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS) += -mcompact-branches=always
+
#
# Firmware support
#
diff --git a/kernel/arch/mips/alchemy/Kconfig b/kernel/arch/mips/alchemy/Kconfig
index b9628983d..7fa24881b 100644
--- a/kernel/arch/mips/alchemy/Kconfig
+++ b/kernel/arch/mips/alchemy/Kconfig
@@ -6,13 +6,6 @@ config ALCHEMY_GPIOINT_AU1000
config ALCHEMY_GPIOINT_AU1300
bool
-# select this in your board config if you don't want to use the gpio
-# namespace as documented in the manuals. In this case however you need
-# to create the necessary gpio_* functions in your board code/headers!
-# see arch/mips/include/asm/mach-au1x00/gpio.h for more information.
-config ALCHEMY_GPIO_INDIRECT
- def_bool n
-
choice
prompt "Machine type"
depends on MIPS_ALCHEMY
diff --git a/kernel/arch/mips/alchemy/board-gpr.c b/kernel/arch/mips/alchemy/board-gpr.c
index acf9a2a37..79efe4c6e 100644
--- a/kernel/arch/mips/alchemy/board-gpr.c
+++ b/kernel/arch/mips/alchemy/board-gpr.c
@@ -34,6 +34,7 @@
#include <asm/idle.h>
#include <asm/reboot.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
#include <prom.h>
const char *get_system_type(void)
diff --git a/kernel/arch/mips/alchemy/board-mtx1.c b/kernel/arch/mips/alchemy/board-mtx1.c
index 1e3b10238..85bb75669 100644
--- a/kernel/arch/mips/alchemy/board-mtx1.c
+++ b/kernel/arch/mips/alchemy/board-mtx1.c
@@ -32,6 +32,7 @@
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/au1xxx_eth.h>
#include <prom.h>
diff --git a/kernel/arch/mips/alchemy/common/Makefile b/kernel/arch/mips/alchemy/common/Makefile
index f64744f3b..23800b8e6 100644
--- a/kernel/arch/mips/alchemy/common/Makefile
+++ b/kernel/arch/mips/alchemy/common/Makefile
@@ -5,10 +5,5 @@
# Makefile for the Alchemy Au1xx0 CPUs, generic files.
#
-obj-y += prom.o time.o clock.o platform.o power.o \
+obj-y += prom.o time.o clock.o platform.o power.o gpiolib.o \
setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
-
-# optional gpiolib support
-ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
- obj-$(CONFIG_GPIOLIB) += gpiolib.o
-endif
diff --git a/kernel/arch/mips/alchemy/common/clock.c b/kernel/arch/mips/alchemy/common/clock.c
index 6a98d2cb4..bd34f4093 100644
--- a/kernel/arch/mips/alchemy/common/clock.c
+++ b/kernel/arch/mips/alchemy/common/clock.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
@@ -389,12 +390,11 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
return div1;
}
-static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk,
- int scale, int maxdiv)
+static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
+ struct clk_rate_request *req,
+ int scale, int maxdiv)
{
- struct clk *pc, *bpc, *free;
+ struct clk_hw *pc, *bpc, *free;
long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
int j;
@@ -408,7 +408,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
* the one that gets closest to but not over the requested rate.
*/
for (j = 0; j < 7; j++) {
- pc = clk_get_parent_by_index(hw->clk, j);
+ pc = clk_hw_get_parent_by_index(hw, j);
if (!pc)
break;
@@ -416,20 +416,20 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
* XXX: we would actually want clk_has_active_children()
* but this is a good-enough approximation for now.
*/
- if (!__clk_is_prepared(pc)) {
+ if (!clk_hw_is_prepared(pc)) {
if (!free)
free = pc;
}
- pr = clk_get_rate(pc);
- if (pr < rate)
+ pr = clk_hw_get_rate(pc);
+ if (pr < req->rate)
continue;
/* what can hardware actually provide */
- tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+ tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
nr = pr / tdv;
- diff = rate - nr;
- if (nr > rate)
+ diff = req->rate - nr;
+ if (nr > req->rate)
continue;
if (diff < lastdiff) {
@@ -448,15 +448,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
*/
if (lastdiff && free) {
for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
- tpr = rate * j;
+ tpr = req->rate * j;
if (tpr < 0)
break;
- pr = clk_round_rate(free, tpr);
+ pr = clk_hw_round_rate(free, tpr);
- tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+ tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
+ NULL);
nr = pr / tdv;
- diff = rate - nr;
- if (nr > rate)
+ diff = req->rate - nr;
+ if (nr > req->rate)
continue;
if (diff < lastdiff) {
lastdiff = diff;
@@ -469,9 +470,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
}
}
- *best_parent_rate = bpr;
- *best_parent_clk = __clk_get_hw(bpc);
- return br;
+ if (br < 0)
+ return br;
+
+ req->best_parent_rate = bpr;
+ req->best_parent_hw = bpc;
+ req->rate = br;
+
+ return 0;
}
static int alchemy_clk_fgv1_en(struct clk_hw *hw)
@@ -562,14 +568,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
return parent_rate / v;
}
-static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, 2, 512);
+ return alchemy_clk_fgcs_detr(hw, req, 2, 512);
}
/* Au1000, Au1100, Au15x0, Au12x0 */
@@ -696,11 +698,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
return t;
}
-static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale, maxdiv;
@@ -713,8 +712,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
maxdiv = 512;
}
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, scale, maxdiv);
+ return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
}
/* Au1300 larger input mux, no separate disable bit, flexible divider */
@@ -752,12 +750,12 @@ static int __init alchemy_clk_init_fgens(int ctype)
switch (ctype) {
case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
id.ops = &alchemy_clkops_fgenv1;
- id.parent_names = (const char **)alchemy_clk_fgv1_parents;
+ id.parent_names = alchemy_clk_fgv1_parents;
id.num_parents = 2;
break;
case ALCHEMY_CPU_AU1300:
id.ops = &alchemy_clkops_fgenv2;
- id.parent_names = (const char **)alchemy_clk_fgv2_parents;
+ id.parent_names = alchemy_clk_fgv2_parents;
id.num_parents = 3;
break;
default:
@@ -917,17 +915,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_csrc_detr(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, scale, 4);
+ return alchemy_clk_fgcs_detr(hw, req, scale, 4);
}
static struct clk_ops alchemy_clkops_csrc = {
@@ -961,7 +955,7 @@ static int __init alchemy_clk_setup_imux(int ctype)
struct clk *c;
id.ops = &alchemy_clkops_csrc;
- id.parent_names = (const char **)alchemy_clk_csrc_parents;
+ id.parent_names = alchemy_clk_csrc_parents;
id.num_parents = 7;
id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
diff --git a/kernel/arch/mips/alchemy/common/irq.c b/kernel/arch/mips/alchemy/common/irq.c
index 6cb60abfd..da9f92200 100644
--- a/kernel/arch/mips/alchemy/common/irq.c
+++ b/kernel/arch/mips/alchemy/common/irq.c
@@ -491,7 +491,7 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
default:
ret = -EINVAL;
}
- __irq_set_chip_handler_name_locked(d->irq, chip, handler, name);
+ irq_set_chip_handler_name_locked(d, chip, handler, name);
wmb();
@@ -703,7 +703,7 @@ static int au1300_gpic_settype(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- __irq_set_chip_handler_name_locked(d->irq, &au1300_gpic, hdl, name);
+ irq_set_chip_handler_name_locked(d, &au1300_gpic, hdl, name);
au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s);
@@ -851,7 +851,7 @@ static struct syscore_ops alchemy_gpic_pmops = {
/* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */
#define DISP(name, base, addr) \
-static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \
+static void au1000_##name##_dispatch(struct irq_desc *d) \
{ \
unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr)); \
if (likely(r)) \
@@ -865,7 +865,7 @@ DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT)
DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT)
DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT)
-static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d)
+static void alchemy_gpic_dispatch(struct irq_desc *d)
{
int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC);
generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i);
diff --git a/kernel/arch/mips/alchemy/common/time.c b/kernel/arch/mips/alchemy/common/time.c
index 50e17e13c..f99d3ec17 100644
--- a/kernel/arch/mips/alchemy/common/time.c
+++ b/kernel/arch/mips/alchemy/common/time.c
@@ -69,11 +69,6 @@ static int au1x_rtcmatch2_set_next_event(unsigned long delta,
return 0;
}
-static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
- struct clock_event_device *cd)
-{
-}
-
static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
{
struct clock_event_device *cd = dev_id;
@@ -86,7 +81,6 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = {
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 1500,
.set_next_event = au1x_rtcmatch2_set_next_event,
- .set_mode = au1x_rtcmatch2_set_mode,
.cpumask = cpu_all_mask,
};
diff --git a/kernel/arch/mips/alchemy/devboards/bcsr.c b/kernel/arch/mips/alchemy/devboards/bcsr.c
index c98c9ea33..faeddf119 100644
--- a/kernel/arch/mips/alchemy/devboards/bcsr.c
+++ b/kernel/arch/mips/alchemy/devboards/bcsr.c
@@ -8,6 +8,7 @@
*/
#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
@@ -85,13 +86,14 @@ EXPORT_SYMBOL_GPL(bcsr_mod);
/*
* DB1200/PB1200 CPLD IRQ muxer
*/
-static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d)
+static void bcsr_csc_handler(struct irq_desc *d)
{
unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT);
+ struct irq_chip *chip = irq_desc_get_chip(d);
- disable_irq_nosync(irq);
+ chained_irq_enter(chip, d);
generic_handle_irq(bcsr_csc_base + __ffs(bisr));
- enable_irq(irq);
+ chained_irq_exit(chip, d);
}
static void bcsr_irq_mask(struct irq_data *d)
diff --git a/kernel/arch/mips/alchemy/devboards/db1000.c b/kernel/arch/mips/alchemy/devboards/db1000.c
index 001102e19..bdeed9d13 100644
--- a/kernel/arch/mips/alchemy/devboards/db1000.c
+++ b/kernel/arch/mips/alchemy/devboards/db1000.c
@@ -33,6 +33,7 @@
#include <linux/spi/spi_gpio.h>
#include <linux/spi/ads7846.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/au1000_dma.h>
#include <asm/mach-au1x00/au1100_mmc.h>
#include <asm/mach-db1x00/bcsr.h>
diff --git a/kernel/arch/mips/alchemy/devboards/db1300.c b/kernel/arch/mips/alchemy/devboards/db1300.c
index 1c64fdbe4..b58077008 100644
--- a/kernel/arch/mips/alchemy/devboards/db1300.c
+++ b/kernel/arch/mips/alchemy/devboards/db1300.c
@@ -24,6 +24,7 @@
#include <linux/wm97xx.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1300.h>
#include <asm/mach-au1x00/au1100_mmc.h>
#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
diff --git a/kernel/arch/mips/alchemy/devboards/db1550.c b/kernel/arch/mips/alchemy/devboards/db1550.c
index 0fd5177e3..5740bcfdf 100644
--- a/kernel/arch/mips/alchemy/devboards/db1550.c
+++ b/kernel/arch/mips/alchemy/devboards/db1550.c
@@ -20,6 +20,7 @@
#include <linux/spi/flash.h>
#include <asm/bootinfo.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/au1xxx_eth.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
diff --git a/kernel/arch/mips/alchemy/devboards/pm.c b/kernel/arch/mips/alchemy/devboards/pm.c
index bfeb8f3c0..93024dc6b 100644
--- a/kernel/arch/mips/alchemy/devboards/pm.c
+++ b/kernel/arch/mips/alchemy/devboards/pm.c
@@ -9,7 +9,7 @@
#include <linux/suspend.h>
#include <linux/sysfs.h>
#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-db1x00/bcsr.h>
/*
diff --git a/kernel/arch/mips/ar7/gpio.c b/kernel/arch/mips/ar7/gpio.c
index d8dbd8f0c..f4930456e 100644
--- a/kernel/arch/mips/ar7/gpio.c
+++ b/kernel/arch/mips/ar7/gpio.c
@@ -21,7 +21,10 @@
#include <linux/module.h>
#include <linux/gpio.h>
-#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+#define TITAN_GPIO_MAX 51
struct ar7_gpio_chip {
void __iomem *regs;
diff --git a/kernel/arch/mips/ar7/platform.c b/kernel/arch/mips/ar7/platform.c
index be9ff1673..58fca9ad5 100644
--- a/kernel/arch/mips/ar7/platform.c
+++ b/kernel/arch/mips/ar7/platform.c
@@ -39,7 +39,6 @@
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
-#include <asm/mach-ar7/gpio.h>
#include <asm/mach-ar7/prom.h>
/*****************************************************************************
@@ -679,7 +678,8 @@ static int __init ar7_register_devices(void)
}
if (ar7_has_high_cpmac()) {
- res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
+ res = fixed_phy_add(PHY_POLL, cpmac_high.id,
+ &fixed_phy_status, -1);
if (!res) {
cpmac_get_mac(1, cpmac_high_data.dev_addr);
@@ -692,7 +692,7 @@ static int __init ar7_register_devices(void)
} else
cpmac_low_data.phy_mask = 0xffffffff;
- res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
+ res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status, -1);
if (!res) {
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(&cpmac_low);
diff --git a/kernel/arch/mips/ar7/setup.c b/kernel/arch/mips/ar7/setup.c
index 820b7a313..7bb9a670b 100644
--- a/kernel/arch/mips/ar7/setup.c
+++ b/kernel/arch/mips/ar7/setup.c
@@ -23,7 +23,6 @@
#include <asm/reboot.h>
#include <asm/mach-ar7/ar7.h>
#include <asm/mach-ar7/prom.h>
-#include <asm/mach-ar7/gpio.h>
static void ar7_machine_restart(char *command)
{
diff --git a/kernel/arch/mips/ath25/ar2315.c b/kernel/arch/mips/ath25/ar2315.c
index 2befa7d76..8da996142 100644
--- a/kernel/arch/mips/ath25/ar2315.c
+++ b/kernel/arch/mips/ath25/ar2315.c
@@ -69,14 +69,14 @@ static struct irqaction ar2315_ahb_err_interrupt = {
.name = "ar2315-ahb-error",
};
-static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar2315_misc_irq_handler(struct irq_desc *desc)
{
u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
ar2315_rst_reg_read(AR2315_IMR);
unsigned nr, misc_irq = 0;
if (pending) {
- struct irq_domain *domain = irq_get_handler_data(irq);
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
@@ -161,8 +161,8 @@ void __init ar2315_arch_init_irq(void)
irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB);
setup_irq(irq, &ar2315_ahb_err_interrupt);
- irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
- irq_set_handler_data(AR2315_IRQ_MISC, domain);
+ irq_set_chained_handler_and_data(AR2315_IRQ_MISC,
+ ar2315_misc_irq_handler, domain);
ar2315_misc_irq_domain = domain;
}
diff --git a/kernel/arch/mips/ath25/ar5312.c b/kernel/arch/mips/ath25/ar5312.c
index b6887f751..acd55a9cf 100644
--- a/kernel/arch/mips/ath25/ar5312.c
+++ b/kernel/arch/mips/ath25/ar5312.c
@@ -73,14 +73,14 @@ static struct irqaction ar5312_ahb_err_interrupt = {
.name = "ar5312-ahb-error",
};
-static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar5312_misc_irq_handler(struct irq_desc *desc)
{
u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
ar5312_rst_reg_read(AR5312_IMR);
unsigned nr, misc_irq = 0;
if (pending) {
- struct irq_domain *domain = irq_get_handler_data(irq);
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
@@ -156,8 +156,8 @@ void __init ar5312_arch_init_irq(void)
irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC);
setup_irq(irq, &ar5312_ahb_err_interrupt);
- irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
- irq_set_handler_data(AR5312_IRQ_MISC, domain);
+ irq_set_chained_handler_and_data(AR5312_IRQ_MISC,
+ ar5312_misc_irq_handler, domain);
ar5312_misc_irq_domain = domain;
}
diff --git a/kernel/arch/mips/ath25/board.c b/kernel/arch/mips/ath25/board.c
index b8bb78282..9ab48ff80 100644
--- a/kernel/arch/mips/ath25/board.c
+++ b/kernel/arch/mips/ath25/board.c
@@ -216,7 +216,7 @@ void __init plat_time_init(void)
ar2315_plat_time_init();
}
-unsigned int __cpuinit get_c0_compare_int(void)
+unsigned int get_c0_compare_int(void)
{
return CP0_LEGACY_COMPARE_IRQ;
}
diff --git a/kernel/arch/mips/ath79/Kconfig b/kernel/arch/mips/ath79/Kconfig
index dfc60209d..13c04cf54 100644
--- a/kernel/arch/mips/ath79/Kconfig
+++ b/kernel/arch/mips/ath79/Kconfig
@@ -71,6 +71,18 @@ config ATH79_MACH_UBNT_XM
Say 'Y' here if you want your kernel to support the
Ubiquiti Networks XM (rev 1.0) board.
+choice
+ prompt "Build a DTB in the kernel"
+ optional
+ help
+ Select a devicetree that should be built into the kernel.
+
+ config DTB_TL_WR1043ND_V1
+ bool "TL-WR1043ND Version 1"
+ select BUILTIN_DTB
+ select SOC_AR913X
+endchoice
+
endmenu
config SOC_AR71XX
diff --git a/kernel/arch/mips/ath79/Makefile b/kernel/arch/mips/ath79/Makefile
index 5c9ff692f..fcc382cfc 100644
--- a/kernel/arch/mips/ath79/Makefile
+++ b/kernel/arch/mips/ath79/Makefile
@@ -8,7 +8,7 @@
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
-obj-y := prom.o setup.o irq.o common.o clock.o gpio.o
+obj-y := prom.o setup.o irq.o common.o clock.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/kernel/arch/mips/ath79/clock.c b/kernel/arch/mips/ath79/clock.c
index 26479f437..eb5117ced 100644
--- a/kernel/arch/mips/ath79/clock.c
+++ b/kernel/arch/mips/ath79/clock.c
@@ -17,6 +17,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
#include <asm/div64.h>
@@ -28,24 +29,27 @@
#define AR724X_BASE_FREQ 5000000
#define AR913X_BASE_FREQ 5000000
-struct clk {
- unsigned long rate;
+static struct clk *clks[3];
+static struct clk_onecell_data clk_data = {
+ .clks = clks,
+ .clk_num = ARRAY_SIZE(clks),
};
-static void __init ath79_add_sys_clkdev(const char *id, unsigned long rate)
+static struct clk *__init ath79_add_sys_clkdev(
+ const char *id, unsigned long rate)
{
struct clk *clk;
int err;
- clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate);
if (!clk)
panic("failed to allocate %s clock structure", id);
- clk->rate = rate;
-
err = clk_register_clkdev(clk, id, NULL);
if (err)
panic("unable to register %s clock device", id);
+
+ return clk;
}
static void __init ar71xx_clocks_init(void)
@@ -62,7 +66,7 @@ static void __init ar71xx_clocks_init(void)
pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
- div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
+ div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1;
freq = div * ref_rate;
div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
@@ -75,9 +79,9 @@ static void __init ar71xx_clocks_init(void)
ahb_rate = cpu_rate / div;
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ahb", NULL);
clk_add_alias("uart", NULL, "ahb", NULL);
@@ -96,7 +100,7 @@ static void __init ar724x_clocks_init(void)
ref_rate = AR724X_BASE_FREQ;
pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
- div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
+ div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK);
freq = div * ref_rate;
div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
@@ -111,9 +115,9 @@ static void __init ar724x_clocks_init(void)
ahb_rate = cpu_rate / div;
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ahb", NULL);
clk_add_alias("uart", NULL, "ahb", NULL);
@@ -132,7 +136,7 @@ static void __init ar913x_clocks_init(void)
ref_rate = AR913X_BASE_FREQ;
pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
- div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
+ div = ((pll >> AR913X_PLL_FB_SHIFT) & AR913X_PLL_FB_MASK);
freq = div * ref_rate;
cpu_rate = freq;
@@ -144,9 +148,9 @@ static void __init ar913x_clocks_init(void)
ahb_rate = cpu_rate / div;
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ahb", NULL);
clk_add_alias("uart", NULL, "ahb", NULL);
@@ -206,9 +210,9 @@ static void __init ar933x_clocks_init(void)
}
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ahb", NULL);
clk_add_alias("uart", NULL, "ref", NULL);
@@ -340,9 +344,9 @@ static void __init ar934x_clocks_init(void)
ahb_rate = cpu_pll / (postdiv + 1);
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ref", NULL);
clk_add_alias("uart", NULL, "ref", NULL);
@@ -427,9 +431,9 @@ static void __init qca955x_clocks_init(void)
ahb_rate = cpu_pll / (postdiv + 1);
ath79_add_sys_clkdev("ref", ref_rate);
- ath79_add_sys_clkdev("cpu", cpu_rate);
- ath79_add_sys_clkdev("ddr", ddr_rate);
- ath79_add_sys_clkdev("ahb", ahb_rate);
+ clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
+ clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
+ clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
clk_add_alias("wdt", NULL, "ref", NULL);
clk_add_alias("uart", NULL, "ref", NULL);
@@ -451,6 +455,8 @@ void __init ath79_clocks_init(void)
qca955x_clocks_init();
else
BUG();
+
+ of_clk_init(NULL);
}
unsigned long __init
@@ -469,22 +475,16 @@ ath79_get_sys_clk_rate(const char *id)
return rate;
}
-/*
- * Linux clock API
- */
-int clk_enable(struct clk *clk)
+#ifdef CONFIG_OF
+static void __init ath79_clocks_init_dt(struct device_node *np)
{
- return 0;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
-EXPORT_SYMBOL(clk_enable);
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
+CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt);
+CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt);
+CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt);
+CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt);
+CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt);
+CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt);
+#endif
diff --git a/kernel/arch/mips/ath79/common.c b/kernel/arch/mips/ath79/common.c
index eb3966cd8..3cedd1f95 100644
--- a/kernel/arch/mips/ath79/common.c
+++ b/kernel/arch/mips/ath79/common.c
@@ -38,11 +38,27 @@ unsigned int ath79_soc_rev;
void __iomem *ath79_pll_base;
void __iomem *ath79_reset_base;
EXPORT_SYMBOL_GPL(ath79_reset_base);
-void __iomem *ath79_ddr_base;
+static void __iomem *ath79_ddr_base;
+static void __iomem *ath79_ddr_wb_flush_base;
+static void __iomem *ath79_ddr_pci_win_base;
+
+void ath79_ddr_ctrl_init(void)
+{
+ ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
+ AR71XX_DDR_CTRL_SIZE);
+ if (soc_is_ar71xx() || soc_is_ar934x()) {
+ ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
+ ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
+ } else {
+ ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c;
+ ath79_ddr_pci_win_base = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
void ath79_ddr_wb_flush(u32 reg)
{
- void __iomem *flush_reg = ath79_ddr_base + reg;
+ void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg;
/* Flush the DDR write buffer. */
__raw_writel(0x1, flush_reg);
@@ -56,6 +72,21 @@ void ath79_ddr_wb_flush(u32 reg)
}
EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
+void ath79_ddr_set_pci_windows(void)
+{
+ BUG_ON(!ath79_ddr_pci_win_base);
+
+ __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0);
+ __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1);
+ __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2);
+ __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3);
+ __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4);
+ __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5);
+ __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6);
+ __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7);
+}
+EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
+
void ath79_device_reset_set(u32 mask)
{
unsigned long flags;
diff --git a/kernel/arch/mips/ath79/common.h b/kernel/arch/mips/ath79/common.h
index c39de61f9..ca7cc19ad 100644
--- a/kernel/arch/mips/ath79/common.h
+++ b/kernel/arch/mips/ath79/common.h
@@ -22,11 +22,9 @@
void ath79_clocks_init(void);
unsigned long ath79_get_sys_clk_rate(const char *id);
+void ath79_ddr_ctrl_init(void);
void ath79_ddr_wb_flush(unsigned int reg);
-void ath79_gpio_function_enable(u32 mask);
-void ath79_gpio_function_disable(u32 mask);
-void ath79_gpio_function_setup(u32 set, u32 clear);
void ath79_gpio_init(void);
#endif /* __ATH79_COMMON_H */
diff --git a/kernel/arch/mips/ath79/dev-common.c b/kernel/arch/mips/ath79/dev-common.c
index 516225d20..9d0172a4d 100644
--- a/kernel/arch/mips/ath79/dev-common.c
+++ b/kernel/arch/mips/ath79/dev-common.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/gpio-ath79.h>
#include <linux/serial_8250.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -106,3 +107,53 @@ void __init ath79_register_wdt(void)
platform_device_register_simple("ath79-wdt", -1, &res, 1);
}
+
+static struct ath79_gpio_platform_data ath79_gpio_pdata;
+
+static struct resource ath79_gpio_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = AR71XX_GPIO_BASE,
+ .end = AR71XX_GPIO_BASE + AR71XX_GPIO_SIZE - 1,
+ },
+ {
+ .start = ATH79_MISC_IRQ(2),
+ .end = ATH79_MISC_IRQ(2),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ath79_gpio_device = {
+ .name = "ath79-gpio",
+ .id = -1,
+ .resource = ath79_gpio_resources,
+ .num_resources = ARRAY_SIZE(ath79_gpio_resources),
+ .dev = {
+ .platform_data = &ath79_gpio_pdata
+ },
+};
+
+void __init ath79_gpio_init(void)
+{
+ if (soc_is_ar71xx()) {
+ ath79_gpio_pdata.ngpios = AR71XX_GPIO_COUNT;
+ } else if (soc_is_ar7240()) {
+ ath79_gpio_pdata.ngpios = AR7240_GPIO_COUNT;
+ } else if (soc_is_ar7241() || soc_is_ar7242()) {
+ ath79_gpio_pdata.ngpios = AR7241_GPIO_COUNT;
+ } else if (soc_is_ar913x()) {
+ ath79_gpio_pdata.ngpios = AR913X_GPIO_COUNT;
+ } else if (soc_is_ar933x()) {
+ ath79_gpio_pdata.ngpios = AR933X_GPIO_COUNT;
+ } else if (soc_is_ar934x()) {
+ ath79_gpio_pdata.ngpios = AR934X_GPIO_COUNT;
+ ath79_gpio_pdata.oe_inverted = 1;
+ } else if (soc_is_qca955x()) {
+ ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT;
+ ath79_gpio_pdata.oe_inverted = 1;
+ } else {
+ BUG();
+ }
+
+ platform_device_register(&ath79_gpio_device);
+}
diff --git a/kernel/arch/mips/ath79/gpio.c b/kernel/arch/mips/ath79/gpio.c
deleted file mode 100644
index 8d025b028..000000000
--- a/kernel/arch/mips/ath79/gpio.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Atheros AR71XX/AR724X/AR913X GPIO API support
- *
- * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
- * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ath79.h>
-#include "common.h"
-
-static void __iomem *ath79_gpio_base;
-static unsigned long ath79_gpio_count;
-static DEFINE_SPINLOCK(ath79_gpio_lock);
-
-static void __ath79_gpio_set_value(unsigned gpio, int value)
-{
- void __iomem *base = ath79_gpio_base;
-
- if (value)
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
- else
- __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
-}
-
-static int __ath79_gpio_get_value(unsigned gpio)
-{
- return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
-}
-
-static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
- return __ath79_gpio_get_value(offset);
-}
-
-static void ath79_gpio_set_value(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- __ath79_gpio_set_value(offset, value);
-}
-
-static int ath79_gpio_direction_input(struct gpio_chip *chip,
- unsigned offset)
-{
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
-
- spin_lock_irqsave(&ath79_gpio_lock, flags);
-
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
- base + AR71XX_GPIO_REG_OE);
-
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
- return 0;
-}
-
-static int ath79_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
-
- spin_lock_irqsave(&ath79_gpio_lock, flags);
-
- if (value)
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
- else
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
-
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
- base + AR71XX_GPIO_REG_OE);
-
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
- return 0;
-}
-
-static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
-
- spin_lock_irqsave(&ath79_gpio_lock, flags);
-
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
- base + AR71XX_GPIO_REG_OE);
-
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
- return 0;
-}
-
-static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- void __iomem *base = ath79_gpio_base;
- unsigned long flags;
-
- spin_lock_irqsave(&ath79_gpio_lock, flags);
-
- if (value)
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
- else
- __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
-
- __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
- base + AR71XX_GPIO_REG_OE);
-
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-
- return 0;
-}
-
-static struct gpio_chip ath79_gpio_chip = {
- .label = "ath79",
- .get = ath79_gpio_get_value,
- .set = ath79_gpio_set_value,
- .direction_input = ath79_gpio_direction_input,
- .direction_output = ath79_gpio_direction_output,
- .base = 0,
-};
-
-static void __iomem *ath79_gpio_get_function_reg(void)
-{
- u32 reg = 0;
-
- if (soc_is_ar71xx() ||
- soc_is_ar724x() ||
- soc_is_ar913x() ||
- soc_is_ar933x())
- reg = AR71XX_GPIO_REG_FUNC;
- else if (soc_is_ar934x())
- reg = AR934X_GPIO_REG_FUNC;
- else
- BUG();
-
- return ath79_gpio_base + reg;
-}
-
-void ath79_gpio_function_setup(u32 set, u32 clear)
-{
- void __iomem *reg = ath79_gpio_get_function_reg();
- unsigned long flags;
-
- spin_lock_irqsave(&ath79_gpio_lock, flags);
-
- __raw_writel((__raw_readl(reg) & ~clear) | set, reg);
- /* flush write */
- __raw_readl(reg);
-
- spin_unlock_irqrestore(&ath79_gpio_lock, flags);
-}
-
-void ath79_gpio_function_enable(u32 mask)
-{
- ath79_gpio_function_setup(mask, 0);
-}
-
-void ath79_gpio_function_disable(u32 mask)
-{
- ath79_gpio_function_setup(0, mask);
-}
-
-void __init ath79_gpio_init(void)
-{
- int err;
-
- if (soc_is_ar71xx())
- ath79_gpio_count = AR71XX_GPIO_COUNT;
- else if (soc_is_ar7240())
- ath79_gpio_count = AR7240_GPIO_COUNT;
- else if (soc_is_ar7241() || soc_is_ar7242())
- ath79_gpio_count = AR7241_GPIO_COUNT;
- else if (soc_is_ar913x())
- ath79_gpio_count = AR913X_GPIO_COUNT;
- else if (soc_is_ar933x())
- ath79_gpio_count = AR933X_GPIO_COUNT;
- else if (soc_is_ar934x())
- ath79_gpio_count = AR934X_GPIO_COUNT;
- else if (soc_is_qca955x())
- ath79_gpio_count = QCA955X_GPIO_COUNT;
- else
- BUG();
-
- ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
- ath79_gpio_chip.ngpio = ath79_gpio_count;
- if (soc_is_ar934x() || soc_is_qca955x()) {
- ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
- ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
- }
-
- err = gpiochip_add(&ath79_gpio_chip);
- if (err)
- panic("cannot add AR71xx GPIO chip, error=%d", err);
-}
-
-int gpio_get_value(unsigned gpio)
-{
- if (gpio < ath79_gpio_count)
- return __ath79_gpio_get_value(gpio);
-
- return __gpio_get_value(gpio);
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned gpio, int value)
-{
- if (gpio < ath79_gpio_count)
- __ath79_gpio_set_value(gpio, value);
- else
- __gpio_set_value(gpio, value);
-}
-EXPORT_SYMBOL(gpio_set_value);
-
-int gpio_to_irq(unsigned gpio)
-{
- /* FIXME */
- return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
- /* FIXME */
- return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
diff --git a/kernel/arch/mips/ath79/irq.c b/kernel/arch/mips/ath79/irq.c
index 6adae366f..eeb3953ed 100644
--- a/kernel/arch/mips/ath79/irq.c
+++ b/kernel/arch/mips/ath79/irq.c
@@ -15,7 +15,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/of_irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
@@ -23,11 +24,9 @@
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include "common.h"
+#include "machtypes.h"
-static void (*ath79_ip2_handler)(void);
-static void (*ath79_ip3_handler)(void);
-
-static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ath79_misc_irq_handler(struct irq_desc *desc)
{
void __iomem *base = ath79_reset_base;
u32 pending;
@@ -120,25 +119,21 @@ static void __init ath79_misc_irq_init(void)
irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
}
-static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void ar934x_ip2_irq_dispatch(struct irq_desc *desc)
{
u32 status;
- disable_irq_nosync(irq);
-
status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
- ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
+ ath79_ddr_wb_flush(3);
generic_handle_irq(ATH79_IP2_IRQ(0));
} else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
- ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
+ ath79_ddr_wb_flush(4);
generic_handle_irq(ATH79_IP2_IRQ(1));
} else {
spurious_interrupt();
}
-
- enable_irq(irq);
}
static void ar934x_ip2_irq_init(void)
@@ -153,18 +148,16 @@ static void ar934x_ip2_irq_init(void)
irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
}
-static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void qca955x_ip2_irq_dispatch(struct irq_desc *desc)
{
u32 status;
- disable_irq_nosync(irq);
-
status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL;
if (status == 0) {
spurious_interrupt();
- goto enable;
+ return;
}
if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) {
@@ -176,17 +169,12 @@ static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
/* TODO: flush DDR? */
generic_handle_irq(ATH79_IP2_IRQ(1));
}
-
-enable:
- enable_irq(irq);
}
-static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void qca955x_ip3_irq_dispatch(struct irq_desc *desc)
{
u32 status;
- disable_irq_nosync(irq);
-
status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
status &= QCA955X_EXT_INT_PCIE_RC2_ALL |
QCA955X_EXT_INT_USB1 |
@@ -194,7 +182,7 @@ static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
if (status == 0) {
spurious_interrupt();
- goto enable;
+ return;
}
if (status & QCA955X_EXT_INT_USB1) {
@@ -211,9 +199,6 @@ static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
/* TODO: flush DDR? */
generic_handle_irq(ATH79_IP3_IRQ(2));
}
-
-enable:
- enable_irq(irq);
}
static void qca955x_irq_init(void)
@@ -235,128 +220,150 @@ static void qca955x_irq_init(void)
irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
}
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned long pending;
-
- pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
- if (pending & STATUSF_IP7)
- do_IRQ(ATH79_CPU_IRQ(7));
-
- else if (pending & STATUSF_IP2)
- ath79_ip2_handler();
-
- else if (pending & STATUSF_IP4)
- do_IRQ(ATH79_CPU_IRQ(4));
-
- else if (pending & STATUSF_IP5)
- do_IRQ(ATH79_CPU_IRQ(5));
-
- else if (pending & STATUSF_IP3)
- ath79_ip3_handler();
-
- else if (pending & STATUSF_IP6)
- do_IRQ(ATH79_CPU_IRQ(6));
-
- else
- spurious_interrupt();
-}
-
/*
* The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
* these devices typically allocate coherent DMA memory, however the
* DMA controller may still have some unsynchronized data in the FIFO.
* Issue a flush in the handlers to ensure that the driver sees
* the update.
+ *
+ * This array map the interrupt lines to the DDR write buffer channels.
*/
-static void ath79_default_ip2_handler(void)
-{
- do_IRQ(ATH79_CPU_IRQ(2));
-}
+static unsigned irq_wb_chan[8] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+};
-static void ath79_default_ip3_handler(void)
+asmlinkage void plat_irq_dispatch(void)
{
- do_IRQ(ATH79_CPU_IRQ(3));
-}
+ unsigned long pending;
+ int irq;
-static void ar71xx_ip2_handler(void)
-{
- ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
- do_IRQ(ATH79_CPU_IRQ(2));
-}
+ pending = read_c0_status() & read_c0_cause() & ST0_IM;
-static void ar724x_ip2_handler(void)
-{
- ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
- do_IRQ(ATH79_CPU_IRQ(2));
-}
+ if (!pending) {
+ spurious_interrupt();
+ return;
+ }
-static void ar913x_ip2_handler(void)
-{
- ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
- do_IRQ(ATH79_CPU_IRQ(2));
+ pending >>= CAUSEB_IP;
+ while (pending) {
+ irq = fls(pending) - 1;
+ if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1)
+ ath79_ddr_wb_flush(irq_wb_chan[irq]);
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+ pending &= ~BIT(irq);
+ }
}
-static void ar933x_ip2_handler(void)
+#ifdef CONFIG_IRQCHIP
+static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
- ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
- do_IRQ(ATH79_CPU_IRQ(2));
+ irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq);
+ return 0;
}
-static void ar71xx_ip3_handler(void)
-{
- ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
- do_IRQ(ATH79_CPU_IRQ(3));
-}
+static const struct irq_domain_ops misc_irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = misc_map,
+};
-static void ar724x_ip3_handler(void)
+static int __init ath79_misc_intc_of_init(
+ struct device_node *node, struct device_node *parent)
{
- ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
- do_IRQ(ATH79_CPU_IRQ(3));
+ void __iomem *base = ath79_reset_base;
+ struct irq_domain *domain;
+ int irq;
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq)
+ panic("Failed to get MISC IRQ");
+
+ domain = irq_domain_add_legacy(node, ATH79_MISC_IRQ_COUNT,
+ ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, NULL);
+ if (!domain)
+ panic("Failed to add MISC irqdomain");
+
+ /* Disable and clear all interrupts */
+ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+
+ irq_set_chained_handler(irq, ath79_misc_irq_handler);
+
+ return 0;
}
-static void ar913x_ip3_handler(void)
+static int __init ar7100_misc_intc_of_init(
+ struct device_node *node, struct device_node *parent)
{
- ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
- do_IRQ(ATH79_CPU_IRQ(3));
+ ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
+ return ath79_misc_intc_of_init(node, parent);
}
-static void ar933x_ip3_handler(void)
+IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
+ ar7100_misc_intc_of_init);
+
+static int __init ar7240_misc_intc_of_init(
+ struct device_node *node, struct device_node *parent)
{
- ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
- do_IRQ(ATH79_CPU_IRQ(3));
+ ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
+ return ath79_misc_intc_of_init(node, parent);
}
-static void ar934x_ip3_handler(void)
+IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
+ ar7240_misc_intc_of_init);
+
+static int __init ar79_cpu_intc_of_init(
+ struct device_node *node, struct device_node *parent)
{
- ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
- do_IRQ(ATH79_CPU_IRQ(3));
+ int err, i, count;
+
+ /* Fill the irq_wb_chan table */
+ count = of_count_phandle_with_args(
+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
+
+ for (i = 0; i < count; i++) {
+ struct of_phandle_args args;
+ u32 irq = i;
+
+ of_property_read_u32_index(
+ node, "qca,ddr-wb-channel-interrupts", i, &irq);
+ if (irq >= ARRAY_SIZE(irq_wb_chan))
+ continue;
+
+ err = of_parse_phandle_with_args(
+ node, "qca,ddr-wb-channels",
+ "#qca,ddr-wb-channel-cells",
+ i, &args);
+ if (err)
+ return err;
+
+ irq_wb_chan[irq] = args.args[0];
+ pr_info("IRQ: Set flush channel of IRQ%d to %d\n",
+ irq, args.args[0]);
+ }
+
+ return mips_cpu_irq_of_init(node, parent);
}
+IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
+ ar79_cpu_intc_of_init);
+
+#endif
void __init arch_init_irq(void)
{
- if (soc_is_ar71xx()) {
- ath79_ip2_handler = ar71xx_ip2_handler;
- ath79_ip3_handler = ar71xx_ip3_handler;
- } else if (soc_is_ar724x()) {
- ath79_ip2_handler = ar724x_ip2_handler;
- ath79_ip3_handler = ar724x_ip3_handler;
- } else if (soc_is_ar913x()) {
- ath79_ip2_handler = ar913x_ip2_handler;
- ath79_ip3_handler = ar913x_ip3_handler;
- } else if (soc_is_ar933x()) {
- ath79_ip2_handler = ar933x_ip2_handler;
- ath79_ip3_handler = ar933x_ip3_handler;
+ if (mips_machtype == ATH79_MACH_GENERIC_OF) {
+ irqchip_init();
+ return;
+ }
+
+ if (soc_is_ar71xx() || soc_is_ar724x() ||
+ soc_is_ar913x() || soc_is_ar933x()) {
+ irq_wb_chan[2] = 3;
+ irq_wb_chan[3] = 2;
} else if (soc_is_ar934x()) {
- ath79_ip2_handler = ath79_default_ip2_handler;
- ath79_ip3_handler = ar934x_ip3_handler;
- } else if (soc_is_qca955x()) {
- ath79_ip2_handler = ath79_default_ip2_handler;
- ath79_ip3_handler = ath79_default_ip3_handler;
- } else {
- BUG();
+ irq_wb_chan[3] = 2;
}
mips_cpu_irq_init();
diff --git a/kernel/arch/mips/ath79/machtypes.h b/kernel/arch/mips/ath79/machtypes.h
index 26254058c..a13db3d15 100644
--- a/kernel/arch/mips/ath79/machtypes.h
+++ b/kernel/arch/mips/ath79/machtypes.h
@@ -15,6 +15,7 @@
#include <asm/mips_machine.h>
enum ath79_mach_type {
+ ATH79_MACH_GENERIC_OF = -1, /* Device tree board */
ATH79_MACH_GENERIC = 0,
ATH79_MACH_AP121, /* Atheros AP121 reference board */
ATH79_MACH_AP136_010, /* Atheros AP136-010 reference board */
diff --git a/kernel/arch/mips/ath79/setup.c b/kernel/arch/mips/ath79/setup.c
index fd2a36a79..8755d618e 100644
--- a/kernel/arch/mips/ath79/setup.c
+++ b/kernel/arch/mips/ath79/setup.c
@@ -17,12 +17,16 @@
#include <linux/bootmem.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
#include <asm/bootinfo.h>
#include <asm/idle.h>
#include <asm/time.h> /* for mips_hpt_frequency */
#include <asm/reboot.h> /* for _machine_{restart,halt} */
#include <asm/mips_machine.h>
+#include <asm/prom.h>
+#include <asm/fw/fw.h>
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
@@ -195,17 +199,28 @@ unsigned int get_c0_compare_int(void)
void __init plat_mem_setup(void)
{
+ unsigned long fdt_start;
+
set_io_port_base(KSEG1);
+ /* Get the position of the FDT passed by the bootloader */
+ fdt_start = fw_getenvl("fdt_start");
+ if (fdt_start)
+ __dt_setup_arch((void *)KSEG0ADDR(fdt_start));
+#ifdef CONFIG_BUILTIN_DTB
+ else
+ __dt_setup_arch(__dtb_start);
+#endif
+
ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
AR71XX_RESET_SIZE);
ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
AR71XX_PLL_SIZE);
- ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
- AR71XX_DDR_CTRL_SIZE);
-
ath79_detect_sys_type();
- detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
+ ath79_ddr_ctrl_init();
+
+ if (mips_machtype != ATH79_MACH_GENERIC_OF)
+ detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
_machine_restart = ath79_restart;
_machine_halt = ath79_halt;
@@ -237,6 +252,10 @@ void __init plat_time_init(void)
static int __init ath79_setup(void)
{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ if (mips_machtype == ATH79_MACH_GENERIC_OF)
+ return 0;
+
ath79_gpio_init();
ath79_register_uart();
ath79_register_wdt();
@@ -248,6 +267,11 @@ static int __init ath79_setup(void)
arch_initcall(ath79_setup);
+void __init device_tree_init(void)
+{
+ unflatten_and_copy_device_tree();
+}
+
static void __init ath79_generic_init(void)
{
/* Nothing to do */
@@ -257,3 +281,8 @@ MIPS_MACHINE(ATH79_MACH_GENERIC,
"Generic",
"Generic AR71XX/AR724X/AR913X based board",
ath79_generic_init);
+
+MIPS_MACHINE(ATH79_MACH_GENERIC_OF,
+ "DTB",
+ "Generic AR71XX/AR724X/AR913X based board (DT)",
+ NULL);
diff --git a/kernel/arch/mips/bcm47xx/Kconfig b/kernel/arch/mips/bcm47xx/Kconfig
index fc21d3659..e970fd9cf 100644
--- a/kernel/arch/mips/bcm47xx/Kconfig
+++ b/kernel/arch/mips/bcm47xx/Kconfig
@@ -4,6 +4,7 @@ config BCM47XX_SSB
bool "SSB Support for Broadcom BCM47XX"
select SYS_HAS_CPU_BMIPS32_3300
select SSB
+ select SSB_HOST_SOC
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
@@ -25,7 +26,6 @@ config BCM47XX_BCMA
select BCMA
select BCMA_HOST_SOC
select BCMA_DRIVER_MIPS
- select BCMA_HOST_PCI if PCI
select BCMA_DRIVER_PCI_HOSTMODE if PCI
select BCMA_DRIVER_GPIO
default y
diff --git a/kernel/arch/mips/bcm47xx/Makefile b/kernel/arch/mips/bcm47xx/Makefile
index d58c51b5e..66bea4ecf 100644
--- a/kernel/arch/mips/bcm47xx/Makefile
+++ b/kernel/arch/mips/bcm47xx/Makefile
@@ -3,5 +3,5 @@
# under Linux.
#
-obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y += irq.o prom.o serial.o setup.o time.o sprom.o
obj-y += board.o buttons.o leds.o workarounds.o
diff --git a/kernel/arch/mips/bcm47xx/board.c b/kernel/arch/mips/bcm47xx/board.c
index bd56415f2..a88975a55 100644
--- a/kernel/arch/mips/bcm47xx/board.c
+++ b/kernel/arch/mips/bcm47xx/board.c
@@ -149,6 +149,7 @@ struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = {
/* board_id */
static const
struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = {
+ {{BCM47XX_BOARD_LUXUL_XWR_1750_V1, "Luxul XWR-1750 V1"}, "luxul_xwr1750_v1"},
{{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WGR614_V10, "Netgear WGR614 V10"}, "U12H139T01_NETGEAR"},
diff --git a/kernel/arch/mips/bcm47xx/buttons.c b/kernel/arch/mips/bcm47xx/buttons.c
index 276276a8c..52caa75bf 100644
--- a/kernel/arch/mips/bcm47xx/buttons.c
+++ b/kernel/arch/mips/bcm47xx/buttons.c
@@ -299,6 +299,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
+/* Luxul */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_luxul_xwr_1750_v1[] = {
+ BCM47XX_GPIO_KEY(14, BTN_TASK),
+};
+
/* Microsoft */
static const struct gpio_keys_button
@@ -389,10 +396,9 @@ static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
{
size_t size = nbuttons * sizeof(*buttons);
- bcm47xx_button_pdata.buttons = kmalloc(size, GFP_KERNEL);
+ bcm47xx_button_pdata.buttons = kmemdup(buttons, size, GFP_KERNEL);
if (!bcm47xx_button_pdata.buttons)
return -ENOMEM;
- memcpy(bcm47xx_button_pdata.buttons, buttons, size);
bcm47xx_button_pdata.nbuttons = nbuttons;
return 0;
@@ -555,6 +561,10 @@ int __init bcm47xx_buttons_register(void)
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
break;
+ case BCM47XX_BOARD_LUXUL_XWR_1750_V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xwr_1750_v1);
+ break;
+
case BCM47XX_BOARD_MICROSOFT_MN700:
err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
break;
diff --git a/kernel/arch/mips/bcm47xx/leds.c b/kernel/arch/mips/bcm47xx/leds.c
index 0e4ade342..d20ae63eb 100644
--- a/kernel/arch/mips/bcm47xx/leds.c
+++ b/kernel/arch/mips/bcm47xx/leds.c
@@ -370,6 +370,16 @@ bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
};
+/* Luxul */
+
+static const struct gpio_led
+bcm47xx_leds_luxul_xwr_1750_v1[] __initconst = {
+ BCM47XX_GPIO_LED(5, "green", "5ghz", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(12, "green", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED_TRIGGER(13, "green", "status", 0, "timer"),
+ BCM47XX_GPIO_LED(15, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
/* Microsoft */
static const struct gpio_led
@@ -623,6 +633,10 @@ void __init bcm47xx_leds_register(void)
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
break;
+ case BCM47XX_BOARD_LUXUL_XWR_1750_V1:
+ bcm47xx_set_pdata(bcm47xx_leds_luxul_xwr_1750_v1);
+ break;
+
case BCM47XX_BOARD_MICROSOFT_MN700:
bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
break;
diff --git a/kernel/arch/mips/bcm47xx/nvram.c b/kernel/arch/mips/bcm47xx/nvram.c
deleted file mode 100644
index ba632ff08..000000000
--- a/kernel/arch/mips/bcm47xx/nvram.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * BCM947xx nvram variable access
- *
- * Copyright (C) 2005 Broadcom Corporation
- * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/io.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mtd/mtd.h>
-#include <linux/bcm47xx_nvram.h>
-
-#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
-#define NVRAM_SPACE 0x10000
-#define NVRAM_MAX_GPIO_ENTRIES 32
-#define NVRAM_MAX_GPIO_VALUE_LEN 30
-
-#define FLASH_MIN 0x00020000 /* Minimum flash size */
-
-struct nvram_header {
- u32 magic;
- u32 len;
- u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
- u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
- u32 config_ncdl; /* ncdl values for memc */
-};
-
-static char nvram_buf[NVRAM_SPACE];
-static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
-
-static u32 find_nvram_size(void __iomem *end)
-{
- struct nvram_header __iomem *header;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
- header = (struct nvram_header *)(end - nvram_sizes[i]);
- if (header->magic == NVRAM_MAGIC)
- return nvram_sizes[i];
- }
-
- return 0;
-}
-
-/* Probe for NVRAM header */
-static int nvram_find_and_copy(void __iomem *iobase, u32 lim)
-{
- struct nvram_header __iomem *header;
- int i;
- u32 off;
- u32 *src, *dst;
- u32 size;
-
- if (nvram_buf[0]) {
- pr_warn("nvram already initialized\n");
- return -EEXIST;
- }
-
- /* TODO: when nvram is on nand flash check for bad blocks first. */
- off = FLASH_MIN;
- while (off <= lim) {
- /* Windowed flash access */
- size = find_nvram_size(iobase + off);
- if (size) {
- header = (struct nvram_header *)(iobase + off - size);
- goto found;
- }
- off <<= 1;
- }
-
- /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
- header = (struct nvram_header *)(iobase + 4096);
- if (header->magic == NVRAM_MAGIC) {
- size = NVRAM_SPACE;
- goto found;
- }
-
- header = (struct nvram_header *)(iobase + 1024);
- if (header->magic == NVRAM_MAGIC) {
- size = NVRAM_SPACE;
- goto found;
- }
-
- pr_err("no nvram found\n");
- return -ENXIO;
-
-found:
- if (header->len > size)
- pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
- if (header->len > NVRAM_SPACE)
- pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
- header->len, NVRAM_SPACE);
-
- src = (u32 *)header;
- dst = (u32 *)nvram_buf;
- for (i = 0; i < sizeof(struct nvram_header); i += 4)
- *dst++ = __raw_readl(src++);
- for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)
- *dst++ = readl(src++);
-
- return 0;
-}
-
-/*
- * On bcm47xx we need access to the NVRAM very early, so we can't use mtd
- * subsystem to access flash. We can't even use platform device / driver to
- * store memory offset.
- * To handle this we provide following symbol. It's supposed to be called as
- * soon as we get info about flash device, before any NVRAM entry is needed.
- */
-int bcm47xx_nvram_init_from_mem(u32 base, u32 lim)
-{
- void __iomem *iobase;
- int err;
-
- iobase = ioremap_nocache(base, lim);
- if (!iobase)
- return -ENOMEM;
-
- err = nvram_find_and_copy(iobase, lim);
-
- iounmap(iobase);
-
- return err;
-}
-
-static int nvram_init(void)
-{
-#ifdef CONFIG_MTD
- struct mtd_info *mtd;
- struct nvram_header header;
- size_t bytes_read;
- int err;
-
- mtd = get_mtd_device_nm("nvram");
- if (IS_ERR(mtd))
- return -ENODEV;
-
- err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header);
- if (!err && header.magic == NVRAM_MAGIC) {
- u8 *dst = (uint8_t *)nvram_buf;
- size_t len = header.len;
-
- if (header.len > NVRAM_SPACE) {
- pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
- header.len, NVRAM_SPACE);
- len = NVRAM_SPACE;
- }
-
- err = mtd_read(mtd, 0, len, &bytes_read, dst);
- if (err)
- return err;
-
- return 0;
- }
-#endif
-
- return -ENXIO;
-}
-
-int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len)
-{
- char *var, *value, *end, *eq;
- int data_left, err;
-
- if (!name)
- return -EINVAL;
-
- if (!nvram_buf[0]) {
- err = nvram_init();
- if (err)
- return err;
- }
-
- /* Look for name=value and return value */
- var = &nvram_buf[sizeof(struct nvram_header)];
- end = nvram_buf + sizeof(nvram_buf) - 2;
- end[0] = '\0';
- end[1] = '\0';
- for (; *var; var = value + strlen(value) + 1) {
- data_left = end - var;
-
- eq = strnchr(var, data_left, '=');
- if (!eq)
- break;
- value = eq + 1;
- if (eq - var == strlen(name) &&
- strncmp(var, name, eq - var) == 0)
- return snprintf(val, val_len, "%s", value);
- }
- return -ENOENT;
-}
-EXPORT_SYMBOL(bcm47xx_nvram_getenv);
-
-int bcm47xx_nvram_gpio_pin(const char *name)
-{
- int i, err;
- char nvram_var[] = "gpioXX";
- char buf[NVRAM_MAX_GPIO_VALUE_LEN];
-
- /* TODO: Optimize it to don't call getenv so many times */
- for (i = 0; i < NVRAM_MAX_GPIO_ENTRIES; i++) {
- err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
- if (err <= 0)
- continue;
- err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
- if (err <= 0)
- continue;
- if (!strcmp(name, buf))
- return i;
- }
- return -ENOENT;
-}
-EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
diff --git a/kernel/arch/mips/bcm47xx/prom.c b/kernel/arch/mips/bcm47xx/prom.c
index ab698bad6..135a5407f 100644
--- a/kernel/arch/mips/bcm47xx/prom.c
+++ b/kernel/arch/mips/bcm47xx/prom.c
@@ -126,7 +126,7 @@ void __init prom_free_prom_memory(void)
/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
* dropped. Calling it at this stage causes a hang.
*/
-void __cpuinit early_tlb_init(void)
+void early_tlb_init(void)
{
write_c0_pagemask(PM_DEFAULT_MASK);
write_c0_wired(0);
diff --git a/kernel/arch/mips/bcm47xx/setup.c b/kernel/arch/mips/bcm47xx/setup.c
index 82ff9fd2a..6d38948f0 100644
--- a/kernel/arch/mips/bcm47xx/setup.c
+++ b/kernel/arch/mips/bcm47xx/setup.c
@@ -105,11 +105,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
char buf[20];
+ int len, err;
/* Fill boardinfo structure */
memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo));
- bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
+ len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
+ if (len > 0) {
+ err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
+ if (err)
+ pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
+ buf);
+ }
+ if (!iv->boardinfo.vendor)
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+
+ len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+ if (len > 0) {
+ err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
+ if (err)
+ pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
+ buf);
+ }
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom(&iv->sprom, NULL, false);
@@ -206,9 +223,6 @@ void __init bcm47xx_bus_setup(void)
err = bcma_host_soc_init(&bcm47xx_bus.bcma);
if (err)
panic("Failed to initialize BCMA bus (err %d)", err);
-
- bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo,
- NULL);
}
#endif
@@ -266,7 +280,7 @@ static int __init bcm47xx_register_bus_complete(void)
bcm47xx_leds_register();
bcm47xx_workarounds();
- fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
+ fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status, -1);
return 0;
}
device_initcall(bcm47xx_register_bus_complete);
diff --git a/kernel/arch/mips/bcm47xx/sprom.c b/kernel/arch/mips/bcm47xx/sprom.c
index 68ebf2322..a7e569c79 100644
--- a/kernel/arch/mips/bcm47xx/sprom.c
+++ b/kernel/arch/mips/bcm47xx/sprom.c
@@ -60,9 +60,9 @@ static int get_nvram_var(const char *prefix, const char *postfix,
}
#define NVRAM_READ_VAL(type) \
-static void nvram_read_ ## type (const char *prefix, \
- const char *postfix, const char *name, \
- type *val, type allset, bool fallback) \
+static void nvram_read_ ## type(const char *prefix, \
+ const char *postfix, const char *name, \
+ type *val, type allset, bool fallback) \
{ \
char buf[100]; \
int err; \
@@ -200,7 +200,13 @@ static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom,
const char *pre = prefix;
bool fb = fallback;
+ /* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */
+ ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback);
+
ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true);
+ ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb);
+ ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb);
+ ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb);
ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb);
ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true);
ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb);
@@ -409,27 +415,6 @@ static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom,
}
#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */
-static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
- const char *prefix, bool fallback)
-{
- nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback);
- nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
-}
-
-static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix,
- bool fallback)
-{
- nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
- &sprom->leddc_off_time, fallback);
-}
-
-static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
- const char *prefix, bool fallback)
-{
- nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
- &sprom->leddc_off_time, fallback);
-}
-
static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
const char *prefix, bool fallback)
{
@@ -437,7 +422,10 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
int i;
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
- struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+ struct ssb_sprom_core_pwr_info *pwr_info;
+
+ pwr_info = &sprom->core_pwr_info[i];
+
snprintf(postfix, sizeof(postfix), "%i", i);
nvram_read_u8(prefix, postfix, "maxp2ga",
&pwr_info->maxpwr_2g, 0, fallback);
@@ -485,7 +473,10 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
int i;
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
- struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+ struct ssb_sprom_core_pwr_info *pwr_info;
+
+ pwr_info = &sprom->core_pwr_info[i];
+
snprintf(postfix, sizeof(postfix), "%i", i);
nvram_read_u16(prefix, postfix, "pa2gw3a",
&pwr_info->pa_2g[3], 0, fallback);
@@ -528,6 +519,8 @@ static int mac_addr_used = 2;
static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
const char *prefix, bool fallback)
{
+ bool fb = fallback;
+
nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback);
nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
fallback);
@@ -540,14 +533,19 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
fallback);
+ nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb);
+ nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb);
+ nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb);
+
nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
/* The address prefix 00:90:4C is used by Broadcom in their initial
- configuration. When a mac address with the prefix 00:90:4C is used
- all devices from the same series are sharing the same mac address.
- To prevent mac address collisions we replace them with a mac address
- based on the base address. */
+ * configuration. When a mac address with the prefix 00:90:4C is used
+ * all devices from the same series are sharing the same mac address.
+ * To prevent mac address collisions we replace them with a mac address
+ * based on the base address.
+ */
if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
u8 mac[6];
@@ -580,83 +578,44 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
+ /* Entries requiring custom functions */
+ nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
+ if (sprom->revision >= 3)
+ nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+ &sprom->leddc_off_time, fallback);
+
switch (sprom->revision) {
- case 1:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- break;
- case 2:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- break;
- case 3:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- bcm47xx_fill_sprom_r3(sprom, prefix, fallback);
- break;
case 4:
case 5:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
break;
case 8:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
- bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
- break;
case 9:
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
- bcm47xx_fill_sprom_r4589(sprom, prefix, fallback);
bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
break;
- default:
- pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
- sprom->revision);
- sprom->revision = 1;
- bcm47xx_fill_sprom_r1234589(sprom, prefix, fallback);
}
bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
}
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
- const char *prefix)
-{
- nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
- true);
- if (!boardinfo->vendor)
- boardinfo->vendor = SSB_BOARDVENDOR_BCM;
-
- nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
-}
-#endif
-
-#ifdef CONFIG_BCM47XX_BCMA
-void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
- const char *prefix)
-{
- nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
- true);
- if (!boardinfo->vendor)
- boardinfo->vendor = SSB_BOARDVENDOR_BCM;
-
- nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
-}
-#endif
-
#if defined(CONFIG_BCM47XX_SSB)
static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
- if (bus->bustype == SSB_BUSTYPE_PCI) {
+ switch (bus->bustype) {
+ case SSB_BUSTYPE_SSB:
+ bcm47xx_fill_sprom(out, NULL, false);
+ return 0;
+ case SSB_BUSTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix, false);
return 0;
- } else {
+ default:
pr_warn("Unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
@@ -698,33 +657,46 @@ static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size)
static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
{
- char prefix[10];
+ struct bcma_boardinfo *binfo = &bus->boardinfo;
struct bcma_device *core;
+ char buf[10];
+ char *prefix;
+ bool fallback = false;
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
- snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+ snprintf(buf, sizeof(buf), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
- bcm47xx_sprom_apply_prefix_alias(prefix, sizeof(prefix));
- bcm47xx_fill_sprom(out, prefix, false);
- return 0;
+ bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf));
+ prefix = buf;
+ break;
case BCMA_HOSTTYPE_SOC:
memset(out, 0, sizeof(struct ssb_sprom));
core = bcma_find_core(bus, BCMA_CORE_80211);
if (core) {
- snprintf(prefix, sizeof(prefix), "sb/%u/",
+ snprintf(buf, sizeof(buf), "sb/%u/",
core->core_index);
- bcm47xx_fill_sprom(out, prefix, true);
+ prefix = buf;
+ fallback = true;
} else {
- bcm47xx_fill_sprom(out, NULL, false);
+ prefix = NULL;
}
- return 0;
+ break;
default:
pr_warn("Unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
+
+ nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true);
+ if (!binfo->vendor)
+ binfo->vendor = SSB_BOARDVENDOR_BCM;
+ nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true);
+
+ bcm47xx_fill_sprom(out, prefix, fallback);
+
+ return 0;
}
#endif
diff --git a/kernel/arch/mips/bcm63xx/boards/board_bcm963xx.c b/kernel/arch/mips/bcm63xx/boards/board_bcm963xx.c
index 33727e7f0..b2097c0d2 100644
--- a/kernel/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/kernel/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -7,6 +7,8 @@
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -31,7 +33,6 @@
#include <uapi/linux/bcm933xx_hcs.h>
-#define PFX "board_bcm963xx: "
#define HCS_OFFSET_128K 0x20000
@@ -740,7 +741,7 @@ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
return 0;
} else {
- printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+ pr_err("unable to fill SPROM for given bustype\n");
return -EINVAL;
}
}
@@ -784,7 +785,7 @@ void __init board_prom_init(void)
cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
else
strcpy(cfe_version, "unknown");
- printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+ pr_info("CFE version: %s\n", cfe_version);
bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
@@ -808,8 +809,7 @@ void __init board_prom_init(void)
char name[17];
memcpy(name, board_name, 16);
name[16] = 0;
- printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
- name);
+ pr_err("unknown bcm963xx board: %s\n", name);
return;
}
@@ -854,7 +854,7 @@ void __init board_setup(void)
{
if (!board.name[0])
panic("unable to detect bcm963xx board");
- printk(KERN_INFO PFX "board name: %s\n", board.name);
+ pr_info("board name: %s\n", board.name);
/* make sure we're running on expected cpu */
if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
@@ -910,7 +910,7 @@ int __init board_register_devices(void)
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
if (ssb_arch_register_fallback_sprom(
&bcm63xx_get_fallback_sprom) < 0)
- pr_err(PFX "failed to register fallback SPROM\n");
+ pr_err("failed to register fallback SPROM\n");
}
#endif
diff --git a/kernel/arch/mips/bcm63xx/cpu.c b/kernel/arch/mips/bcm63xx/cpu.c
index 307ec8b8e..1c7c3fbfa 100644
--- a/kernel/arch/mips/bcm63xx/cpu.c
+++ b/kernel/arch/mips/bcm63xx/cpu.c
@@ -376,10 +376,10 @@ void __init bcm63xx_cpu_init(void)
bcm63xx_cpu_freq = detect_cpu_clock();
bcm63xx_memory_size = detect_memory_size();
- printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x\n",
- bcm63xx_cpu_id, bcm63xx_cpu_rev);
- printk(KERN_INFO "CPU frequency is %u MHz\n",
- bcm63xx_cpu_freq / 1000000);
- printk(KERN_INFO "%uMB of RAM installed\n",
- bcm63xx_memory_size >> 20);
+ pr_info("Detected Broadcom 0x%04x CPU revision %02x\n",
+ bcm63xx_cpu_id, bcm63xx_cpu_rev);
+ pr_info("CPU frequency is %u MHz\n",
+ bcm63xx_cpu_freq / 1000000);
+ pr_info("%uMB of RAM installed\n",
+ bcm63xx_memory_size >> 20);
}
diff --git a/kernel/arch/mips/bcm63xx/dev-pcmcia.c b/kernel/arch/mips/bcm63xx/dev-pcmcia.c
index a551bab5e..9496cd236 100644
--- a/kernel/arch/mips/bcm63xx/dev-pcmcia.c
+++ b/kernel/arch/mips/bcm63xx/dev-pcmcia.c
@@ -139,6 +139,6 @@ int __init bcm63xx_pcmcia_register(void)
return platform_device_register(&bcm63xx_pcmcia_device);
out_err:
- printk(KERN_ERR "unable to set pcmcia chip select\n");
+ pr_err("unable to set pcmcia chip select\n");
return ret;
}
diff --git a/kernel/arch/mips/bcm63xx/dev-spi.c b/kernel/arch/mips/bcm63xx/dev-spi.c
index ad448e41e..232385441 100644
--- a/kernel/arch/mips/bcm63xx/dev-spi.c
+++ b/kernel/arch/mips/bcm63xx/dev-spi.c
@@ -18,29 +18,6 @@
#include <bcm63xx_dev_spi.h>
#include <bcm63xx_regs.h>
-/*
- * register offsets
- */
-static const unsigned long bcm6348_regs_spi[] = {
- __GEN_SPI_REGS_TABLE(6348)
-};
-
-static const unsigned long bcm6358_regs_spi[] = {
- __GEN_SPI_REGS_TABLE(6358)
-};
-
-const unsigned long *bcm63xx_regs_spi;
-EXPORT_SYMBOL(bcm63xx_regs_spi);
-
-static __init void bcm63xx_spi_regs_init(void)
-{
- if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
- bcm63xx_regs_spi = bcm6348_regs_spi;
- if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
- BCMCPU_IS_6362() || BCMCPU_IS_6368())
- bcm63xx_regs_spi = bcm6358_regs_spi;
-}
-
static struct resource spi_resources[] = {
{
.start = -1, /* filled at runtime */
@@ -53,19 +30,10 @@ static struct resource spi_resources[] = {
},
};
-static struct bcm63xx_spi_pdata spi_pdata = {
- .bus_num = 0,
- .num_chipselect = 8,
-};
-
static struct platform_device bcm63xx_spi_device = {
- .name = "bcm63xx-spi",
.id = -1,
.num_resources = ARRAY_SIZE(spi_resources),
.resource = spi_resources,
- .dev = {
- .platform_data = &spi_pdata,
- },
};
int __init bcm63xx_spi_register(void)
@@ -78,21 +46,15 @@ int __init bcm63xx_spi_register(void)
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
+ bcm63xx_spi_device.name = "bcm6348-spi",
spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
- spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE;
- spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT;
- spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH;
}
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
BCMCPU_IS_6368()) {
+ bcm63xx_spi_device.name = "bcm6358-spi",
spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
- spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
- spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
- spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
}
- bcm63xx_spi_regs_init();
-
return platform_device_register(&bcm63xx_spi_device);
}
diff --git a/kernel/arch/mips/bcm63xx/irq.c b/kernel/arch/mips/bcm63xx/irq.c
index e3e808a6c..c96139097 100644
--- a/kernel/arch/mips/bcm63xx/irq.c
+++ b/kernel/arch/mips/bcm63xx/irq.c
@@ -60,7 +60,7 @@ static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
if (m)
enable &= cpumask_test_cpu(cpu, m);
else if (irqd_affinity_was_set(d))
- enable &= cpumask_test_cpu(cpu, d->affinity);
+ enable &= cpumask_test_cpu(cpu, irq_data_get_affinity_mask(d));
#endif
return enable;
}
@@ -311,7 +311,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
break;
default:
- printk(KERN_ERR "bogus flow type combination given !\n");
+ pr_err("bogus flow type combination given !\n");
return -EINVAL;
}
@@ -365,9 +365,9 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
irqd_set_trigger_type(d, flow_type);
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
- __irq_set_handler_locked(d->irq, handle_level_irq);
+ irq_set_handler_locked(d, handle_level_irq);
else
- __irq_set_handler_locked(d->irq, handle_edge_irq);
+ irq_set_handler_locked(d, handle_edge_irq);
return IRQ_SET_MASK_OK_NOCOPY;
}
diff --git a/kernel/arch/mips/bcm63xx/setup.c b/kernel/arch/mips/bcm63xx/setup.c
index 240fb4ffa..2be9caaa2 100644
--- a/kernel/arch/mips/bcm63xx/setup.c
+++ b/kernel/arch/mips/bcm63xx/setup.c
@@ -24,7 +24,7 @@
void bcm63xx_machine_halt(void)
{
- printk(KERN_INFO "System halted\n");
+ pr_info("System halted\n");
while (1)
;
}
@@ -34,7 +34,7 @@ static void bcm6348_a1_reboot(void)
u32 reg;
/* soft reset all blocks */
- printk(KERN_INFO "soft-resetting all blocks ...\n");
+ pr_info("soft-resetting all blocks ...\n");
reg = bcm_perf_readl(PERF_SOFTRESET_REG);
reg &= ~SOFTRESET_6348_ALL;
bcm_perf_writel(reg, PERF_SOFTRESET_REG);
@@ -46,7 +46,7 @@ static void bcm6348_a1_reboot(void)
mdelay(10);
/* Jump to the power on address. */
- printk(KERN_INFO "jumping to reset vector.\n");
+ pr_info("jumping to reset vector.\n");
/* set high vectors (base at 0xbfc00000 */
set_c0_status(ST0_BEV | ST0_ERL);
/* run uncached in kseg0 */
@@ -110,7 +110,7 @@ void bcm63xx_machine_reboot(void)
if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
bcm6348_a1_reboot();
- printk(KERN_INFO "triggering watchdog soft-reset...\n");
+ pr_info("triggering watchdog soft-reset...\n");
if (BCMCPU_IS_6328()) {
bcm_wdt_writel(1, WDT_SOFTRESET_REG);
} else {
diff --git a/kernel/arch/mips/bcm63xx/timer.c b/kernel/arch/mips/bcm63xx/timer.c
index 5f1135981..2110359c0 100644
--- a/kernel/arch/mips/bcm63xx/timer.c
+++ b/kernel/arch/mips/bcm63xx/timer.c
@@ -195,7 +195,7 @@ int bcm63xx_timer_init(void)
irq = bcm63xx_get_irq_number(IRQ_TIMER);
ret = request_irq(irq, timer_interrupt, 0, "bcm63xx_timer", NULL);
if (ret) {
- printk(KERN_ERR "bcm63xx_timer: failed to register irq\n");
+ pr_err("%s: failed to register irq\n", __func__);
return ret;
}
diff --git a/kernel/arch/mips/bmips/Kconfig b/kernel/arch/mips/bmips/Kconfig
index f35c84c01..e2c4fd682 100644
--- a/kernel/arch/mips/bmips/Kconfig
+++ b/kernel/arch/mips/bmips/Kconfig
@@ -57,6 +57,10 @@ config DT_BCM97425SVMB
bool "BCM97425SVMB"
select BUILTIN_DTB
+config DT_BCM97435SVMB
+ bool "BCM97435SVMB"
+ select BUILTIN_DTB
+
endchoice
endif
diff --git a/kernel/arch/mips/bmips/irq.c b/kernel/arch/mips/bmips/irq.c
index 14552e58f..e7fc6f934 100644
--- a/kernel/arch/mips/bmips/irq.c
+++ b/kernel/arch/mips/bmips/irq.c
@@ -34,5 +34,5 @@ void __init arch_init_irq(void)
irqchip_init();
}
-OF_DECLARE_2(irqchip, mips_cpu_intc, "mti,cpu-interrupt-controller",
+IRQCHIP_DECLARE(mips_cpu_intc, "mti,cpu-interrupt-controller",
mips_cpu_irq_of_init);
diff --git a/kernel/arch/mips/bmips/setup.c b/kernel/arch/mips/bmips/setup.c
index fae800e8b..5b16d2955 100644
--- a/kernel/arch/mips/bmips/setup.c
+++ b/kernel/arch/mips/bmips/setup.c
@@ -149,13 +149,14 @@ void __init plat_mem_setup(void)
/* intended to somewhat resemble ARM; see Documentation/arm/Booting */
if (fw_arg0 == 0 && fw_arg1 == 0xffffffff)
dtb = phys_to_virt(fw_arg2);
+ else if (fw_arg0 == -2) /* UHI interface */
+ dtb = (void *)fw_arg1;
else if (__dtb_start != __dtb_end)
dtb = (void *)__dtb_start;
else
panic("no dtb found");
__dt_setup_arch(dtb);
- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
for (q = bmips_quirk_list; q->quirk_fn; q++) {
if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
diff --git a/kernel/arch/mips/boot/compressed/Makefile b/kernel/arch/mips/boot/compressed/Makefile
index dc91bde10..d5bdee115 100644
--- a/kernel/arch/mips/boot/compressed/Makefile
+++ b/kernel/arch/mips/boot/compressed/Makefile
@@ -78,7 +78,7 @@ endif
vmlinuzobjs-y += $(obj)/piggy.o
-quiet_cmd_zld = LD $@
+quiet_cmd_zld = LD $@
cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@
quiet_cmd_strip = STRIP $@
cmd_strip = $(STRIP) -s $@
diff --git a/kernel/arch/mips/boot/compressed/head.S b/kernel/arch/mips/boot/compressed/head.S
index 409cb483a..c580e853b 100644
--- a/kernel/arch/mips/boot/compressed/head.S
+++ b/kernel/arch/mips/boot/compressed/head.S
@@ -25,6 +25,22 @@ start:
move s2, a2
move s3, a3
+#ifdef CONFIG_MIPS_ZBOOT_APPENDED_DTB
+ PTR_LA t0, __appended_dtb
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ li t1, 0xd00dfeed
+#else
+ li t1, 0xedfe0dd0
+#endif
+ lw t2, (t0)
+ bne t1, t2, not_found
+ nop
+
+ move s1, t0
+ PTR_LI s0, -2
+not_found:
+#endif
+
/* Clear BSS */
PTR_LA a0, _edata
PTR_LA a2, _end
diff --git a/kernel/arch/mips/boot/compressed/ld.script b/kernel/arch/mips/boot/compressed/ld.script
index 5a33409c7..2ed08fbef 100644
--- a/kernel/arch/mips/boot/compressed/ld.script
+++ b/kernel/arch/mips/boot/compressed/ld.script
@@ -29,8 +29,12 @@ SECTIONS
*(.image)
__image_end = .;
CONSTRUCTORS
+ . = ALIGN(16);
}
- . = ALIGN(16);
+ __appended_dtb = .;
+ /* leave space for appended DTB */
+ . += 0x100000;
+
_edata = .;
/* End of data section */
diff --git a/kernel/arch/mips/boot/compressed/uart-16550.c b/kernel/arch/mips/boot/compressed/uart-16550.c
index 237494b7a..408799a83 100644
--- a/kernel/arch/mips/boot/compressed/uart-16550.c
+++ b/kernel/arch/mips/boot/compressed/uart-16550.c
@@ -7,7 +7,7 @@
#include <asm/addrspace.h>
-#if defined(CONFIG_MACH_LOONGSON) || defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MACH_LOONGSON64) || defined(CONFIG_MIPS_MALTA)
#define UART_BASE 0x1fd003f8
#define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset))
#endif
diff --git a/kernel/arch/mips/boot/dts/Makefile b/kernel/arch/mips/boot/dts/Makefile
index 5d95e4bd7..a0bf516ec 100644
--- a/kernel/arch/mips/boot/dts/Makefile
+++ b/kernel/arch/mips/boot/dts/Makefile
@@ -1,12 +1,18 @@
dts-dirs += brcm
dts-dirs += cavium-octeon
+dts-dirs += ingenic
dts-dirs += lantiq
dts-dirs += mti
dts-dirs += netlogic
+dts-dirs += qca
dts-dirs += ralink
+dts-dirs += xilfpga
obj-y := $(addsuffix /, $(dts-dirs))
+dtstree := $(srctree)/$(src)
+dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts)))
+
always := $(dtb-y)
subdir-y := $(dts-dirs)
clean-files := *.dtb *.dtb.S
diff --git a/kernel/arch/mips/boot/dts/brcm/Makefile b/kernel/arch/mips/boot/dts/brcm/Makefile
index 1c8353bfe..eabeb603e 100644
--- a/kernel/arch/mips/boot/dts/brcm/Makefile
+++ b/kernel/arch/mips/boot/dts/brcm/Makefile
@@ -9,6 +9,20 @@ dtb-$(CONFIG_DT_BCM97360SVMB) += bcm97360svmb.dtb
dtb-$(CONFIG_DT_BCM97362SVMB) += bcm97362svmb.dtb
dtb-$(CONFIG_DT_BCM97420C) += bcm97420c.dtb
dtb-$(CONFIG_DT_BCM97425SVMB) += bcm97425svmb.dtb
+dtb-$(CONFIG_DT_BCM97435SVMB) += bcm97435svmb.dtb
+
+dtb-$(CONFIG_DT_NONE) += \
+ bcm93384wvg.dtb \
+ bcm93384wvg_viper.dtb \
+ bcm96368mvwg.dtb \
+ bcm9ejtagprb.dtb \
+ bcm97125cbmb.dtb \
+ bcm97346dbsmb.dtb \
+ bcm97358svmb.dtb \
+ bcm97360svmb.dtb \
+ bcm97362svmb.dtb \
+ bcm97420c.dtb \
+ bcm97425svmb.dtb
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7346.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7346.dtsi
index 1f30728a3..d4bf52cfc 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm7346.dtsi
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7346.dtsi
@@ -24,6 +24,8 @@
aliases {
uart0 = &uart0;
+ uart1 = &uart1;
+ uart2 = &uart2;
};
cpu_intc: cpu_intc {
@@ -85,14 +87,32 @@
compatible = "brcm,bcm7120-l2-intc";
reg = <0x406780 0x8>;
- brcm,int-map-mask = <0x44>;
+ brcm,int-map-mask = <0x44>, <0xf000000>;
brcm,int-fwd-mask = <0x70000>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&periph_intc>;
- interrupts = <59>;
+ interrupts = <59>, <57>;
+ interrupt-names = "upg_main", "upg_bsc";
+ };
+
+ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+ compatible = "brcm,bcm7120-l2-intc";
+ reg = <0x408b80 0x8>;
+
+ brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+ brcm,int-fwd-mask = <0>;
+ brcm,irq-can-wake;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&periph_intc>;
+ interrupts = <60>, <58>, <62>;
+ interrupt-names = "upg_main_aon", "upg_bsc_aon",
+ "upg_spi";
};
sun_top_ctrl: syscon@404000 {
@@ -118,6 +138,80 @@
status = "disabled";
};
+ uart1: serial@406940 {
+ compatible = "ns16550a";
+ reg = <0x406940 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <65>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart2: serial@406980 {
+ compatible = "ns16550a";
+ reg = <0x406980 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <66>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ bsca: i2c@406200 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406200 0x58>;
+ interrupts = <24>;
+ interrupt-names = "upg_bsca";
+ status = "disabled";
+ };
+
+ bscb: i2c@406280 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406280 0x58>;
+ interrupts = <25>;
+ interrupt-names = "upg_bscb";
+ status = "disabled";
+ };
+
+ bscc: i2c@406300 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406300 0x58>;
+ interrupts = <26>;
+ interrupt-names = "upg_bscc";
+ status = "disabled";
+ };
+
+ bscd: i2c@406380 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406380 0x58>;
+ interrupts = <27>;
+ interrupt-names = "upg_bscd";
+ status = "disabled";
+ };
+
+ bsce: i2c@408980 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_aon_irq0_intc>;
+ reg = <0x408980 0x58>;
+ interrupts = <27>;
+ interrupt-names = "upg_bsce";
+ status = "disabled";
+ };
+
enet0: ethernet@430000 {
phy-mode = "internal";
phy-handle = <&phy1>;
@@ -220,5 +314,47 @@
interrupts = <76>;
status = "disabled";
};
+
+ sata: sata@181000 {
+ compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+ reg-names = "ahci", "top-ctrl";
+ reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ brcm,broken-ncq;
+ brcm,broken-phy;
+ status = "disabled";
+
+ sata0: sata-port@0 {
+ reg = <0>;
+ phys = <&sata_phy0>;
+ };
+
+ sata1: sata-port@1 {
+ reg = <1>;
+ phys = <&sata_phy1>;
+ };
+ };
+
+ sata_phy: sata-phy@1800000 {
+ compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+ reg = <0x180100 0x0eff>;
+ reg-names = "phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata_phy0: sata-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ sata_phy1: sata-phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+ };
};
};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7358.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7358.dtsi
index 2c2aa9368..8e2501694 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm7358.dtsi
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7358.dtsi
@@ -18,6 +18,8 @@
aliases {
uart0 = &uart0;
+ uart1 = &uart1;
+ uart2 = &uart2;
};
cpu_intc: cpu_intc {
@@ -79,14 +81,32 @@
compatible = "brcm,bcm7120-l2-intc";
reg = <0x406600 0x8>;
- brcm,int-map-mask = <0x44>;
+ brcm,int-map-mask = <0x44>, <0x7000000>;
brcm,int-fwd-mask = <0x70000>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&periph_intc>;
- interrupts = <56>;
+ interrupts = <56>, <54>;
+ interrupt-names = "upg_main", "upg_bsc";
+ };
+
+ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+ compatible = "brcm,bcm7120-l2-intc";
+ reg = <0x408b80 0x8>;
+
+ brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+ brcm,int-fwd-mask = <0>;
+ brcm,irq-can-wake;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&periph_intc>;
+ interrupts = <57>, <55>, <59>;
+ interrupt-names = "upg_main_aon", "upg_bsc_aon",
+ "upg_spi";
};
sun_top_ctrl: syscon@404000 {
@@ -112,6 +132,70 @@
status = "disabled";
};
+ uart1: serial@406840 {
+ compatible = "ns16550a";
+ reg = <0x406840 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <62>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart2: serial@406880 {
+ compatible = "ns16550a";
+ reg = <0x406880 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <63>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ bsca: i2c@406200 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406200 0x58>;
+ interrupts = <24>;
+ interrupt-names = "upg_bsca";
+ status = "disabled";
+ };
+
+ bscb: i2c@406280 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406280 0x58>;
+ interrupts = <25>;
+ interrupt-names = "upg_bscb";
+ status = "disabled";
+ };
+
+ bscc: i2c@406300 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406300 0x58>;
+ interrupts = <26>;
+ interrupt-names = "upg_bscc";
+ status = "disabled";
+ };
+
+ bscd: i2c@408980 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_aon_irq0_intc>;
+ reg = <0x408980 0x58>;
+ interrupts = <27>;
+ interrupt-names = "upg_bscd";
+ status = "disabled";
+ };
+
enet0: ethernet@430000 {
phy-mode = "internal";
phy-handle = <&phy1>;
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7360.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7360.dtsi
index f23b0aed2..7e5f76040 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm7360.dtsi
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7360.dtsi
@@ -18,6 +18,8 @@
aliases {
uart0 = &uart0;
+ uart1 = &uart1;
+ uart2 = &uart2;
};
cpu_intc: cpu_intc {
@@ -79,14 +81,32 @@
compatible = "brcm,bcm7120-l2-intc";
reg = <0x406600 0x8>;
- brcm,int-map-mask = <0x44>;
+ brcm,int-map-mask = <0x44>, <0x7000000>;
brcm,int-fwd-mask = <0x70000>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&periph_intc>;
- interrupts = <56>;
+ interrupts = <56>, <54>;
+ interrupt-names = "upg_main", "upg_bsc";
+ };
+
+ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+ compatible = "brcm,bcm7120-l2-intc";
+ reg = <0x408b80 0x8>;
+
+ brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+ brcm,int-fwd-mask = <0>;
+ brcm,irq-can-wake;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&periph_intc>;
+ interrupts = <57>, <55>, <59>;
+ interrupt-names = "upg_main_aon", "upg_bsc_aon",
+ "upg_spi";
};
sun_top_ctrl: syscon@404000 {
@@ -112,6 +132,70 @@
status = "disabled";
};
+ uart1: serial@406840 {
+ compatible = "ns16550a";
+ reg = <0x406840 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <62>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart2: serial@406880 {
+ compatible = "ns16550a";
+ reg = <0x406880 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <63>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ bsca: i2c@406200 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406200 0x58>;
+ interrupts = <24>;
+ interrupt-names = "upg_bsca";
+ status = "disabled";
+ };
+
+ bscb: i2c@406280 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406280 0x58>;
+ interrupts = <25>;
+ interrupt-names = "upg_bscb";
+ status = "disabled";
+ };
+
+ bscc: i2c@406300 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406300 0x58>;
+ interrupts = <26>;
+ interrupt-names = "upg_bscc";
+ status = "disabled";
+ };
+
+ bscd: i2c@408980 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_aon_irq0_intc>;
+ reg = <0x408980 0x58>;
+ interrupts = <27>;
+ interrupt-names = "upg_bscd";
+ status = "disabled";
+ };
+
enet0: ethernet@430000 {
phy-mode = "internal";
phy-handle = <&phy1>;
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7362.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7362.dtsi
index da99db665..c739ea77a 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm7362.dtsi
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7362.dtsi
@@ -24,6 +24,8 @@
aliases {
uart0 = &uart0;
+ uart1 = &uart1;
+ uart2 = &uart2;
};
cpu_intc: cpu_intc {
@@ -85,14 +87,32 @@
compatible = "brcm,bcm7120-l2-intc";
reg = <0x406600 0x8>;
- brcm,int-map-mask = <0x44>;
+ brcm,int-map-mask = <0x44>, <0x7000000>;
brcm,int-fwd-mask = <0x70000>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&periph_intc>;
- interrupts = <56>;
+ interrupts = <56>, <54>;
+ interrupt-names = "upg_main", "upg_bsc";
+ };
+
+ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+ compatible = "brcm,bcm7120-l2-intc";
+ reg = <0x408b80 0x8>;
+
+ brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+ brcm,int-fwd-mask = <0>;
+ brcm,irq-can-wake;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&periph_intc>;
+ interrupts = <57>, <55>, <59>;
+ interrupt-names = "upg_main_aon", "upg_bsc_aon",
+ "upg_spi";
};
sun_top_ctrl: syscon@404000 {
@@ -118,6 +138,60 @@
status = "disabled";
};
+ uart1: serial@406840 {
+ compatible = "ns16550a";
+ reg = <0x406840 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <62>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ uart2: serial@406880 {
+ compatible = "ns16550a";
+ reg = <0x406880 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <63>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ bsca: i2c@406200 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406200 0x58>;
+ interrupts = <24>;
+ interrupt-names = "upg_bsca";
+ status = "disabled";
+ };
+
+ bscb: i2c@406280 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_irq0_intc>;
+ reg = <0x406280 0x58>;
+ interrupts = <25>;
+ interrupt-names = "upg_bscb";
+ status = "disabled";
+ };
+
+ bscd: i2c@408980 {
+ clock-frequency = <390000>;
+ compatible = "brcm,brcmstb-i2c";
+ interrupt-parent = <&upg_aon_irq0_intc>;
+ reg = <0x408980 0x58>;
+ interrupts = <27>;
+ interrupt-names = "upg_bscd";
+ status = "disabled";
+ };
+
enet0: ethernet@430000 {
phy-mode = "internal";
phy-handle = <&phy1>;
@@ -163,5 +237,47 @@
interrupts = <66>;
status = "disabled";
};
+
+ sata: sata@181000 {
+ compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+ reg-names = "ahci", "top-ctrl";
+ reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <86>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ brcm,broken-ncq;
+ brcm,broken-phy;
+ status = "disabled";
+
+ sata0: sata-port@0 {
+ reg = <0>;
+ phys = <&sata_phy0>;
+ };
+
+ sata1: sata-port@1 {
+ reg = <1>;
+ phys = <&sata_phy1>;
+ };
+ };
+
+ sata_phy: sata-phy@1800000 {
+ compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+ reg = <0x180100 0x0eff>;
+ reg-names = "phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata_phy0: sata-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ sata_phy1: sata-phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+ };
};
};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7425.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7425.dtsi
index 5b660b617..e24d41ab4 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm7425.dtsi
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7425.dtsi
@@ -221,5 +221,47 @@
interrupts = <73>;
status = "disabled";
};
+
+ sata: sata@181000 {
+ compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+ reg-names = "ahci", "top-ctrl";
+ reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ brcm,broken-ncq;
+ brcm,broken-phy;
+ status = "disabled";
+
+ sata0: sata-port@0 {
+ reg = <0>;
+ phys = <&sata_phy0>;
+ };
+
+ sata1: sata-port@1 {
+ reg = <1>;
+ phys = <&sata_phy1>;
+ };
+ };
+
+ sata_phy: sata-phy@1800000 {
+ compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+ reg = <0x180100 0x0eff>;
+ reg-names = "phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ sata_phy0: sata-phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ sata_phy1: sata-phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+ };
};
};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm7435.dtsi b/kernel/arch/mips/boot/dts/brcm/bcm7435.dtsi
new file mode 100644
index 000000000..8b9432cc0
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/brcm/bcm7435.dtsi
@@ -0,0 +1,239 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "brcm,bcm7435";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mips-hpt-frequency = <163125000>;
+
+ cpu@0 {
+ compatible = "brcm,bmips5200";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "brcm,bmips5200";
+ device_type = "cpu";
+ reg = <1>;
+ };
+
+ cpu@2 {
+ compatible = "brcm,bmips5200";
+ device_type = "cpu";
+ reg = <2>;
+ };
+
+ cpu@3 {
+ compatible = "brcm,bmips5200";
+ device_type = "cpu";
+ reg = <3>;
+ };
+ };
+
+ aliases {
+ uart0 = &uart0;
+ };
+
+ cpu_intc: cpu_intc {
+ #address-cells = <0>;
+ compatible = "mti,cpu-interrupt-controller";
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ clocks {
+ uart_clk: uart_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <81000000>;
+ };
+ };
+
+ rdb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ compatible = "simple-bus";
+ ranges = <0 0x10000000 0x01000000>;
+
+ periph_intc: periph_intc@41b500 {
+ compatible = "brcm,bcm7038-l1-intc";
+ reg = <0x41b500 0x40>, <0x41b600 0x40>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpu_intc>;
+ interrupts = <2>, <3>;
+ };
+
+ sun_l2_intc: sun_l2_intc@403000 {
+ compatible = "brcm,l2-intc";
+ reg = <0x403000 0x30>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <52>;
+ };
+
+ gisb-arb@400000 {
+ compatible = "brcm,bcm7400-gisb-arb";
+ reg = <0x400000 0xdc>;
+ native-endian;
+ interrupt-parent = <&sun_l2_intc>;
+ interrupts = <0>, <2>;
+ brcm,gisb-arb-master-mask = <0xf77f>;
+ brcm,gisb-arb-master-names = "ssp_0", "cpu_0", "webcpu_0",
+ "pcie_0", "bsp_0",
+ "rdc_0", "raaga_0",
+ "avd_1", "jtag_0",
+ "svd_0", "vice_0",
+ "vice_1", "raaga_1",
+ "scpu";
+ };
+
+ upg_irq0_intc: upg_irq0_intc@406780 {
+ compatible = "brcm,bcm7120-l2-intc";
+ reg = <0x406780 0x8>;
+
+ brcm,int-map-mask = <0x44>;
+ brcm,int-fwd-mask = <0x70000>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&periph_intc>;
+ interrupts = <60>;
+ };
+
+ sun_top_ctrl: syscon@404000 {
+ compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
+ reg = <0x404000 0x51c>;
+ little-endian;
+ };
+
+ reboot {
+ compatible = "brcm,brcmstb-reboot";
+ syscon = <&sun_top_ctrl 0x304 0x308>;
+ };
+
+ uart0: serial@406b00 {
+ compatible = "ns16550a";
+ reg = <0x406b00 0x20>;
+ reg-io-width = <0x4>;
+ reg-shift = <0x2>;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <66>;
+ clocks = <&uart_clk>;
+ status = "disabled";
+ };
+
+ enet0: ethernet@b80000 {
+ phy-mode = "internal";
+ phy-handle = <&phy1>;
+ mac-address = [ 00 10 18 36 23 1a ];
+ compatible = "brcm,genet-v3";
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ reg = <0xb80000 0x11c88>;
+ interrupts = <17>, <18>;
+ interrupt-parent = <&periph_intc>;
+ status = "disabled";
+
+ mdio@e14 {
+ compatible = "brcm,genet-mdio-v3";
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ reg = <0xe14 0x8>;
+
+ phy1: ethernet-phy@1 {
+ max-speed = <100>;
+ reg = <0x1>;
+ compatible = "brcm,40nm-ephy",
+ "ethernet-phy-ieee802.3-c22";
+ };
+ };
+ };
+
+ ehci0: usb@480300 {
+ compatible = "brcm,bcm7435-ehci", "generic-ehci";
+ reg = <0x480300 0x100>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <70>;
+ status = "disabled";
+ };
+
+ ohci0: usb@480400 {
+ compatible = "brcm,bcm7435-ohci", "generic-ohci";
+ reg = <0x480400 0x100>;
+ native-endian;
+ no-big-frame-no;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <72>;
+ status = "disabled";
+ };
+
+ ehci1: usb@480500 {
+ compatible = "brcm,bcm7435-ehci", "generic-ehci";
+ reg = <0x480500 0x100>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <71>;
+ status = "disabled";
+ };
+
+ ohci1: usb@480600 {
+ compatible = "brcm,bcm7435-ohci", "generic-ohci";
+ reg = <0x480600 0x100>;
+ native-endian;
+ no-big-frame-no;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <73>;
+ status = "disabled";
+ };
+
+ ehci2: usb@490300 {
+ compatible = "brcm,bcm7435-ehci", "generic-ehci";
+ reg = <0x490300 0x100>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <75>;
+ status = "disabled";
+ };
+
+ ohci2: usb@490400 {
+ compatible = "brcm,bcm7435-ohci", "generic-ohci";
+ reg = <0x490400 0x100>;
+ native-endian;
+ no-big-frame-no;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <77>;
+ status = "disabled";
+ };
+
+ ehci3: usb@490500 {
+ compatible = "brcm,bcm7435-ehci", "generic-ehci";
+ reg = <0x490500 0x100>;
+ native-endian;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <76>;
+ status = "disabled";
+ };
+
+ ohci3: usb@490600 {
+ compatible = "brcm,bcm7435-ohci", "generic-ohci";
+ reg = <0x490600 0x100>;
+ native-endian;
+ no-big-frame-no;
+ interrupt-parent = <&periph_intc>;
+ interrupts = <78>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts b/kernel/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts
index 70f196d89..d3d28816a 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts
+++ b/kernel/arch/mips/boot/dts/brcm/bcm97346dbsmb.dts
@@ -21,6 +21,34 @@
status = "okay";
};
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&bsca {
+ status = "okay";
+};
+
+&bscb {
+ status = "okay";
+};
+
+&bscc {
+ status = "okay";
+};
+
+&bscd {
+ status = "okay";
+};
+
+&bsce {
+ status = "okay";
+};
+
&enet0 {
status = "okay";
};
@@ -56,3 +84,11 @@
&ohci3 {
status = "okay";
};
+
+&sata {
+ status = "okay";
+};
+
+&sata_phy {
+ status = "okay";
+};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm97358svmb.dts b/kernel/arch/mips/boot/dts/brcm/bcm97358svmb.dts
index d18e6d947..02ce6b429 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm97358svmb.dts
+++ b/kernel/arch/mips/boot/dts/brcm/bcm97358svmb.dts
@@ -21,6 +21,30 @@
status = "okay";
};
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&bsca {
+ status = "okay";
+};
+
+&bscb {
+ status = "okay";
+};
+
+&bscc {
+ status = "okay";
+};
+
+&bscd {
+ status = "okay";
+};
+
&enet0 {
status = "okay";
};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/kernel/arch/mips/boot/dts/brcm/bcm97360svmb.dts
index 4fe515500..d48462e09 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm97360svmb.dts
+++ b/kernel/arch/mips/boot/dts/brcm/bcm97360svmb.dts
@@ -21,6 +21,30 @@
status = "okay";
};
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&bsca {
+ status = "okay";
+};
+
+&bscb {
+ status = "okay";
+};
+
+&bscc {
+ status = "okay";
+};
+
+&bscd {
+ status = "okay";
+};
+
&enet0 {
status = "okay";
};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm97362svmb.dts b/kernel/arch/mips/boot/dts/brcm/bcm97362svmb.dts
index b7b88e5dc..3cfcaebe7 100644
--- a/kernel/arch/mips/boot/dts/brcm/bcm97362svmb.dts
+++ b/kernel/arch/mips/boot/dts/brcm/bcm97362svmb.dts
@@ -21,6 +21,26 @@
status = "okay";
};
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&bsca {
+ status = "okay";
+};
+
+&bscb {
+ status = "okay";
+};
+
+&bscd {
+ status = "okay";
+};
+
&enet0 {
status = "okay";
};
@@ -32,3 +52,11 @@
&ohci0 {
status = "okay";
};
+
+&sata {
+ status = "okay";
+};
+
+&sata_phy {
+ status = "okay";
+};
diff --git a/kernel/arch/mips/boot/dts/brcm/bcm97435svmb.dts b/kernel/arch/mips/boot/dts/brcm/bcm97435svmb.dts
new file mode 100644
index 000000000..1df088183
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/brcm/bcm97435svmb.dts
@@ -0,0 +1,60 @@
+/dts-v1/;
+
+/include/ "bcm7435.dtsi"
+
+/ {
+ compatible = "brcm,bcm97435svmb", "brcm,bcm7435";
+ model = "Broadcom BCM97435SVMB";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>,
+ <0x20000000 0x30000000>,
+ <0x90000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200 maxcpus=1";
+ stdout-path = &uart0;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&enet0 {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
diff --git a/kernel/arch/mips/boot/dts/ingenic/Makefile b/kernel/arch/mips/boot/dts/ingenic/Makefile
new file mode 100644
index 000000000..f2b864f07
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/ingenic/Makefile
@@ -0,0 +1,10 @@
+dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
+dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb
+
+obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj- += dummy.o
+
+always := $(dtb-y)
+clean-files := *.dtb *.dtb.S
diff --git a/kernel/arch/mips/boot/dts/ingenic/ci20.dts b/kernel/arch/mips/boot/dts/ingenic/ci20.dts
new file mode 100644
index 000000000..9fcb9e7d1
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/ingenic/ci20.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+ compatible = "img,ci20", "ingenic,jz4780";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = &uart4;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000
+ 0x30000000 0x30000000>;
+ };
+};
+
+&ext {
+ clock-frequency = <48000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
diff --git a/kernel/arch/mips/boot/dts/ingenic/jz4740.dtsi b/kernel/arch/mips/boot/dts/ingenic/jz4740.dtsi
new file mode 100644
index 000000000..8b2437cd0
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -0,0 +1,68 @@
+#include <dt-bindings/clock/jz4740-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4740";
+
+ cpuintc: interrupt-controller@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4740-intc";
+ reg = <0x10001000 0x14>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4740-cgu@10000000 {
+ compatible = "ingenic,jz4740-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10030000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <9>;
+
+ clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+ clock-names = "baud", "module";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0x10031000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <8>;
+
+ clocks = <&ext>, <&cgu JZ4740_CLK_UART1>;
+ clock-names = "baud", "module";
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/ingenic/jz4780.dtsi b/kernel/arch/mips/boot/dts/ingenic/jz4780.dtsi
new file mode 100644
index 000000000..65389f602
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/ingenic/jz4780.dtsi
@@ -0,0 +1,111 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4780";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4780-intc";
+ reg = <0x10001000 0x50>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4780-cgu@10000000 {
+ compatible = "ingenic,jz4780-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10030000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <51>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10031000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <50>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10032000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <49>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10033000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <48>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart4: serial@10034000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10034000 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <34>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/ingenic/qi_lb60.dts b/kernel/arch/mips/boot/dts/ingenic/qi_lb60.dts
new file mode 100644
index 000000000..2414d63ae
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+#include "jz4740.dtsi"
+
+/ {
+ compatible = "qi,lb60", "ingenic,jz4740";
+
+ chosen {
+ stdout-path = &uart0;
+ };
+};
+
+&ext {
+ clock-frequency = <12000000>;
+};
diff --git a/kernel/arch/mips/boot/dts/mti/Makefile b/kernel/arch/mips/boot/dts/mti/Makefile
index ef1f3dbed..144d776cc 100644
--- a/kernel/arch/mips/boot/dts/mti/Makefile
+++ b/kernel/arch/mips/boot/dts/mti/Makefile
@@ -1,3 +1,4 @@
+dtb-$(CONFIG_MIPS_MALTA) += malta.dtb
dtb-$(CONFIG_MIPS_SEAD3) += sead3.dtb
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/kernel/arch/mips/boot/dts/mti/malta.dts b/kernel/arch/mips/boot/dts/mti/malta.dts
new file mode 100644
index 000000000..b18c46637
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/mti/malta.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/memreserve/ 0x00000000 0x00001000; /* YAMON exception vectors */
+/memreserve/ 0x00001000 0x000ef000; /* YAMON */
+/memreserve/ 0x000f0000 0x00010000; /* PIIX4 ISA memory */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mti,malta";
+};
diff --git a/kernel/arch/mips/boot/dts/netlogic/xlp_evp.dts b/kernel/arch/mips/boot/dts/netlogic/xlp_evp.dts
index 89ad04808..ec16ec2d8 100644
--- a/kernel/arch/mips/boot/dts/netlogic/xlp_evp.dts
+++ b/kernel/arch/mips/boot/dts/netlogic/xlp_evp.dts
@@ -110,6 +110,18 @@
read-only;
};
};
+
+ gpio: xlp_gpio@34100 {
+ compatible = "netlogic,xlp832-gpio";
+ reg = <0 0x34100 0x1000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pic>;
+ interrupts = <39>;
+ interrupt-controller;
+ };
};
chosen {
diff --git a/kernel/arch/mips/boot/dts/netlogic/xlp_fvp.dts b/kernel/arch/mips/boot/dts/netlogic/xlp_fvp.dts
index 63e62b7bd..4bcebe641 100644
--- a/kernel/arch/mips/boot/dts/netlogic/xlp_fvp.dts
+++ b/kernel/arch/mips/boot/dts/netlogic/xlp_fvp.dts
@@ -110,6 +110,18 @@
read-only;
};
};
+
+ gpio: xlp_gpio@34100 {
+ compatible = "netlogic,xlp208-gpio";
+ reg = <0 0x34100 0x1000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pic>;
+ interrupts = <39>;
+ interrupt-controller;
+ };
};
chosen {
diff --git a/kernel/arch/mips/boot/dts/netlogic/xlp_gvp.dts b/kernel/arch/mips/boot/dts/netlogic/xlp_gvp.dts
index bb4ecd1d4..b3ccb82ad 100644
--- a/kernel/arch/mips/boot/dts/netlogic/xlp_gvp.dts
+++ b/kernel/arch/mips/boot/dts/netlogic/xlp_gvp.dts
@@ -69,6 +69,17 @@
};
};
+ gpio: xlp_gpio@114100 {
+ compatible = "netlogic,xlp980-gpio";
+ reg = <0 0x114100 0x1000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pic>;
+ interrupts = <39>;
+ interrupt-controller;
+ };
};
chosen {
diff --git a/kernel/arch/mips/boot/dts/netlogic/xlp_rvp.dts b/kernel/arch/mips/boot/dts/netlogic/xlp_rvp.dts
index 7188aed2e..3783639a3 100644
--- a/kernel/arch/mips/boot/dts/netlogic/xlp_rvp.dts
+++ b/kernel/arch/mips/boot/dts/netlogic/xlp_rvp.dts
@@ -69,6 +69,17 @@
};
};
+ gpio: xlp_gpio@114100 {
+ compatible = "netlogic,xlp532-gpio";
+ reg = <0 0x114100 0x1000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pic>;
+ interrupts = <39>;
+ interrupt-controller;
+ };
};
chosen {
diff --git a/kernel/arch/mips/boot/dts/netlogic/xlp_svp.dts b/kernel/arch/mips/boot/dts/netlogic/xlp_svp.dts
index 1ebd00eda..44d6640c1 100644
--- a/kernel/arch/mips/boot/dts/netlogic/xlp_svp.dts
+++ b/kernel/arch/mips/boot/dts/netlogic/xlp_svp.dts
@@ -110,6 +110,18 @@
read-only;
};
};
+
+ gpio: xlp_gpio@34100 {
+ compatible = "netlogic,xlp316-gpio";
+ reg = <0 0x34100 0x1000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ #interrupt-cells = <2>;
+ interrupt-parent = <&pic>;
+ interrupts = <39>;
+ interrupt-controller;
+ };
};
chosen {
diff --git a/kernel/arch/mips/boot/dts/qca/Makefile b/kernel/arch/mips/boot/dts/qca/Makefile
new file mode 100644
index 000000000..2d61455d5
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/qca/Makefile
@@ -0,0 +1,11 @@
+# All DTBs
+dtb-$(CONFIG_ATH79) += ar9132_tl_wr1043nd_v1.dtb
+
+# Select a DTB to build in the kernel
+obj-$(CONFIG_DTB_TL_WR1043ND_V1) += ar9132_tl_wr1043nd_v1.dtb.o
+
+# Force kbuild to make empty built-in.o if necessary
+obj- += dummy.o
+
+always := $(dtb-y)
+clean-files := *.dtb *.dtb.S
diff --git a/kernel/arch/mips/boot/dts/qca/ar9132.dtsi b/kernel/arch/mips/boot/dts/qca/ar9132.dtsi
new file mode 100644
index 000000000..13d043949
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/qca/ar9132.dtsi
@@ -0,0 +1,141 @@
+/ {
+ compatible = "qca,ar9132";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "mips,mips24Kc";
+ reg = <0>;
+ };
+ };
+
+ cpuintc: interrupt-controller {
+ compatible = "qca,ar9132-cpu-intc", "qca,ar7100-cpu-intc";
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ qca,ddr-wb-channel-interrupts = <2>, <3>, <4>, <5>;
+ qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>,
+ <&ddr_ctrl 0>, <&ddr_ctrl 1>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ ranges;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+
+ apb {
+ compatible = "simple-bus";
+ ranges;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&miscintc>;
+
+ ddr_ctrl: memory-controller@18000000 {
+ compatible = "qca,ar9132-ddr-controller",
+ "qca,ar7240-ddr-controller";
+ reg = <0x18000000 0x100>;
+
+ #qca,ddr-wb-channel-cells = <1>;
+ };
+
+ uart@18020000 {
+ compatible = "ns8250";
+ reg = <0x18020000 0x20>;
+ interrupts = <3>;
+
+ clocks = <&pll 2>;
+ clock-names = "uart";
+
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ no-loopback-test;
+
+ status = "disabled";
+ };
+
+ gpio: gpio@18040000 {
+ compatible = "qca,ar9132-gpio",
+ "qca,ar7100-gpio";
+ reg = <0x18040000 0x30>;
+ interrupts = <2>;
+
+ ngpios = <22>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pll: pll-controller@18050000 {
+ compatible = "qca,ar9132-ppl",
+ "qca,ar9130-pll";
+ reg = <0x18050000 0x20>;
+
+ clock-names = "ref";
+ /* The board must provides the ref clock */
+
+ #clock-cells = <1>;
+ clock-output-names = "cpu", "ddr", "ahb";
+ };
+
+ wdt@18060008 {
+ compatible = "qca,ar7130-wdt";
+ reg = <0x18060008 0x8>;
+
+ interrupts = <4>;
+
+ clocks = <&pll 2>;
+ clock-names = "wdt";
+ };
+
+ miscintc: interrupt-controller@18060010 {
+ compatible = "qca,ar9132-misc-intc",
+ "qca,ar7100-misc-intc";
+ reg = <0x18060010 0x8>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <6>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ rst: reset-controller@1806001c {
+ compatible = "qca,ar9132-reset",
+ "qca,ar7100-reset";
+ reg = <0x1806001c 0x4>;
+
+ #reset-cells = <1>;
+ };
+ };
+
+ spi@1f000000 {
+ compatible = "qca,ar9132-spi", "qca,ar7100-spi";
+ reg = <0x1f000000 0x10>;
+
+ clocks = <&pll 2>;
+ clock-names = "ahb";
+
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts b/kernel/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts
new file mode 100644
index 000000000..003015ab3
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts
@@ -0,0 +1,112 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9132.dtsi"
+
+/ {
+ compatible = "tplink,tl-wr1043nd-v1", "qca,ar9132";
+ model = "TP-Link TL-WR1043ND Version 1";
+
+ alias {
+ serial0 = "/ahb/apb/uart@18020000";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x2000000>;
+ };
+
+ extosc: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <40000000>;
+ };
+
+ ahb {
+ apb {
+ uart@18020000 {
+ status = "okay";
+ };
+
+ pll-controller@18050000 {
+ clocks = <&extosc>;
+ };
+ };
+
+ spi@1f000000 {
+ status = "okay";
+ num-cs = <1>;
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "s25sl064a";
+ reg = <0>;
+ spi-max-frequency = <25000000>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x000000 0x020000>;
+ };
+
+ partition@1 {
+ label = "firmware";
+ reg = <0x020000 0x7D0000>;
+ };
+
+ partition@2 {
+ label = "art";
+ reg = <0x7F0000 0x010000>;
+ read-only;
+ };
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys-polled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ poll-interval = <20>;
+ button@0 {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
+ debounce-interval = <60>;
+ };
+
+ button@1 {
+ label = "qss";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
+ debounce-interval = <60>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led@0 {
+ label = "tp-link:green:usb";
+ gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+ };
+
+ led@1 {
+ label = "tp-link:green:system";
+ gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led@2 {
+ label = "tp-link:green:qss";
+ gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+ };
+
+ led@3 {
+ label = "tp-link:green:wlan";
+ gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/xilfpga/Makefile b/kernel/arch/mips/boot/dts/xilfpga/Makefile
new file mode 100644
index 000000000..913a752a9
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/xilfpga/Makefile
@@ -0,0 +1,9 @@
+dtb-$(CONFIG_XILFPGA_NEXYS4DDR) += nexys4ddr.dtb
+
+obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj- += dummy.o
+
+always := $(dtb-y)
+clean-files := *.dtb *.dtb.S
diff --git a/kernel/arch/mips/boot/dts/xilfpga/microAptiv.dtsi b/kernel/arch/mips/boot/dts/xilfpga/microAptiv.dtsi
new file mode 100644
index 000000000..81d518e75
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/xilfpga/microAptiv.dtsi
@@ -0,0 +1,21 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "img,xilfpga";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "mips,m14Kc";
+ clocks = <&ext>;
+ reg = <0>;
+ };
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+};
diff --git a/kernel/arch/mips/boot/dts/xilfpga/nexys4ddr.dts b/kernel/arch/mips/boot/dts/xilfpga/nexys4ddr.dts
new file mode 100644
index 000000000..686ebd113
--- /dev/null
+++ b/kernel/arch/mips/boot/dts/xilfpga/nexys4ddr.dts
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+#include "microAptiv.dtsi"
+
+/ {
+ compatible = "digilent,nexys4ddr";
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x08000000>;
+ };
+
+ cpuintc: interrupt-controller@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ axi_gpio: gpio@10600000 {
+ #gpio-cells = <1>;
+ compatible = "xlnx,xps-gpio-1.00.a";
+ gpio-controller;
+ reg = <0x10600000 0x10000>;
+ xlnx,all-inputs = <0x0>;
+ xlnx,dout-default = <0x0>;
+ xlnx,gpio-width = <0x16>;
+ xlnx,interrupt-present = <0x0>;
+ xlnx,is-dual = <0x0>;
+ xlnx,tri-default = <0xffffffff>;
+ } ;
+
+ axi_uart16550: serial@10400000 {
+ compatible = "ns16550a";
+ reg = <0x10400000 0x10000>;
+
+ reg-shift = <2>;
+ reg-offset = <0x1000>;
+
+ clocks = <&ext>;
+ };
+};
+
+&ext {
+ clock-frequency = <50000000>;
+};
diff --git a/kernel/arch/mips/cavium-octeon/Makefile b/kernel/arch/mips/cavium-octeon/Makefile
index 69a8a8dab..2a5926578 100644
--- a/kernel/arch/mips/cavium-octeon/Makefile
+++ b/kernel/arch/mips/cavium-octeon/Makefile
@@ -9,9 +9,6 @@
# Copyright (C) 2005-2009 Cavium Networks
#
-CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt
-CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
-
obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
obj-y += dma-octeon.o
obj-y += octeon-memcpy.o
diff --git a/kernel/arch/mips/cavium-octeon/crypto/octeon-md5.c b/kernel/arch/mips/cavium-octeon/crypto/octeon-md5.c
index 12dccdb38..af4c712f7 100644
--- a/kernel/arch/mips/cavium-octeon/crypto/octeon-md5.c
+++ b/kernel/arch/mips/cavium-octeon/crypto/octeon-md5.c
@@ -69,10 +69,10 @@ static int octeon_md5_init(struct shash_desc *desc)
{
struct md5_state *mctx = shash_desc_ctx(desc);
- mctx->hash[0] = cpu_to_le32(0x67452301);
- mctx->hash[1] = cpu_to_le32(0xefcdab89);
- mctx->hash[2] = cpu_to_le32(0x98badcfe);
- mctx->hash[3] = cpu_to_le32(0x10325476);
+ mctx->hash[0] = cpu_to_le32(MD5_H0);
+ mctx->hash[1] = cpu_to_le32(MD5_H1);
+ mctx->hash[2] = cpu_to_le32(MD5_H2);
+ mctx->hash[3] = cpu_to_le32(MD5_H3);
mctx->byte_count = 0;
return 0;
diff --git a/kernel/arch/mips/cavium-octeon/dma-octeon.c b/kernel/arch/mips/cavium-octeon/dma-octeon.c
index d8960d464..2cd45f5f9 100644
--- a/kernel/arch/mips/cavium-octeon/dma-octeon.c
+++ b/kernel/arch/mips/cavium-octeon/dma-octeon.c
@@ -161,9 +161,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
{
void *ret;
- if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
- return ret;
-
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
@@ -194,11 +191,6 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
static void octeon_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
{
- int order = get_order(size);
-
- if (dma_release_from_coherent(dev, order, vaddr))
- return;
-
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index 9eb0feef4..36e30d65b 100644
--- a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -195,6 +195,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return 8;
else
return -1;
+ case CVMX_BOARD_TYPE_KONTRON_S1901:
+ if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
+ return 1;
+ else
+ return -1;
+
}
/* Some unknown board. Somebody forgot to update this function... */
diff --git a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-util.c b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
index 453d7f664..b45b29757 100644
--- a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
+++ b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-util.c
@@ -95,9 +95,9 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
uint8_t *data_address;
uint8_t *end_of_data;
- cvmx_dprintf("Packet Length: %u\n", work->len);
- cvmx_dprintf(" Input Port: %u\n", work->ipprt);
- cvmx_dprintf(" QoS: %u\n", work->qos);
+ cvmx_dprintf("Packet Length: %u\n", work->word1.len);
+ cvmx_dprintf(" Input Port: %u\n", cvmx_wqe_get_port(work));
+ cvmx_dprintf(" QoS: %u\n", cvmx_wqe_get_qos(work));
cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs);
if (work->word2.s.bufs == 0) {
@@ -127,7 +127,7 @@ int cvmx_helper_dump_packet(cvmx_wqe_t *work)
}
} else
buffer_ptr = work->packet_ptr;
- remaining_bytes = work->len;
+ remaining_bytes = work->word1.len;
while (remaining_bytes) {
start_of_buffer =
@@ -382,6 +382,10 @@ int cvmx_helper_get_ipd_port(int interface, int port)
return port + 32;
case 3:
return port + 36;
+ case 4:
+ return port + 40;
+ case 5:
+ return port + 44;
}
return -1;
}
@@ -404,6 +408,10 @@ int cvmx_helper_get_interface_num(int ipd_port)
return 2;
else if (ipd_port < 40)
return 3;
+ else if (ipd_port < 44)
+ return 4;
+ else if (ipd_port < 48)
+ return 5;
else
cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD "
"port number\n");
@@ -428,6 +436,10 @@ int cvmx_helper_get_interface_index_num(int ipd_port)
return ipd_port & 3;
else if (ipd_port < 40)
return ipd_port & 3;
+ else if (ipd_port < 44)
+ return ipd_port & 3;
+ else if (ipd_port < 48)
+ return ipd_port & 3;
else
cvmx_dprintf("cvmx_helper_get_interface_index_num: "
"Illegal IPD port number\n");
diff --git a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
index 7653b7e92..a56ee590d 100644
--- a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
+++ b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
@@ -124,6 +124,13 @@ int __cvmx_helper_xaui_enable(int interface)
union cvmx_gmxx_tx_int_en gmx_tx_int_en;
union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
+ /* Setup PKND */
+ if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
+ gmx_cfg.s.pknd = cvmx_helper_get_ipd_port(interface, 0);
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
+ }
+
/* (1) Interface has already been enabled. */
/* (2) Disable GMX. */
@@ -151,7 +158,12 @@ int __cvmx_helper_xaui_enable(int interface)
/* (4)c Aply reset sequence */
xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
xauiCtl.s.lo_pwr = 0;
- xauiCtl.s.reset = 1;
+
+ /* Issuing a reset here seems to hang some CN68XX chips. */
+ if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) &&
+ !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X))
+ xauiCtl.s.reset = 1;
+
cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
/* Wait for PCS to come out of reset */
diff --git a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper.c b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper.c
index 7e5cf7a5e..376701f41 100644
--- a/kernel/arch/mips/cavium-octeon/executive/cvmx-helper.c
+++ b/kernel/arch/mips/cavium-octeon/executive/cvmx-helper.c
@@ -83,6 +83,8 @@ static cvmx_helper_link_info_t
*/
int cvmx_helper_get_number_of_interfaces(void)
{
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return 9;
if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
return 4;
else
@@ -656,6 +658,21 @@ static int __cvmx_helper_global_setup_pko(void)
fau_to.s.tout_val = 0xfff;
fau_to.s.tout_enb = 0;
cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
+
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ union cvmx_pko_reg_min_pkt min_pkt;
+
+ min_pkt.u64 = 0;
+ min_pkt.s.size1 = 59;
+ min_pkt.s.size2 = 59;
+ min_pkt.s.size3 = 59;
+ min_pkt.s.size4 = 59;
+ min_pkt.s.size5 = 59;
+ min_pkt.s.size6 = 59;
+ min_pkt.s.size7 = 59;
+ cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
+ }
+
return 0;
}
diff --git a/kernel/arch/mips/cavium-octeon/executive/cvmx-pko.c b/kernel/arch/mips/cavium-octeon/executive/cvmx-pko.c
index 008b881cd..87be167a7 100644
--- a/kernel/arch/mips/cavium-octeon/executive/cvmx-pko.c
+++ b/kernel/arch/mips/cavium-octeon/executive/cvmx-pko.c
@@ -39,6 +39,143 @@
* Internal state of packet output
*/
+static int __cvmx_pko_int(int interface, int index)
+{
+ switch (interface) {
+ case 0:
+ return index;
+ case 1:
+ return 4;
+ case 2:
+ return index + 0x08;
+ case 3:
+ return index + 0x0c;
+ case 4:
+ return index + 0x10;
+ case 5:
+ return 0x1c;
+ case 6:
+ return 0x1d;
+ case 7:
+ return 0x1e;
+ case 8:
+ return 0x1f;
+ default:
+ return -1;
+ }
+}
+
+static void __cvmx_pko_iport_config(int pko_port)
+{
+ int queue;
+ const int num_queues = 1;
+ const int base_queue = pko_port;
+ const int static_priority_end = 1;
+ const int static_priority_base = 1;
+
+ for (queue = 0; queue < num_queues; queue++) {
+ union cvmx_pko_mem_iqueue_ptrs config;
+ cvmx_cmd_queue_result_t cmd_res;
+ uint64_t *buf_ptr;
+
+ config.u64 = 0;
+ config.s.index = queue;
+ config.s.qid = base_queue + queue;
+ config.s.ipid = pko_port;
+ config.s.tail = (queue == (num_queues - 1));
+ config.s.s_tail = (queue == static_priority_end);
+ config.s.static_p = (static_priority_base >= 0);
+ config.s.static_q = (queue <= static_priority_end);
+ config.s.qos_mask = 0xff;
+
+ cmd_res = cvmx_cmd_queue_initialize(
+ CVMX_CMD_QUEUE_PKO(base_queue + queue),
+ CVMX_PKO_MAX_QUEUE_DEPTH,
+ CVMX_FPA_OUTPUT_BUFFER_POOL,
+ (CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE -
+ CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST * 8));
+
+ WARN(cmd_res,
+ "%s: cmd_res=%d pko_port=%d base_queue=%d num_queues=%d queue=%d\n",
+ __func__, (int)cmd_res, pko_port, base_queue,
+ num_queues, queue);
+
+ buf_ptr = (uint64_t *)cvmx_cmd_queue_buffer(
+ CVMX_CMD_QUEUE_PKO(base_queue + queue));
+ config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr) >> 7;
+ CVMX_SYNCWS;
+ cvmx_write_csr(CVMX_PKO_MEM_IQUEUE_PTRS, config.u64);
+ }
+}
+
+static void __cvmx_pko_queue_alloc_o68(void)
+{
+ int port;
+
+ for (port = 0; port < 48; port++)
+ __cvmx_pko_iport_config(port);
+}
+
+static void __cvmx_pko_port_map_o68(void)
+{
+ int port;
+ int interface, index;
+ cvmx_helper_interface_mode_t mode;
+ union cvmx_pko_mem_iport_ptrs config;
+
+ /*
+ * Initialize every iport with the invalid eid.
+ */
+ config.u64 = 0;
+ config.s.eid = 31; /* Invalid */
+ for (port = 0; port < 128; port++) {
+ config.s.ipid = port;
+ cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+ }
+
+ /*
+ * Set up PKO_MEM_IPORT_PTRS
+ */
+ for (port = 0; port < 48; port++) {
+ interface = cvmx_helper_get_interface_num(port);
+ index = cvmx_helper_get_interface_index_num(port);
+ mode = cvmx_helper_interface_get_mode(interface);
+ if (mode == CVMX_HELPER_INTERFACE_MODE_DISABLED)
+ continue;
+
+ config.s.ipid = port;
+ config.s.qos_mask = 0xff;
+ config.s.crc = 1;
+ config.s.min_pkt = 1;
+ config.s.intr = __cvmx_pko_int(interface, index);
+ config.s.eid = config.s.intr;
+ config.s.pipe = (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) ?
+ index : port;
+ cvmx_write_csr(CVMX_PKO_MEM_IPORT_PTRS, config.u64);
+ }
+}
+
+static void __cvmx_pko_chip_init(void)
+{
+ int i;
+
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+ __cvmx_pko_port_map_o68();
+ __cvmx_pko_queue_alloc_o68();
+ return;
+ }
+
+ /*
+ * Initialize queues
+ */
+ for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++) {
+ const uint64_t priority = 8;
+
+ cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
+ &priority);
+ }
+}
+
/**
* Call before any other calls to initialize the packet
* output system. This does chip global config, and should only be
@@ -47,8 +184,6 @@
void cvmx_pko_initialize_global(void)
{
- int i;
- uint64_t priority = 8;
union cvmx_pko_reg_cmd_buf config;
/*
@@ -62,9 +197,10 @@ void cvmx_pko_initialize_global(void)
cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
- for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++)
- cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
- &priority);
+ /*
+ * Chip-specific setup.
+ */
+ __cvmx_pko_chip_init();
/*
* If we aren't using all of the queues optimize PKO's
@@ -212,6 +348,9 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
int static_priority_base = -1;
int static_priority_end = -1;
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return CVMX_PKO_SUCCESS;
+
if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS)
&& (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) {
cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
diff --git a/kernel/arch/mips/cavium-octeon/octeon-irq.c b/kernel/arch/mips/cavium-octeon/octeon-irq.c
index 10f762557..4f9eb0576 100644
--- a/kernel/arch/mips/cavium-octeon/octeon-irq.c
+++ b/kernel/arch/mips/cavium-octeon/octeon-irq.c
@@ -225,13 +225,14 @@ static int next_cpu_for_irq(struct irq_data *data)
#ifdef CONFIG_SMP
int cpu;
- int weight = cpumask_weight(data->affinity);
+ struct cpumask *mask = irq_data_get_affinity_mask(data);
+ int weight = cpumask_weight(mask);
struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
if (weight > 1) {
cpu = cd->current_cpu;
for (;;) {
- cpu = cpumask_next(cpu, data->affinity);
+ cpu = cpumask_next(cpu, mask);
if (cpu >= nr_cpu_ids) {
cpu = -1;
continue;
@@ -240,7 +241,7 @@ static int next_cpu_for_irq(struct irq_data *data)
}
}
} else if (weight == 1) {
- cpu = cpumask_first(data->affinity);
+ cpu = cpumask_first(mask);
} else {
cpu = smp_processor_id();
}
@@ -662,6 +663,11 @@ static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
irqd_set_trigger_type(data, t);
octeon_irq_gpio_setup(data);
+ if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
+ irq_set_handler_locked(data, handle_edge_irq);
+ else
+ irq_set_handler_locked(data, handle_level_irq);
+
return IRQ_SET_MASK_OK;
}
@@ -696,30 +702,23 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
}
-static void octeon_irq_handle_trigger(unsigned int irq, struct irq_desc *desc)
-{
- if (irq_get_trigger_type(irq) & IRQ_TYPE_EDGE_BOTH)
- handle_edge_irq(irq, desc);
- else
- handle_level_irq(irq, desc);
-}
-
#ifdef CONFIG_SMP
static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
{
int cpu = smp_processor_id();
cpumask_t new_affinity;
+ struct cpumask *mask = irq_data_get_affinity_mask(data);
- if (!cpumask_test_cpu(cpu, data->affinity))
+ if (!cpumask_test_cpu(cpu, mask))
return;
- if (cpumask_weight(data->affinity) > 1) {
+ if (cpumask_weight(mask) > 1) {
/*
* It has multi CPU affinity, just remove this CPU
* from the affinity set.
*/
- cpumask_copy(&new_affinity, data->affinity);
+ cpumask_copy(&new_affinity, mask);
cpumask_clear_cpu(cpu, &new_affinity);
} else {
/* Otherwise, put it on lowest numbered online CPU. */
@@ -1095,7 +1094,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
unsigned int pin;
unsigned int trigger;
- if (d->of_node != node)
+ if (irq_domain_get_of_node(d) != node)
return -EINVAL;
if (intsize < 2)
@@ -1225,8 +1224,13 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
+ /*
+ * Default to handle_level_irq. If the DT contains a different
+ * trigger type, it will call the irq_set_type callback and
+ * the handler gets updated.
+ */
r = octeon_irq_set_ciu_mapping(virq, line, bit, hw,
- octeon_irq_gpio_chip, octeon_irq_handle_trigger);
+ octeon_irq_gpio_chip, handle_level_irq);
return r;
}
@@ -2159,7 +2163,7 @@ static int octeon_irq_cib_map(struct irq_domain *d,
if (hw >= host_data->max_bits) {
pr_err("ERROR: %s mapping %u is to big!\n",
- d->of_node->name, (unsigned)hw);
+ irq_domain_get_of_node(d)->name, (unsigned)hw);
return -EINVAL;
}
@@ -2217,7 +2221,7 @@ static irqreturn_t octeon_irq_cib_handler(int my_irq, void *data)
if (irqd_get_trigger_type(irq_data) &
IRQ_TYPE_EDGE_BOTH)
cvmx_write_csr(host_data->raw_reg, 1ull << i);
- generic_handle_irq_desc(irq, desc);
+ generic_handle_irq_desc(desc);
}
}
diff --git a/kernel/arch/mips/cavium-octeon/setup.c b/kernel/arch/mips/cavium-octeon/setup.c
index 89a628455..cd7101fb6 100644
--- a/kernel/arch/mips/cavium-octeon/setup.c
+++ b/kernel/arch/mips/cavium-octeon/setup.c
@@ -933,7 +933,7 @@ void __init plat_mem_setup(void)
while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
&& (total < MAX_MEMORY)) {
memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
- __pa_symbol(&__init_end), -1,
+ __pa_symbol(&_end), -1,
0x100000,
CVMX_BOOTMEM_FLAG_NO_LOCKING);
if (memory >= 0) {
@@ -1081,6 +1081,7 @@ void __init prom_free_prom_memory(void)
int octeon_prune_device_tree(void);
+extern const char __appended_dtb;
extern const char __dtb_octeon_3xxx_begin;
extern const char __dtb_octeon_68xx_begin;
void __init device_tree_init(void)
@@ -1088,11 +1089,19 @@ void __init device_tree_init(void)
const void *fdt;
bool do_prune;
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+ if (!fdt_check_header(&__appended_dtb)) {
+ fdt = &__appended_dtb;
+ do_prune = false;
+ pr_info("Using appended Device Tree.\n");
+ } else
+#endif
if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
if (fdt_check_header(fdt))
panic("Corrupt Device Tree passed to kernel.");
do_prune = false;
+ pr_info("Using passed Device Tree.\n");
} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
fdt = &__dtb_octeon_68xx_begin;
do_prune = true;
@@ -1106,8 +1115,6 @@ void __init device_tree_init(void)
if (do_prune) {
octeon_prune_device_tree();
pr_info("Using internal Device Tree.\n");
- } else {
- pr_info("Using passed Device Tree.\n");
}
unflatten_and_copy_device_tree();
}
diff --git a/kernel/arch/mips/cavium-octeon/smp.c b/kernel/arch/mips/cavium-octeon/smp.c
index 56f5d080e..b7fa9ae28 100644
--- a/kernel/arch/mips/cavium-octeon/smp.c
+++ b/kernel/arch/mips/cavium-octeon/smp.c
@@ -42,7 +42,7 @@ static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
diff --git a/kernel/arch/mips/cobalt/mtd.c b/kernel/arch/mips/cobalt/mtd.c
index 8db7b5d81..83e1b1093 100644
--- a/kernel/arch/mips/cobalt/mtd.c
+++ b/kernel/arch/mips/cobalt/mtd.c
@@ -57,5 +57,4 @@ static int __init cobalt_mtd_init(void)
return 0;
}
-
-module_init(cobalt_mtd_init);
+device_initcall(cobalt_mtd_init);
diff --git a/kernel/arch/mips/configs/bigsur_defconfig b/kernel/arch/mips/configs/bigsur_defconfig
index 1cdff6b63..b3e7a1b61 100644
--- a/kernel/arch/mips/configs/bigsur_defconfig
+++ b/kernel/arch/mips/configs/bigsur_defconfig
@@ -122,20 +122,20 @@ CONFIG_EEPROM_MAX6875=y
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDETAPE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_CHR_DEV_SCH=m
CONFIG_ATA=y
CONFIG_SATA_SIL24=y
+CONFIG_PATA_CMD64X=y
+CONFIG_PATA_IT8213=m
CONFIG_PATA_SIL680=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
diff --git a/kernel/arch/mips/configs/bmips_be_defconfig b/kernel/arch/mips/configs/bmips_be_defconfig
index f5585c8f3..24dcb90b0 100644
--- a/kernel/arch/mips/configs/bmips_be_defconfig
+++ b/kernel/arch/mips/configs/bmips_be_defconfig
@@ -8,7 +8,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
# CONFIG_SWAP is not set
CONFIG_NO_HZ=y
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
CONFIG_EXPERT=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
@@ -33,6 +33,7 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_MTD=y
CONFIG_MTD_CFI=y
diff --git a/kernel/arch/mips/configs/bmips_stb_defconfig b/kernel/arch/mips/configs/bmips_stb_defconfig
index 400a47ec1..4eb5d6e9c 100644
--- a/kernel/arch/mips/configs/bmips_stb_defconfig
+++ b/kernel/arch/mips/configs/bmips_stb_defconfig
@@ -9,7 +9,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
# CONFIG_SWAP is not set
CONFIG_NO_HZ=y
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
CONFIG_EXPERT=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
@@ -34,6 +34,7 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_MTD=y
CONFIG_MTD_CFI=y
diff --git a/kernel/arch/mips/configs/capcella_defconfig b/kernel/arch/mips/configs/capcella_defconfig
index 5135dc0b9..2924ba34a 100644
--- a/kernel/arch/mips/configs/capcella_defconfig
+++ b/kernel/arch/mips/configs/capcella_defconfig
@@ -31,9 +31,9 @@ CONFIG_NETWORK_SECMARK=y
CONFIG_IP_SCTP=m
CONFIG_FW_LOADER=m
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
CONFIG_NETDEVICES=y
CONFIG_PHYLIB=m
CONFIG_MARVELL_PHY=m
diff --git a/kernel/arch/mips/configs/ci20_defconfig b/kernel/arch/mips/configs/ci20_defconfig
new file mode 100644
index 000000000..4e36b6e18
--- /dev/null
+++ b/kernel/arch/mips/configs/ci20_defconfig
@@ -0,0 +1,162 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4780_CI20=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_HZ_100=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+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_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=2
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_JZ4780=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_MEMORY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS=y
+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_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon console=ttyS4,115200 clk_ignore_unused"
diff --git a/kernel/arch/mips/configs/e55_defconfig b/kernel/arch/mips/configs/e55_defconfig
index 0126e66d6..e94d266c4 100644
--- a/kernel/arch/mips/configs/e55_defconfig
+++ b/kernel/arch/mips/configs/e55_defconfig
@@ -14,9 +14,9 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
diff --git a/kernel/arch/mips/configs/fuloong2e_defconfig b/kernel/arch/mips/configs/fuloong2e_defconfig
index b2a577ebc..87435897f 100644
--- a/kernel/arch/mips/configs/fuloong2e_defconfig
+++ b/kernel/arch/mips/configs/fuloong2e_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_LOONGSON=y
+CONFIG_MACH_LOONGSON64=y
CONFIG_64BIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -34,7 +34,7 @@ CONFIG_MIPS32_N32=y
CONFIG_PM=y
# CONFIG_SUSPEND is not set
CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION="/dev/hda3"
+CONFIG_PM_STD_PARTITION="/dev/sda3"
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -114,20 +114,16 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_RAM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_TASK_IOCTL=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_VIA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=m
CONFIG_VETH=m
diff --git a/kernel/arch/mips/configs/lasat_defconfig b/kernel/arch/mips/configs/lasat_defconfig
index 0179c7fa0..e620a2c3e 100644
--- a/kernel/arch/mips/configs/lasat_defconfig
+++ b/kernel/arch/mips/configs/lasat_defconfig
@@ -35,11 +35,11 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_CMD64X=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_NET_PCI=y
diff --git a/kernel/arch/mips/configs/lemote2f_defconfig b/kernel/arch/mips/configs/lemote2f_defconfig
index 0cbc9863c..004cf52d1 100644
--- a/kernel/arch/mips/configs/lemote2f_defconfig
+++ b/kernel/arch/mips/configs/lemote2f_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_LOONGSON=y
+CONFIG_MACH_LOONGSON64=y
CONFIG_LEMOTE_MACH2F=y
CONFIG_CS5536_MFGPT=y
CONFIG_64BIT=y
@@ -108,16 +108,11 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_TASK_IOCTL=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_AMD74XX=y
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_AMD=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
diff --git a/kernel/arch/mips/configs/loongson3_defconfig b/kernel/arch/mips/configs/loongson3_defconfig
index c84429974..f8bf915c6 100644
--- a/kernel/arch/mips/configs/loongson3_defconfig
+++ b/kernel/arch/mips/configs/loongson3_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_LOONGSON=y
+CONFIG_MACH_LOONGSON64=y
CONFIG_SWIOTLB=y
CONFIG_LOONGSON_MACH3X=y
CONFIG_CPU_LOONGSON3=y
diff --git a/kernel/arch/mips/configs/ls1b_defconfig b/kernel/arch/mips/configs/ls1b_defconfig
index 7eb75543c..1b2cc1fb2 100644
--- a/kernel/arch/mips/configs/ls1b_defconfig
+++ b/kernel/arch/mips/configs/ls1b_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_LOONGSON1=y
+CONFIG_MACH_LOONGSON32=y
CONFIG_PREEMPT=y
# CONFIG_SECCOMP is not set
CONFIG_EXPERIMENTAL=y
diff --git a/kernel/arch/mips/configs/malta_defconfig b/kernel/arch/mips/configs/malta_defconfig
index 61a4460d6..5afb4840a 100644
--- a/kernel/arch/mips/configs/malta_defconfig
+++ b/kernel/arch/mips/configs/malta_defconfig
@@ -241,14 +241,11 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
CONFIG_RAID_ATTRS=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=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_SCSI_CONSTANTS=y
@@ -265,6 +262,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
CONFIG_ATA=y
CONFIG_ATA_PIIX=y
+CONFIG_PATA_LEGACY=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
diff --git a/kernel/arch/mips/configs/malta_kvm_defconfig b/kernel/arch/mips/configs/malta_kvm_defconfig
index d41742dd2..98f13879b 100644
--- a/kernel/arch/mips/configs/malta_kvm_defconfig
+++ b/kernel/arch/mips/configs/malta_kvm_defconfig
@@ -248,17 +248,12 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_RESET_DELAY_MS=15000
# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
diff --git a/kernel/arch/mips/configs/malta_kvm_guest_defconfig b/kernel/arch/mips/configs/malta_kvm_guest_defconfig
index a7806e83e..3b5d5913f 100644
--- a/kernel/arch/mips/configs/malta_kvm_guest_defconfig
+++ b/kernel/arch/mips/configs/malta_kvm_guest_defconfig
@@ -248,17 +248,12 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_VIRTIO_BLK=y
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_RESET_DELAY_MS=15000
# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
diff --git a/kernel/arch/mips/configs/malta_qemu_32r6_defconfig b/kernel/arch/mips/configs/malta_qemu_32r6_defconfig
index 4bce1f8eb..7f50dd67a 100644
--- a/kernel/arch/mips/configs/malta_qemu_32r6_defconfig
+++ b/kernel/arch/mips/configs/malta_qemu_32r6_defconfig
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
diff --git a/kernel/arch/mips/configs/maltaaprp_defconfig b/kernel/arch/mips/configs/maltaaprp_defconfig
index fb042ce86..a9d433a17 100644
--- a/kernel/arch/mips/configs/maltaaprp_defconfig
+++ b/kernel/arch/mips/configs/maltaaprp_defconfig
@@ -81,15 +81,14 @@ CONFIG_NET_CLS_IND=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
diff --git a/kernel/arch/mips/configs/maltasmvp_defconfig b/kernel/arch/mips/configs/maltasmvp_defconfig
index f8a32315b..ac0eb4daf 100644
--- a/kernel/arch/mips/configs/maltasmvp_defconfig
+++ b/kernel/arch/mips/configs/maltasmvp_defconfig
@@ -84,15 +84,12 @@ CONFIG_NET_CLS_IND=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+CONFIG_ATA_PIIX=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
@@ -138,7 +135,6 @@ CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_HW_RANDOM=y
# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_MATROX=y
@@ -152,7 +148,6 @@ CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_IDE_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
@@ -160,7 +155,11 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_EXT2_FS=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_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_XFS_FS=y
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
diff --git a/kernel/arch/mips/configs/maltasmvp_eva_defconfig b/kernel/arch/mips/configs/maltasmvp_eva_defconfig
index c83338a39..2774ef064 100644
--- a/kernel/arch/mips/configs/maltasmvp_eva_defconfig
+++ b/kernel/arch/mips/configs/maltasmvp_eva_defconfig
@@ -85,15 +85,14 @@ CONFIG_NET_CLS_IND=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
diff --git a/kernel/arch/mips/configs/maltaup_defconfig b/kernel/arch/mips/configs/maltaup_defconfig
index 62344648e..9bbd2218f 100644
--- a/kernel/arch/mips/configs/maltaup_defconfig
+++ b/kernel/arch/mips/configs/maltaup_defconfig
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
CONFIG_DEVTMPFS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
diff --git a/kernel/arch/mips/configs/maltaup_xpa_defconfig b/kernel/arch/mips/configs/maltaup_xpa_defconfig
index c388bff09..732215732 100644
--- a/kernel/arch/mips/configs/maltaup_xpa_defconfig
+++ b/kernel/arch/mips/configs/maltaup_xpa_defconfig
@@ -244,17 +244,12 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_IDE=y
CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_SCSI_CONSTANTS=y
@@ -269,6 +264,13 @@ CONFIG_SCSI_AACRAID=m
CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_RESET_DELAY_MS=15000
# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_MD_LINEAR=m
diff --git a/kernel/arch/mips/configs/mpc30x_defconfig b/kernel/arch/mips/configs/mpc30x_defconfig
index 7a346605c..a2c045fab 100644
--- a/kernel/arch/mips/configs/mpc30x_defconfig
+++ b/kernel/arch/mips/configs/mpc30x_defconfig
@@ -27,9 +27,9 @@ CONFIG_INET_XFRM_MODE_BEET=m
CONFIG_NETWORK_SECMARK=y
CONFIG_CONNECTOR=m
CONFIG_ATA_OVER_ETH=m
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
CONFIG_NETDEVICES=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
diff --git a/kernel/arch/mips/configs/pistachio_defconfig b/kernel/arch/mips/configs/pistachio_defconfig
index f22e92ee7..8b7429127 100644
--- a/kernel/arch/mips/configs/pistachio_defconfig
+++ b/kernel/arch/mips/configs/pistachio_defconfig
@@ -257,7 +257,6 @@ CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
CONFIG_MMC_TEST=m
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_RTC_CLASS=y
@@ -272,6 +271,7 @@ CONFIG_IIO=y
CONFIG_CC10001_ADC=y
CONFIG_PWM=y
CONFIG_PWM_IMG=y
+CONFIG_PHY_PISTACHIO_USB=y
CONFIG_ANDROID=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
@@ -319,7 +319,6 @@ CONFIG_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_YAMA=y
-CONFIG_SECURITY_YAMA_STACKED=y
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_HMAC=y
diff --git a/kernel/arch/mips/configs/qi_lb60_defconfig b/kernel/arch/mips/configs/qi_lb60_defconfig
index 2b965470c..d7bb8cce1 100644
--- a/kernel/arch/mips/configs/qi_lb60_defconfig
+++ b/kernel/arch/mips/configs/qi_lb60_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_JZ4740=y
+CONFIG_MACH_INGENIC=y
# CONFIG_COMPACTION is not set
# CONFIG_CROSS_MEMORY_ATTACH is not set
CONFIG_HZ_100=y
@@ -66,6 +66,7 @@ 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_SERIAL_8250_INGENIC=y
# CONFIG_HW_RANDOM is not set
CONFIG_SPI=y
CONFIG_SPI_GPIO=y
diff --git a/kernel/arch/mips/configs/xilfpga_defconfig b/kernel/arch/mips/configs/xilfpga_defconfig
new file mode 100644
index 000000000..ed1dce348
--- /dev/null
+++ b/kernel/arch/mips/configs/xilfpga_defconfig
@@ -0,0 +1,40 @@
+CONFIG_MACH_XILFPGA=y
+# CONFIG_COMPACTION is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
diff --git a/kernel/arch/mips/include/asm/Kbuild b/kernel/arch/mips/include/asm/Kbuild
index 526539cbc..c7fe4d01e 100644
--- a/kernel/arch/mips/include/asm/Kbuild
+++ b/kernel/arch/mips/include/asm/Kbuild
@@ -7,15 +7,15 @@ generic-y += emergency-restart.h
generic-y += irq_work.h
generic-y += local64.h
generic-y += mcs_spinlock.h
+generic-y += mm-arch-hooks.h
generic-y += mutex.h
generic-y += parport.h
generic-y += percpu.h
generic-y += preempt.h
-generic-y += scatterlist.h
generic-y += sections.h
generic-y += segment.h
generic-y += serial.h
generic-y += trace_clock.h
-generic-y += ucontext.h
generic-y += user.h
+generic-y += word-at-a-time.h
generic-y += xor.h
diff --git a/kernel/arch/mips/include/asm/abi.h b/kernel/arch/mips/include/asm/abi.h
index 7186bb51b..940760844 100644
--- a/kernel/arch/mips/include/asm/abi.h
+++ b/kernel/arch/mips/include/asm/abi.h
@@ -11,15 +11,20 @@
#include <asm/signal.h>
#include <asm/siginfo.h>
+#include <asm/vdso.h>
struct mips_abi {
int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set);
- const unsigned long signal_return_offset;
int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set);
- const unsigned long rt_signal_return_offset;
const unsigned long restart;
+
+ unsigned off_sc_fpregs;
+ unsigned off_sc_fpc_csr;
+ unsigned off_sc_used_math;
+
+ struct mips_vdso_image *vdso;
};
#endif /* _ASM_ABI_H */
diff --git a/kernel/arch/mips/include/asm/asmmacro.h b/kernel/arch/mips/include/asm/asmmacro.h
index 6156ac8c4..867f924b0 100644
--- a/kernel/arch/mips/include/asm/asmmacro.h
+++ b/kernel/arch/mips/include/asm/asmmacro.h
@@ -211,9 +211,13 @@
.endm
#ifdef TOOLCHAIN_SUPPORTS_MSA
+/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
+#undef fp
+
.macro _cfcmsa rd, cs
.set push
.set mips32r2
+ .set fp=64
.set msa
cfcmsa \rd, $\cs
.set pop
@@ -222,22 +226,73 @@
.macro _ctcmsa cd, rs
.set push
.set mips32r2
+ .set fp=64
.set msa
ctcmsa $\cd, \rs
.set pop
.endm
+ .macro ld_b wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ ld.b $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro ld_h wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ ld.h $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro ld_w wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ ld.w $w\wd, \off(\base)
+ .set pop
+ .endm
+
.macro ld_d wd, off, base
.set push
.set mips32r2
+ .set fp=64
.set msa
ld.d $w\wd, \off(\base)
.set pop
.endm
+ .macro st_b wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ st.b $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro st_h wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ st.h $w\wd, \off(\base)
+ .set pop
+ .endm
+
+ .macro st_w wd, off, base
+ .set push
+ .set mips32r2
+ .set msa
+ st.w $w\wd, \off(\base)
+ .set pop
+ .endm
+
.macro st_d wd, off, base
.set push
.set mips32r2
+ .set fp=64
.set msa
st.d $w\wd, \off(\base)
.set pop
@@ -246,6 +301,7 @@
.macro copy_u_w ws, n
.set push
.set mips32r2
+ .set fp=64
.set msa
copy_u.w $1, $w\ws[\n]
.set pop
@@ -254,6 +310,7 @@
.macro copy_u_d ws, n
.set push
.set mips64r2
+ .set fp=64
.set msa
copy_u.d $1, $w\ws[\n]
.set pop
@@ -262,6 +319,7 @@
.macro insert_w wd, n
.set push
.set mips32r2
+ .set fp=64
.set msa
insert.w $w\wd[\n], $1
.set pop
@@ -270,6 +328,7 @@
.macro insert_d wd, n
.set push
.set mips64r2
+ .set fp=64
.set msa
insert.d $w\wd[\n], $1
.set pop
@@ -279,7 +338,13 @@
#ifdef CONFIG_CPU_MICROMIPS
#define CFC_MSA_INSN 0x587e0056
#define CTC_MSA_INSN 0x583e0816
+#define LDB_MSA_INSN 0x58000807
+#define LDH_MSA_INSN 0x58000817
+#define LDW_MSA_INSN 0x58000827
#define LDD_MSA_INSN 0x58000837
+#define STB_MSA_INSN 0x5800080f
+#define STH_MSA_INSN 0x5800081f
+#define STW_MSA_INSN 0x5800082f
#define STD_MSA_INSN 0x5800083f
#define COPY_UW_MSA_INSN 0x58f00056
#define COPY_UD_MSA_INSN 0x58f80056
@@ -288,7 +353,13 @@
#else
#define CFC_MSA_INSN 0x787e0059
#define CTC_MSA_INSN 0x783e0819
+#define LDB_MSA_INSN 0x78000820
+#define LDH_MSA_INSN 0x78000821
+#define LDW_MSA_INSN 0x78000822
#define LDD_MSA_INSN 0x78000823
+#define STB_MSA_INSN 0x78000824
+#define STH_MSA_INSN 0x78000825
+#define STW_MSA_INSN 0x78000826
#define STD_MSA_INSN 0x78000827
#define COPY_UW_MSA_INSN 0x78f00059
#define COPY_UD_MSA_INSN 0x78f80059
@@ -318,6 +389,33 @@
.set pop
.endm
+ .macro ld_b wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word LDB_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro ld_h wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word LDH_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro ld_w wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word LDW_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
.macro ld_d wd, off, base
.set push
.set noat
@@ -327,6 +425,33 @@
.set pop
.endm
+ .macro st_b wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word STB_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro st_h wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word STH_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
+ .macro st_w wd, off, base
+ .set push
+ .set noat
+ SET_HARDFLOAT
+ addu $1, \base, \off
+ .word STW_MSA_INSN | (\wd << 6)
+ .set pop
+ .endm
+
.macro st_d wd, off, base
.set push
.set noat
diff --git a/kernel/arch/mips/include/asm/atomic.h b/kernel/arch/mips/include/asm/atomic.h
index 26d436336..835b402e4 100644
--- a/kernel/arch/mips/include/asm/atomic.h
+++ b/kernel/arch/mips/include/asm/atomic.h
@@ -30,7 +30,7 @@
*
* Atomically reads the value of @v.
*/
-#define atomic_read(v) ACCESS_ONCE((v)->counter)
+#define atomic_read(v) READ_ONCE((v)->counter)
/*
* atomic_set - set atomic variable
@@ -39,7 +39,7 @@
*
* Atomically sets the value of @v to @i.
*/
-#define atomic_set(v, i) ((v)->counter = (i))
+#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i))
#define ATOMIC_OP(op, c_op, asm_op) \
static __inline__ void atomic_##op(int i, atomic_t * v) \
@@ -137,6 +137,10 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \
ATOMIC_OPS(add, +=, addu)
ATOMIC_OPS(sub, -=, subu)
+ATOMIC_OP(and, &=, and)
+ATOMIC_OP(or, |=, or)
+ATOMIC_OP(xor, ^=, xor)
+
#undef ATOMIC_OPS
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP
@@ -311,14 +315,14 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
* @v: pointer of type atomic64_t
*
*/
-#define atomic64_read(v) ACCESS_ONCE((v)->counter)
+#define atomic64_read(v) READ_ONCE((v)->counter)
/*
* atomic64_set - set atomic variable
* @v: pointer of type atomic64_t
* @i: required value
*/
-#define atomic64_set(v, i) ((v)->counter = (i))
+#define atomic64_set(v, i) WRITE_ONCE((v)->counter, (i))
#define ATOMIC64_OP(op, c_op, asm_op) \
static __inline__ void atomic64_##op(long i, atomic64_t * v) \
@@ -416,6 +420,9 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
ATOMIC64_OPS(add, +=, daddu)
ATOMIC64_OPS(sub, -=, dsubu)
+ATOMIC64_OP(and, &=, and)
+ATOMIC64_OP(or, |=, or)
+ATOMIC64_OP(xor, ^=, xor)
#undef ATOMIC64_OPS
#undef ATOMIC64_OP_RETURN
@@ -500,7 +507,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns the old value of @v.
+ * Returns true iff @v was not @u.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
diff --git a/kernel/arch/mips/include/asm/barrier.h b/kernel/arch/mips/include/asm/barrier.h
index 2b8bbbcb9..752e0b86c 100644
--- a/kernel/arch/mips/include/asm/barrier.h
+++ b/kernel/arch/mips/include/asm/barrier.h
@@ -112,8 +112,8 @@
#define __WEAK_LLSC_MB " \n"
#endif
-#define set_mb(var, value) \
- do { var = value; smp_mb(); } while (0)
+#define smp_store_mb(var, value) \
+ do { WRITE_ONCE(var, value); smp_mb(); } while (0)
#define smp_llsc_mb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
@@ -133,12 +133,12 @@
do { \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
- ACCESS_ONCE(*p) = (v); \
+ WRITE_ONCE(*p, v); \
} while (0)
#define smp_load_acquire(p) \
({ \
- typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
___p1; \
diff --git a/kernel/arch/mips/include/asm/bcache.h b/kernel/arch/mips/include/asm/bcache.h
index 8c34484ce..a00857b13 100644
--- a/kernel/arch/mips/include/asm/bcache.h
+++ b/kernel/arch/mips/include/asm/bcache.h
@@ -9,6 +9,7 @@
#ifndef _ASM_BCACHE_H
#define _ASM_BCACHE_H
+#include <linux/types.h>
/* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
chipset implemented caches. On machines with other CPUs the CPU does the
@@ -18,6 +19,9 @@ struct bcache_ops {
void (*bc_disable)(void);
void (*bc_wback_inv)(unsigned long page, unsigned long size);
void (*bc_inv)(unsigned long page, unsigned long size);
+ void (*bc_prefetch_enable)(void);
+ void (*bc_prefetch_disable)(void);
+ bool (*bc_prefetch_is_enabled)(void);
};
extern void indy_sc_init(void);
@@ -46,6 +50,26 @@ static inline void bc_inv(unsigned long page, unsigned long size)
bcops->bc_inv(page, size);
}
+static inline void bc_prefetch_enable(void)
+{
+ if (bcops->bc_prefetch_enable)
+ bcops->bc_prefetch_enable();
+}
+
+static inline void bc_prefetch_disable(void)
+{
+ if (bcops->bc_prefetch_disable)
+ bcops->bc_prefetch_disable();
+}
+
+static inline bool bc_prefetch_is_enabled(void)
+{
+ if (bcops->bc_prefetch_is_enabled)
+ return bcops->bc_prefetch_is_enabled();
+
+ return false;
+}
+
#else /* !defined(CONFIG_BOARD_SCACHE) */
/* Not R4000 / R4400 / R4600 / R5000. */
@@ -54,6 +78,9 @@ static inline void bc_inv(unsigned long page, unsigned long size)
#define bc_disable() do { } while (0)
#define bc_wback_inv(page, size) do { } while (0)
#define bc_inv(page, size) do { } while (0)
+#define bc_prefetch_enable() do { } while (0)
+#define bc_prefetch_disable() do { } while (0)
+#define bc_prefetch_is_enabled() 0
#endif /* !defined(CONFIG_BOARD_SCACHE) */
diff --git a/kernel/arch/mips/include/asm/bitops.h b/kernel/arch/mips/include/asm/bitops.h
index 0cf29bd5d..ce9666cf1 100644
--- a/kernel/arch/mips/include/asm/bitops.h
+++ b/kernel/arch/mips/include/asm/bitops.h
@@ -469,7 +469,7 @@ static inline int test_and_change_bit(unsigned long nr,
*/
static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *addr)
{
- smp_mb();
+ smp_mb__before_llsc();
__clear_bit(nr, addr);
}
diff --git a/kernel/arch/mips/include/asm/bmips-spaces.h b/kernel/arch/mips/include/asm/bmips-spaces.h
new file mode 100644
index 000000000..eb96541ae
--- /dev/null
+++ b/kernel/arch/mips/include/asm/bmips-spaces.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_BMIPS_SPACES_H
+#define __ASM_BMIPS_SPACES_H
+
+/* Avoid collisions with system base register (SBR) region on BMIPS3300 */
+#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000)
+
+#endif /* __ASM_BMIPS_SPACES_H */
diff --git a/kernel/arch/mips/include/asm/cdmm.h b/kernel/arch/mips/include/asm/cdmm.h
index 16e22ce97..c06dbf8ba 100644
--- a/kernel/arch/mips/include/asm/cdmm.h
+++ b/kernel/arch/mips/include/asm/cdmm.h
@@ -53,7 +53,7 @@ struct mips_cdmm_driver {
* mips_cdmm_phys_base() - Choose a physical base address for CDMM region.
*
* Picking a suitable physical address at which to map the CDMM region is
- * platform specific, so this weak function can be defined by platform code to
+ * platform specific, so this function can be defined by platform code to
* pick a suitable value if none is configured by the bootloader.
*
* This address must be 32kB aligned, and the region occupies a maximum of 32kB
@@ -61,7 +61,7 @@ struct mips_cdmm_driver {
*
* Returns: Physical base address for CDMM region, or 0 on failure.
*/
-phys_addr_t __weak mips_cdmm_phys_base(void);
+phys_addr_t mips_cdmm_phys_base(void);
extern struct bus_type mips_cdmm_bustype;
void __iomem *mips_cdmm_early_probe(unsigned int dev_type);
@@ -84,6 +84,17 @@ void mips_cdmm_driver_unregister(struct mips_cdmm_driver *);
module_driver(__mips_cdmm_driver, mips_cdmm_driver_register, \
mips_cdmm_driver_unregister)
+/*
+ * builtin_mips_cdmm_driver() - Helper macro for drivers that don't do anything
+ * special in init and have no exit. This eliminates some boilerplate. Each
+ * driver may only use this macro once, and calling it replaces device_initcall
+ * (or in some cases, the legacy __initcall). This is meant to be a direct
+ * parallel of module_mips_cdmm_driver() above but without the __exit stuff that
+ * is not used for builtin cases.
+ */
+#define builtin_mips_cdmm_driver(__mips_cdmm_driver) \
+ builtin_driver(__mips_cdmm_driver, mips_cdmm_driver_register)
+
/* drivers/tty/mips_ejtag_fdc.c */
#ifdef CONFIG_MIPS_EJTAG_FDC_EARLYCON
diff --git a/kernel/arch/mips/include/asm/cevt-r4k.h b/kernel/arch/mips/include/asm/cevt-r4k.h
index f0edf6fcd..2e13a038d 100644
--- a/kernel/arch/mips/include/asm/cevt-r4k.h
+++ b/kernel/arch/mips/include/asm/cevt-r4k.h
@@ -21,7 +21,6 @@ DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
void mips_event_handler(struct clock_event_device *dev);
int c0_compare_int_usable(void);
-void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *);
irqreturn_t c0_compare_interrupt(int, void *);
extern struct irqaction c0_compare_irqaction;
diff --git a/kernel/arch/mips/include/asm/clocksource.h b/kernel/arch/mips/include/asm/clocksource.h
new file mode 100644
index 000000000..3deb1d0c1
--- /dev/null
+++ b/kernel/arch/mips/include/asm/clocksource.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_CLOCKSOURCE_H
+#define __ASM_CLOCKSOURCE_H
+
+#include <linux/types.h>
+
+/* VDSO clocksources. */
+#define VDSO_CLOCK_NONE 0 /* No suitable clocksource. */
+#define VDSO_CLOCK_R4K 1 /* Use the coprocessor 0 count. */
+#define VDSO_CLOCK_GIC 2 /* Use the GIC. */
+
+/**
+ * struct arch_clocksource_data - Architecture-specific clocksource information.
+ * @vdso_clock_mode: Method the VDSO should use to access the clocksource.
+ */
+struct arch_clocksource_data {
+ u8 vdso_clock_mode;
+};
+
+#endif /* __ASM_CLOCKSOURCE_H */
diff --git a/kernel/arch/mips/include/asm/cmpxchg.h b/kernel/arch/mips/include/asm/cmpxchg.h
index 412f945f1..b71ab4a5f 100644
--- a/kernel/arch/mips/include/asm/cmpxchg.h
+++ b/kernel/arch/mips/include/asm/cmpxchg.h
@@ -138,8 +138,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \
})
-#define __HAVE_ARCH_CMPXCHG 1
-
#define __cmpxchg_asm(ld, st, m, old, new) \
({ \
__typeof(*(m)) __ret; \
diff --git a/kernel/arch/mips/include/asm/compat.h b/kernel/arch/mips/include/asm/compat.h
index c4bd54a7f..a9580097c 100644
--- a/kernel/arch/mips/include/asm/compat.h
+++ b/kernel/arch/mips/include/asm/compat.h
@@ -130,6 +130,8 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+/* Can't use the generic version because si_code and si_errno are swapped */
+
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
typedef struct compat_siginfo {
@@ -138,57 +140,61 @@ typedef struct compat_siginfo {
int si_errno;
union {
- int _pad[SI_PAD_SIZE32];
+ int _pad[128 / sizeof(int) - 3];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
+ __compat_uid32_t _uid; /* sender's uid */
} _kill;
+ /* POSIX.1b timers */
+ struct {
+ compat_timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ compat_sigval_t _sigval; /* same as below */
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ __compat_uid32_t _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
- __compat_uid_t _uid; /* sender's uid */
+ __compat_uid32_t _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
} _sigchld;
- /* IRIX SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- compat_clock_t _utime;
- int _status; /* exit code */
- compat_clock_t _stime;
- } _irix_sigchld;
-
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
- s32 _addr; /* faulting insn/memory ref. */
+ compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+ int _trapno; /* TRAP # which caused the signal */
+#endif
+ short _addr_lsb; /* LSB of the reported address */
+ struct {
+ compat_uptr_t _lower;
+ compat_uptr_t _upper;
+ } _addr_bnd;
} _sigfault;
- /* SIGPOLL, SIGXFSZ (To do ...) */
+ /* SIGPOLL */
struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
- /* POSIX.1b timers */
- struct {
- timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval;/* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
struct {
- compat_pid_t _pid; /* sender's pid */
- __compat_uid_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
+ compat_uptr_t _call_addr; /* calling insn */
+ int _syscall; /* triggering system call number */
+ compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} compat_siginfo_t;
diff --git a/kernel/arch/mips/include/asm/cpu-features.h b/kernel/arch/mips/include/asm/cpu-features.h
index 5aeaf19c2..d1e04c943 100644
--- a/kernel/arch/mips/include/asm/cpu-features.h
+++ b/kernel/arch/mips/include/asm/cpu-features.h
@@ -20,6 +20,9 @@
#ifndef cpu_has_tlb
#define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB)
#endif
+#ifndef cpu_has_ftlb
+#define cpu_has_ftlb (cpu_data[0].options & MIPS_CPU_FTLB)
+#endif
#ifndef cpu_has_tlbinv
#define cpu_has_tlbinv (cpu_data[0].options & MIPS_CPU_TLBINV)
#endif
@@ -108,6 +111,9 @@
#ifndef cpu_has_llsc
#define cpu_has_llsc (cpu_data[0].options & MIPS_CPU_LLSC)
#endif
+#ifndef cpu_has_bp_ghist
+#define cpu_has_bp_ghist (cpu_data[0].options & MIPS_CPU_BP_GHIST)
+#endif
#ifndef kernel_uses_llsc
#define kernel_uses_llsc cpu_has_llsc
#endif
@@ -125,11 +131,7 @@
#endif
#ifndef cpu_has_rixi
-# ifdef CONFIG_64BIT
-# define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI)
-# else /* CONFIG_32BIT */
-# define cpu_has_rixi ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits)
-# endif
+#define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI)
#endif
#ifndef cpu_has_mmips
@@ -408,4 +410,8 @@
# define cpu_has_cdmm (cpu_data[0].options & MIPS_CPU_CDMM)
#endif
+#ifndef cpu_has_small_pages
+# define cpu_has_small_pages (cpu_data[0].options & MIPS_CPU_SP)
+#endif
+
#endif /* __ASM_CPU_FEATURES_H */
diff --git a/kernel/arch/mips/include/asm/cpu-type.h b/kernel/arch/mips/include/asm/cpu-type.h
index 33f3cab9e..abee2bfd1 100644
--- a/kernel/arch/mips/include/asm/cpu-type.h
+++ b/kernel/arch/mips/include/asm/cpu-type.h
@@ -32,12 +32,12 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_4KC:
case CPU_ALCHEMY:
case CPU_PR4450:
- case CPU_JZRISC:
#endif
#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R1) || \
defined(CONFIG_SYS_HAS_CPU_MIPS32_R2)
case CPU_4KEC:
+ case CPU_JZRISC:
#endif
#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2
@@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
*/
#endif
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
+ case CPU_I6400:
+#endif
+
#ifdef CONFIG_SYS_HAS_CPU_R3000
case CPU_R2000:
case CPU_R3000:
diff --git a/kernel/arch/mips/include/asm/cpu.h b/kernel/arch/mips/include/asm/cpu.h
index e3adca1d0..82ad15f11 100644
--- a/kernel/arch/mips/include/asm/cpu.h
+++ b/kernel/arch/mips/include/asm/cpu.h
@@ -42,7 +42,9 @@
#define PRID_COMP_LEXRA 0x0b0000
#define PRID_COMP_NETLOGIC 0x0c0000
#define PRID_COMP_CAVIUM 0x0d0000
-#define PRID_COMP_INGENIC 0xd00000
+#define PRID_COMP_INGENIC_D0 0xd00000 /* JZ4740, JZ4750 */
+#define PRID_COMP_INGENIC_D1 0xd10000 /* JZ4770, JZ4775 */
+#define PRID_COMP_INGENIC_E1 0xe10000 /* JZ4780 */
/*
* Assigned Processor ID (implementation) values for bits 15:8 of the PRId
@@ -118,6 +120,7 @@
#define PRID_IMP_PROAPTIV_MP 0xa300
#define PRID_IMP_M5150 0xa700
#define PRID_IMP_P5600 0xa800
+#define PRID_IMP_I6400 0xa900
/*
* These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -168,7 +171,7 @@
#define PRID_IMP_CAVIUM_CN70XX 0x9600
/*
- * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
+ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_*
*/
#define PRID_IMP_JZRISC 0x0200
@@ -305,6 +308,7 @@ enum cpu_type_enum {
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
+ CPU_I6400,
/*
* MIPS64 class processors
@@ -379,6 +383,9 @@ enum cpu_type_enum {
#define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */
#define MIPS_CPU_XPA 0x2000000000ull /* CPU supports Extended Physical Addressing */
#define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */
+#define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */
+#define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */
+#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */
/*
* CPU ASE encodings
diff --git a/kernel/arch/mips/include/asm/debug.h b/kernel/arch/mips/include/asm/debug.h
index 1fd5a2b39..254f00deb 100644
--- a/kernel/arch/mips/include/asm/debug.h
+++ b/kernel/arch/mips/include/asm/debug.h
@@ -1,48 +1,22 @@
/*
- * Debug macros for run-time debugging.
- * Turned on/off with CONFIG_RUNTIME_DEBUG option.
+ * Copyright (C) 2015 Imagination Technologies
*
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
- *
*/
-#ifndef _ASM_DEBUG_H
-#define _ASM_DEBUG_H
+#ifndef __MIPS_ASM_DEBUG_H__
+#define __MIPS_ASM_DEBUG_H__
+#include <linux/dcache.h>
/*
- * run-time macros for catching spurious errors. Eable CONFIG_RUNTIME_DEBUG in
- * kernel hacking config menu to use them.
- *
- * Use them as run-time debugging aid. NEVER USE THEM AS ERROR HANDLING CODE!!!
+ * mips_debugfs_dir corresponds to the "mips" directory at the top level
+ * of the DebugFS hierarchy. MIPS-specific DebugFS entires should be
+ * placed beneath this directory.
*/
+extern struct dentry *mips_debugfs_dir;
-#ifdef CONFIG_RUNTIME_DEBUG
-
-#include <linux/kernel.h>
-
-#define db_assert(x) if (!(x)) { \
- panic("assertion failed at %s:%d: %s", __FILE__, __LINE__, #x); }
-#define db_warn(x) if (!(x)) { \
- printk(KERN_WARNING "warning at %s:%d: %s", __FILE__, __LINE__, #x); }
-#define db_verify(x, y) db_assert(x y)
-#define db_verify_warn(x, y) db_warn(x y)
-#define db_run(x) do { x; } while (0)
-
-#else
-
-#define db_assert(x)
-#define db_warn(x)
-#define db_verify(x, y) x
-#define db_verify_warn(x, y) x
-#define db_run(x)
-
-#endif
-
-#endif /* _ASM_DEBUG_H */
+#endif /* __MIPS_ASM_DEBUG_H__ */
diff --git a/kernel/arch/mips/include/asm/dma-mapping.h b/kernel/arch/mips/include/asm/dma-mapping.h
index fd1b4a150..e604f760c 100644
--- a/kernel/arch/mips/include/asm/dma-mapping.h
+++ b/kernel/arch/mips/include/asm/dma-mapping.h
@@ -1,10 +1,9 @@
#ifndef _ASM_DMA_MAPPING_H
#define _ASM_DMA_MAPPING_H
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <asm/dma-coherence.h>
#include <asm/cache.h>
-#include <asm-generic/dma-coherent.h>
#ifndef CONFIG_SGI_IP27 /* Kludge to fix 2.6.39 build for IP27 */
#include <dma-coherence.h>
@@ -32,73 +31,7 @@ static inline void dma_mark_clean(void *addr, size_t size) {}
#include <asm-generic/dma-mapping-common.h>
-static inline int dma_supported(struct device *dev, u64 mask)
-{
- struct dma_map_ops *ops = get_dma_ops(dev);
- return ops->dma_supported(dev, mask);
-}
-
-static inline int dma_mapping_error(struct device *dev, u64 mask)
-{
- struct dma_map_ops *ops = get_dma_ops(dev);
-
- debug_dma_mapping_error(dev, mask);
- return ops->mapping_error(dev, mask);
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 mask)
-{
- struct dma_map_ops *ops = get_dma_ops(dev);
-
- if(!dev->dma_mask || !dma_supported(dev, mask))
- return -EIO;
-
- if (ops->set_dma_mask)
- return ops->set_dma_mask(dev, mask);
-
- *dev->dma_mask = mask;
-
- return 0;
-}
-
extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);
-#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
-{
- void *ret;
- struct dma_map_ops *ops = get_dma_ops(dev);
-
- ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
-
- debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
-
- return ret;
-}
-
-#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
-
-static inline void dma_free_attrs(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *ops = get_dma_ops(dev);
-
- ops->free(dev, size, vaddr, dma_handle, attrs);
-
- debug_dma_free_coherent(dev, size, vaddr, dma_handle);
-}
-
-
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
-
-void dma_free_noncoherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-
#endif /* _ASM_DMA_MAPPING_H */
diff --git a/kernel/arch/mips/include/asm/edac.h b/kernel/arch/mips/include/asm/edac.h
index 94105d3f5..980b16527 100644
--- a/kernel/arch/mips/include/asm/edac.h
+++ b/kernel/arch/mips/include/asm/edac.h
@@ -5,7 +5,7 @@
/* ECC atomic, DMA, SMP and interrupt safe scrub function */
-static inline void atomic_scrub(void *va, u32 size)
+static inline void edac_atomic_scrub(void *va, u32 size)
{
unsigned long *virt_addr = va;
unsigned long temp;
@@ -21,7 +21,7 @@ static inline void atomic_scrub(void *va, u32 size)
__asm__ __volatile__ (
" .set mips2 \n"
- "1: ll %0, %1 # atomic_scrub \n"
+ "1: ll %0, %1 # edac_atomic_scrub \n"
" addu %0, $0 \n"
" sc %0, %1 \n"
" beqz %0, 1b \n"
diff --git a/kernel/arch/mips/include/asm/elf.h b/kernel/arch/mips/include/asm/elf.h
index f19e890b9..b01a6ff46 100644
--- a/kernel/arch/mips/include/asm/elf.h
+++ b/kernel/arch/mips/include/asm/elf.h
@@ -8,6 +8,7 @@
#ifndef _ASM_ELF_H
#define _ASM_ELF_H
+#include <linux/auxvec.h>
#include <linux/fs.h>
#include <uapi/linux/elf.h>
@@ -382,7 +383,9 @@ do { \
instruction set this cpu supports. This could be done in userspace,
but it's not easy, and we've already done it here. */
-#define ELF_HWCAP (0)
+#define ELF_HWCAP (elf_hwcap)
+extern unsigned int elf_hwcap;
+#include <asm/hwcap.h>
/*
* This yields a string that ld.so will use to load implementation
@@ -417,6 +420,12 @@ extern const char *__elf_platform;
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif
+#define ARCH_DLINFO \
+do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (unsigned long)current->mm->context.vdso); \
+} while (0)
+
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
diff --git a/kernel/arch/mips/include/asm/fpu.h b/kernel/arch/mips/include/asm/fpu.h
index 1b0625189..9cbf383b8 100644
--- a/kernel/arch/mips/include/asm/fpu.h
+++ b/kernel/arch/mips/include/asm/fpu.h
@@ -164,25 +164,30 @@ static inline int own_fpu(int restore)
return ret;
}
-static inline void lose_fpu(int save)
+static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
{
- preempt_disable();
if (is_msa_enabled()) {
if (save) {
- save_msa(current);
- current->thread.fpu.fcr31 =
+ save_msa(tsk);
+ tsk->thread.fpu.fcr31 =
read_32bit_cp1_register(CP1_STATUS);
}
disable_msa();
- clear_thread_flag(TIF_USEDMSA);
+ clear_tsk_thread_flag(tsk, TIF_USEDMSA);
__disable_fpu();
} else if (is_fpu_owner()) {
if (save)
- _save_fp(current);
+ _save_fp(tsk);
__disable_fpu();
}
- KSTK_STATUS(current) &= ~ST0_CU1;
- clear_thread_flag(TIF_USEDFPU);
+ KSTK_STATUS(tsk) &= ~ST0_CU1;
+ clear_tsk_thread_flag(tsk, TIF_USEDFPU);
+}
+
+static inline void lose_fpu(int save)
+{
+ preempt_disable();
+ lose_fpu_inatomic(save, current);
preempt_enable();
}
diff --git a/kernel/arch/mips/include/asm/fw/fw.h b/kernel/arch/mips/include/asm/fw/fw.h
index f3e6978aa..d0ef8b489 100644
--- a/kernel/arch/mips/include/asm/fw/fw.h
+++ b/kernel/arch/mips/include/asm/fw/fw.h
@@ -10,21 +10,6 @@
#include <asm/bootinfo.h> /* For cleaner code... */
-enum fw_memtypes {
- fw_dontuse,
- fw_code,
- fw_free,
-};
-
-typedef struct {
- unsigned long base; /* Within KSEG0 */
- unsigned int size; /* bytes */
- enum fw_memtypes type; /* fw_memtypes */
-} fw_memblock_t;
-
-/* Maximum number of memory block descriptors. */
-#define FW_MAX_MEMBLOCKS 32
-
extern int fw_argc;
extern int *_fw_argv;
extern int *_fw_envp;
@@ -38,7 +23,6 @@ extern int *_fw_envp;
extern void fw_init_cmdline(void);
extern char *fw_getcmdline(void);
-extern fw_memblock_t *fw_getmdesc(int);
extern void fw_meminit(void);
extern char *fw_getenv(char *name);
extern unsigned long fw_getenvl(char *name);
diff --git a/kernel/arch/mips/include/asm/gpio.h b/kernel/arch/mips/include/asm/gpio.h
deleted file mode 100644
index 06e46faf8..000000000
--- a/kernel/arch/mips/include/asm/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_MIPS_GPIO_H
-#define __ASM_MIPS_GPIO_H
-
-#include <gpio.h>
-
-#endif /* __ASM_MIPS_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/hazards.h b/kernel/arch/mips/include/asm/hazards.h
index 4087b47ad..7b99efd31 100644
--- a/kernel/arch/mips/include/asm/hazards.h
+++ b/kernel/arch/mips/include/asm/hazards.h
@@ -31,9 +31,15 @@
#define __mtc0_tlbw_hazard \
___ehb
+#define __mtc0_tlbr_hazard \
+ ___ehb
+
#define __tlbw_use_hazard \
___ehb
+#define __tlb_read_hazard \
+ ___ehb
+
#define __tlb_probe_hazard \
___ehb
@@ -80,12 +86,23 @@ do { \
___ssnop; \
___ehb
+#define __mtc0_tlbr_hazard \
+ ___ssnop; \
+ ___ssnop; \
+ ___ehb
+
#define __tlbw_use_hazard \
___ssnop; \
___ssnop; \
___ssnop; \
___ehb
+#define __tlb_read_hazard \
+ ___ssnop; \
+ ___ssnop; \
+ ___ssnop; \
+ ___ehb
+
#define __tlb_probe_hazard \
___ssnop; \
___ssnop; \
@@ -147,8 +164,12 @@ do { \
#define __mtc0_tlbw_hazard
+#define __mtc0_tlbr_hazard
+
#define __tlbw_use_hazard
+#define __tlb_read_hazard
+
#define __tlb_probe_hazard
#define __irq_enable_hazard
@@ -166,8 +187,12 @@ do { \
*/
#define __mtc0_tlbw_hazard
+#define __mtc0_tlbr_hazard
+
#define __tlbw_use_hazard
+#define __tlb_read_hazard
+
#define __tlb_probe_hazard
#define __irq_enable_hazard
@@ -196,11 +221,20 @@ do { \
nop; \
nop
+#define __mtc0_tlbr_hazard \
+ nop; \
+ nop
+
#define __tlbw_use_hazard \
nop; \
nop; \
nop
+#define __tlb_read_hazard \
+ nop; \
+ nop; \
+ nop
+
#define __tlb_probe_hazard \
nop; \
nop; \
@@ -267,7 +301,9 @@ do { \
#define _ssnop ___ssnop
#define _ehb ___ehb
#define mtc0_tlbw_hazard __mtc0_tlbw_hazard
+#define mtc0_tlbr_hazard __mtc0_tlbr_hazard
#define tlbw_use_hazard __tlbw_use_hazard
+#define tlb_read_hazard __tlb_read_hazard
#define tlb_probe_hazard __tlb_probe_hazard
#define irq_enable_hazard __irq_enable_hazard
#define irq_disable_hazard __irq_disable_hazard
@@ -300,6 +336,14 @@ do { \
} while (0)
+#define mtc0_tlbr_hazard() \
+do { \
+ __asm__ __volatile__( \
+ __stringify(__mtc0_tlbr_hazard) \
+ ); \
+} while (0)
+
+
#define tlbw_use_hazard() \
do { \
__asm__ __volatile__( \
@@ -308,6 +352,14 @@ do { \
} while (0)
+#define tlb_read_hazard() \
+do { \
+ __asm__ __volatile__( \
+ __stringify(__tlb_read_hazard) \
+ ); \
+} while (0)
+
+
#define tlb_probe_hazard() \
do { \
__asm__ __volatile__( \
diff --git a/kernel/arch/mips/include/asm/highmem.h b/kernel/arch/mips/include/asm/highmem.h
index 572e63ec2..01880b34a 100644
--- a/kernel/arch/mips/include/asm/highmem.h
+++ b/kernel/arch/mips/include/asm/highmem.h
@@ -49,7 +49,6 @@ extern void kunmap(struct page *page);
extern void *kmap_atomic(struct page *page);
extern void __kunmap_atomic(void *kvaddr);
extern void *kmap_atomic_pfn(unsigned long pfn);
-extern struct page *kmap_atomic_to_page(void *ptr);
#define flush_cache_kmaps() flush_cache_all()
diff --git a/kernel/arch/mips/include/asm/hugetlb.h b/kernel/arch/mips/include/asm/hugetlb.h
index fe0d15d32..982bc0685 100644
--- a/kernel/arch/mips/include/asm/hugetlb.h
+++ b/kernel/arch/mips/include/asm/hugetlb.h
@@ -38,10 +38,6 @@ static inline int prepare_hugepage_range(struct file *file,
return 0;
}
-static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
-{
-}
-
static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr,
unsigned long end,
@@ -114,15 +110,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
return *ptep;
}
-static inline int arch_prepare_hugepage(struct page *page)
-{
- return 0;
-}
-
-static inline void arch_release_hugepage(struct page *page)
-{
-}
-
static inline void arch_clear_hugepage_flags(struct page *page)
{
}
diff --git a/kernel/arch/mips/include/asm/i8259.h b/kernel/arch/mips/include/asm/i8259.h
index c7e278447..a7fbcd6ed 100644
--- a/kernel/arch/mips/include/asm/i8259.h
+++ b/kernel/arch/mips/include/asm/i8259.h
@@ -41,6 +41,7 @@ extern int i8259A_irq_pending(unsigned int irq);
extern void make_8259A_irq(unsigned int irq);
extern void init_i8259_irqs(void);
+extern int i8259_of_init(struct device_node *node, struct device_node *parent);
/*
* Do the traditional i8259 interrupt polling thing. This is for the few
diff --git a/kernel/arch/mips/include/asm/io.h b/kernel/arch/mips/include/asm/io.h
index 9e777cd42..d10fd80db 100644
--- a/kernel/arch/mips/include/asm/io.h
+++ b/kernel/arch/mips/include/asm/io.h
@@ -256,6 +256,7 @@ static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long si
*/
#define ioremap_nocache(offset, size) \
__ioremap_mode((offset), (size), _CACHE_UNCACHED)
+#define ioremap_uc ioremap_nocache
/*
* ioremap_cachable - map bus memory into CPU space
diff --git a/kernel/arch/mips/include/asm/irq.h b/kernel/arch/mips/include/asm/irq.h
index f0db99f8d..15e0fecbc 100644
--- a/kernel/arch/mips/include/asm/irq.h
+++ b/kernel/arch/mips/include/asm/irq.h
@@ -49,7 +49,7 @@ extern int cp0_compare_irq_shift;
extern int cp0_perfcount_irq;
extern int cp0_fdc_irq;
-extern int __weak get_c0_fdc_int(void);
+extern int get_c0_fdc_int(void);
void arch_trigger_all_cpu_backtrace(bool);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
diff --git a/kernel/arch/mips/include/asm/irqflags.h b/kernel/arch/mips/include/asm/irqflags.h
index d60cc68fa..e7b138b4b 100644
--- a/kernel/arch/mips/include/asm/irqflags.h
+++ b/kernel/arch/mips/include/asm/irqflags.h
@@ -60,7 +60,7 @@ static inline void arch_local_irq_restore(unsigned long flags)
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_MIPS_CPU)
/*
* Slow, but doesn't suffer from a relatively unlikely race
* condition we're having since days 1.
@@ -90,7 +90,7 @@ static inline void __arch_local_irq_restore(unsigned long flags)
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_MIPS_CPU)
/*
* Slow, but doesn't suffer from a relatively unlikely race
* condition we're having since days 1.
diff --git a/kernel/arch/mips/include/asm/jump_label.h b/kernel/arch/mips/include/asm/jump_label.h
index 608aa5779..e77672539 100644
--- a/kernel/arch/mips/include/asm/jump_label.h
+++ b/kernel/arch/mips/include/asm/jump_label.h
@@ -26,14 +26,29 @@
#define NOP_INSN "nop"
#endif
-static __always_inline bool arch_static_branch(struct static_key *key)
+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
asm_volatile_goto("1:\t" NOP_INSN "\n\t"
"nop\n\t"
".pushsection __jump_table, \"aw\"\n\t"
WORD_INSN " 1b, %l[l_yes], %0\n\t"
".popsection\n\t"
- : : "i" (key) : : l_yes);
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+{
+ asm_volatile_goto("1:\tj %l[l_yes]\n\t"
+ "nop\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ WORD_INSN " 1b, %l[l_yes], %0\n\t"
+ ".popsection\n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
return false;
l_yes:
return true;
diff --git a/kernel/arch/mips/include/asm/kdebug.h b/kernel/arch/mips/include/asm/kdebug.h
index cba22ab7a..8e3d08e73 100644
--- a/kernel/arch/mips/include/asm/kdebug.h
+++ b/kernel/arch/mips/include/asm/kdebug.h
@@ -11,7 +11,9 @@ enum die_val {
DIE_PAGE_FAULT,
DIE_BREAK,
DIE_SSTEPBP,
- DIE_MSAFP
+ DIE_MSAFP,
+ DIE_UPROBE,
+ DIE_UPROBE_XOL,
};
#endif /* _ASM_MIPS_KDEBUG_H */
diff --git a/kernel/arch/mips/include/asm/kgdb.h b/kernel/arch/mips/include/asm/kgdb.h
index e6c0b0e14..69dc0df94 100644
--- a/kernel/arch/mips/include/asm/kgdb.h
+++ b/kernel/arch/mips/include/asm/kgdb.h
@@ -33,7 +33,6 @@
#define CACHE_FLUSH_IS_SAFE 0
extern void arch_kgdb_breakpoint(void);
-extern int kgdb_early_setup;
extern void *saved_vectors[32];
extern void handle_exception(struct pt_regs *regs);
extern void breakinst(void);
diff --git a/kernel/arch/mips/include/asm/kvm_host.h b/kernel/arch/mips/include/asm/kvm_host.h
index 4c2582356..6ded8d347 100644
--- a/kernel/arch/mips/include/asm/kvm_host.h
+++ b/kernel/arch/mips/include/asm/kvm_host.h
@@ -61,6 +61,7 @@
#define KVM_PRIVATE_MEM_SLOTS 0
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_HALT_POLL_NS_DEFAULT 500000
@@ -128,6 +129,7 @@ struct kvm_vcpu_stat {
u32 msa_disabled_exits;
u32 flush_dcache_exits;
u32 halt_successful_poll;
+ u32 halt_attempted_poll;
u32 halt_wakeup;
};
@@ -839,11 +841,13 @@ static inline void kvm_arch_hardware_unsetup(void) {}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_free_memslot(struct kvm *kvm,
struct kvm_memory_slot *free, struct kvm_memory_slot *dont) {}
-static inline void kvm_arch_memslots_updated(struct kvm *kvm) {}
+static inline void kvm_arch_memslots_updated(struct kvm *kvm, struct kvm_memslots *slots) {}
static inline void kvm_arch_flush_shadow_all(struct kvm *kvm) {}
static inline void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
struct kvm_memory_slot *slot) {}
static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
#endif /* __MIPS_KVM_HOST_H__ */
diff --git a/kernel/arch/mips/include/asm/linkage.h b/kernel/arch/mips/include/asm/linkage.h
index 2767dda9e..99651b0ea 100644
--- a/kernel/arch/mips/include/asm/linkage.h
+++ b/kernel/arch/mips/include/asm/linkage.h
@@ -5,7 +5,6 @@
#include <asm/asm.h>
#endif
-#define __weak __attribute__((weak))
#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
#define SYSCALL_ALIAS(alias, name) \
asm ( #alias " = " #name "\n\t.globl " #alias)
diff --git a/kernel/arch/mips/include/asm/maar.h b/kernel/arch/mips/include/asm/maar.h
index 6c62b0f89..21d9607c8 100644
--- a/kernel/arch/mips/include/asm/maar.h
+++ b/kernel/arch/mips/include/asm/maar.h
@@ -26,7 +26,7 @@
*
* Return: The number of MAAR pairs configured.
*/
-unsigned __weak platform_maar_init(unsigned num_pairs);
+unsigned platform_maar_init(unsigned num_pairs);
/**
* write_maar_pair() - write to a pair of MAARs
@@ -66,6 +66,15 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
}
/**
+ * maar_init() - initialise MAARs
+ *
+ * Performs initialisation of MAARs for the current CPU, making use of the
+ * platforms implementation of platform_maar_init where necessary and
+ * duplicating the setup it provides on secondary CPUs.
+ */
+extern void maar_init(void);
+
+/**
* struct maar_config - MAAR configuration data
* @lower: The lowest address that the MAAR pair will affect. Must be
* aligned to a 2^16 byte boundary.
diff --git a/kernel/arch/mips/include/asm/mach-ar7/ar7.h b/kernel/arch/mips/include/asm/mach-ar7/ar7.h
index a47ea0c85..468cbd61b 100644
--- a/kernel/arch/mips/include/asm/mach-ar7/ar7.h
+++ b/kernel/arch/mips/include/asm/mach-ar7/ar7.h
@@ -203,4 +203,8 @@ static inline void ar7_device_off(u32 bit)
int __init ar7_gpio_init(void);
void __init ar7_init_clocks(void);
+/* Board specific GPIO functions */
+int ar7_gpio_enable(unsigned gpio);
+int ar7_gpio_disable(unsigned gpio);
+
#endif /* __AR7_H__ */
diff --git a/kernel/arch/mips/include/asm/mach-ar7/gpio.h b/kernel/arch/mips/include/asm/mach-ar7/gpio.h
deleted file mode 100644
index c177cd1ee..000000000
--- a/kernel/arch/mips/include/asm/mach-ar7/gpio.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Florian Fainelli <florian@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __AR7_GPIO_H__
-#define __AR7_GPIO_H__
-
-#include <asm/mach-ar7/ar7.h>
-
-#define AR7_GPIO_MAX 32
-#define TITAN_GPIO_MAX 51
-#define NR_BUILTIN_GPIO TITAN_GPIO_MAX
-
-#define gpio_to_irq(gpio) -1
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-/* Board specific GPIO functions */
-int ar7_gpio_enable(unsigned gpio);
-int ar7_gpio_disable(unsigned gpio);
-
-#include <asm-generic/gpio.h>
-
-#endif
diff --git a/kernel/arch/mips/include/asm/mach-ath25/gpio.h b/kernel/arch/mips/include/asm/mach-ath25/gpio.h
deleted file mode 100644
index 713564b8e..000000000
--- a/kernel/arch/mips/include/asm/mach-ath25/gpio.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_MACH_ATH25_GPIO_H
-#define __ASM_MACH_ATH25_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-static inline int irq_to_gpio(unsigned irq)
-{
- return -EINVAL;
-}
-
-#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/kernel/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index cd41e93bc..aa3800c82 100644
--- a/kernel/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/kernel/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -157,8 +157,8 @@
#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10
#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14
-#define AR71XX_PLL_DIV_SHIFT 3
-#define AR71XX_PLL_DIV_MASK 0x1f
+#define AR71XX_PLL_FB_SHIFT 3
+#define AR71XX_PLL_FB_MASK 0x1f
#define AR71XX_CPU_DIV_SHIFT 16
#define AR71XX_CPU_DIV_MASK 0x3
#define AR71XX_DDR_DIV_SHIFT 18
@@ -169,8 +169,8 @@
#define AR724X_PLL_REG_CPU_CONFIG 0x00
#define AR724X_PLL_REG_PCIE_CONFIG 0x18
-#define AR724X_PLL_DIV_SHIFT 0
-#define AR724X_PLL_DIV_MASK 0x3ff
+#define AR724X_PLL_FB_SHIFT 0
+#define AR724X_PLL_FB_MASK 0x3ff
#define AR724X_PLL_REF_DIV_SHIFT 10
#define AR724X_PLL_REF_DIV_MASK 0xf
#define AR724X_AHB_DIV_SHIFT 19
@@ -183,8 +183,8 @@
#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14
#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18
-#define AR913X_PLL_DIV_SHIFT 0
-#define AR913X_PLL_DIV_MASK 0x3ff
+#define AR913X_PLL_FB_SHIFT 0
+#define AR913X_PLL_FB_MASK 0x3ff
#define AR913X_DDR_DIV_SHIFT 22
#define AR913X_DDR_DIV_MASK 0x3
#define AR913X_AHB_DIV_SHIFT 19
diff --git a/kernel/arch/mips/include/asm/mach-ath79/ath79.h b/kernel/arch/mips/include/asm/mach-ath79/ath79.h
index 1557934aa..4eee221b0 100644
--- a/kernel/arch/mips/include/asm/mach-ath79/ath79.h
+++ b/kernel/arch/mips/include/asm/mach-ath79/ath79.h
@@ -115,7 +115,8 @@ static inline int soc_is_qca955x(void)
return soc_is_qca9556() || soc_is_qca9558();
}
-extern void __iomem *ath79_ddr_base;
+void ath79_ddr_set_pci_windows(void);
+
extern void __iomem *ath79_pll_base;
extern void __iomem *ath79_reset_base;
diff --git a/kernel/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/kernel/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
index aa2283e60..aa71216ed 100644
--- a/kernel/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
+++ b/kernel/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
@@ -16,8 +16,4 @@ struct ath79_spi_platform_data {
unsigned num_chipselect;
};
-struct ath79_spi_controller_data {
- unsigned gpio;
-};
-
#endif /* _ATH79_SPI_PLATFORM_H */
diff --git a/kernel/arch/mips/include/asm/mach-ath79/gpio.h b/kernel/arch/mips/include/asm/mach-ath79/gpio.h
deleted file mode 100644
index 60dcb6278..000000000
--- a/kernel/arch/mips/include/asm/mach-ath79/gpio.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Atheros AR71XX/AR724X/AR913X GPIO API definitions
- *
- * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#ifndef __ASM_MACH_ATH79_GPIO_H
-#define __ASM_MACH_ATH79_GPIO_H
-
-#define ARCH_NR_GPIOS 64
-#include <asm-generic/gpio.h>
-
-int gpio_to_irq(unsigned gpio);
-int irq_to_gpio(unsigned irq);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-
-#define gpio_cansleep __gpio_cansleep
-
-#endif /* __ASM_MACH_ATH79_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/kernel/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
index 9785e4ebb..adde1fa50 100644
--- a/kernel/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
+++ b/kernel/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
@@ -266,6 +266,17 @@ static inline int alchemy_gpio1_to_irq(int gpio)
return -ENXIO;
}
+/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
+ * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this
+ * register enables use of GPIOs as wake source.
+ */
+static inline void alchemy_gpio1_input_enable(void)
+{
+ void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+ __raw_writel(0, base + 0x110); /* the write op is key */
+ wmb();
+}
+
/*
* GPIO2 block macros for common linux GPIO functions. The 'gpio'
* parameter must be in range of ALCHEMY_GPIO2_BASE..ALCHEMY_GPIO2_MAX.
@@ -518,141 +529,4 @@ static inline int alchemy_irq_to_gpio(int irq)
return -ENXIO;
}
-/**********************************************************************/
-
-/* Linux gpio framework integration.
- *
- * 4 use cases of Au1000-Au1200 GPIOS:
- *(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
- * Board must register gpiochips.
- *(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
- * 2 (1 for Au1000) gpio_chips are registered.
- *
- *(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
- * the boards' gpio.h must provide the linux gpio wrapper functions,
- *
- *(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
- * inlinable gpio functions are provided which enable access to the
- * Au1000 gpios only by using the numbers straight out of the data-
- * sheets.
-
- * Cases 1 and 3 are intended for boards which want to provide their own
- * GPIO namespace and -operations (i.e. for example you have 8 GPIOs
- * which are in part provided by spare Au1000 GPIO pins and in part by
- * an external FPGA but you still want them to be accssible in linux
- * as gpio0-7. The board can of course use the alchemy_gpioX_* functions
- * as required).
- */
-
-#ifndef CONFIG_GPIOLIB
-
-#ifdef CONFIG_ALCHEMY_GPIOINT_AU1000
-
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (4) */
-
-static inline int gpio_direction_input(int gpio)
-{
- return alchemy_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(int gpio, int v)
-{
- return alchemy_gpio_direction_output(gpio, v);
-}
-
-static inline int gpio_get_value(int gpio)
-{
- return alchemy_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(int gpio, int v)
-{
- alchemy_gpio_set_value(gpio, v);
-}
-
-static inline int gpio_get_value_cansleep(unsigned gpio)
-{
- return gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value_cansleep(unsigned gpio, int value)
-{
- gpio_set_value(gpio, value);
-}
-
-static inline int gpio_is_valid(int gpio)
-{
- return alchemy_gpio_is_valid(gpio);
-}
-
-static inline int gpio_cansleep(int gpio)
-{
- return alchemy_gpio_cansleep(gpio);
-}
-
-static inline int gpio_to_irq(int gpio)
-{
- return alchemy_gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(int irq)
-{
- return alchemy_irq_to_gpio(irq);
-}
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
- return 0;
-}
-
-static inline int gpio_request_one(unsigned gpio,
- unsigned long flags, const char *label)
-{
- return 0;
-}
-
-static inline int gpio_request_array(struct gpio *array, size_t num)
-{
- return 0;
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-}
-
-static inline void gpio_free_array(struct gpio *array, size_t num)
-{
-}
-
-static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
-{
- return -ENOSYS;
-}
-
-static inline int gpio_export(unsigned gpio, bool direction_may_change)
-{
- return -ENOSYS;
-}
-
-static inline int gpio_export_link(struct device *dev, const char *name,
- unsigned gpio)
-{
- return -ENOSYS;
-}
-
-static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
-{
- return -ENOSYS;
-}
-
-static inline void gpio_unexport(unsigned gpio)
-{
-}
-
-#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
-#endif /* CONFIG_ALCHEMY_GPIOINT_AU1000 */
-
-#endif /* !CONFIG_GPIOLIB */
-
#endif /* _ALCHEMY_GPIO_AU1000_H_ */
diff --git a/kernel/arch/mips/include/asm/mach-au1x00/gpio.h b/kernel/arch/mips/include/asm/mach-au1x00/gpio.h
deleted file mode 100644
index 22e7ff17f..000000000
--- a/kernel/arch/mips/include/asm/mach-au1x00/gpio.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Alchemy GPIO support.
- *
- * With CONFIG_GPIOLIB=y different types of on-chip GPIO can be supported within
- * the same kernel image.
- * With CONFIG_GPIOLIB=n, your board must select ALCHEMY_GPIOINT_AU1XXX for the
- * appropriate CPU type (AU1000 currently).
- */
-
-#ifndef _ALCHEMY_GPIO_H_
-#define _ALCHEMY_GPIO_H_
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-au1x00/gpio-au1000.h>
-#include <asm/mach-au1x00/gpio-au1300.h>
-
-/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
- * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this
- * register enables use of GPIOs as wake source.
- */
-static inline void alchemy_gpio1_input_enable(void)
-{
- void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
- __raw_writel(0, base + 0x110); /* the write op is key */
- wmb();
-}
-
-
-/* Linux gpio framework integration.
-*
-* 4 use cases of Alchemy GPIOS:
-*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
-* Board must register gpiochips.
-*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
-* A gpiochip for the 75 GPIOs is registered.
-*
-*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
-* the boards' gpio.h must provide the linux gpio wrapper functions,
-*
-*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
-* inlinable gpio functions are provided which enable access to the
-* Au1300 gpios only by using the numbers straight out of the data-
-* sheets.
-
-* Cases 1 and 3 are intended for boards which want to provide their own
-* GPIO namespace and -operations (i.e. for example you have 8 GPIOs
-* which are in part provided by spare Au1300 GPIO pins and in part by
-* an external FPGA but you still want them to be accssible in linux
-* as gpio0-7. The board can of course use the alchemy_gpioX_* functions
-* as required).
-*/
-
-#ifdef CONFIG_GPIOLIB
-
-/* wraps the cpu-dependent irq_to_gpio functions */
-/* FIXME: gpiolib needs an irq_to_gpio hook */
-static inline int __au_irq_to_gpio(unsigned int irq)
-{
- switch (alchemy_get_cputype()) {
- case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
- return alchemy_irq_to_gpio(irq);
- case ALCHEMY_CPU_AU1300:
- return au1300_irq_to_gpio(irq);
- }
- return -EINVAL;
-}
-
-
-/* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
-#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (2) */
-
-/* get everything through gpiolib */
-#define gpio_to_irq __gpio_to_irq
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define irq_to_gpio __au_irq_to_gpio
-
-#include <asm-generic/gpio.h>
-
-#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
-
-
-#endif /* CONFIG_GPIOLIB */
-
-#endif /* _ALCHEMY_GPIO_H_ */
diff --git a/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h b/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
index 8ed77f618..71e4096a2 100644
--- a/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
+++ b/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
@@ -48,15 +48,6 @@ extern enum bcm47xx_bus_type bcm47xx_bus_type;
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
bool fallback);
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
- const char *prefix);
-#endif
-#ifdef CONFIG_BCM47XX_BCMA
-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/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
index c41d1dce1..2afb84072 100644
--- a/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/kernel/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -80,6 +80,8 @@ enum bcm47xx_board {
BCM47XX_BOARD_LINKSYS_WRT610NV2,
BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+ BCM47XX_BOARD_LUXUL_XWR_1750_V1,
+
BCM47XX_BOARD_MICROSOFT_MN700,
BCM47XX_BOARD_MOTOROLA_WE800G,
diff --git a/kernel/arch/mips/include/asm/mach-bcm47xx/gpio.h b/kernel/arch/mips/include/asm/mach-bcm47xx/gpio.h
deleted file mode 100644
index 90daefa24..000000000
--- a/kernel/arch/mips/include/asm/mach-bcm47xx/gpio.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __ASM_MIPS_MACH_BCM47XX_GPIO_H
-#define __ASM_MIPS_MACH_BCM47XX_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-static inline int irq_to_gpio(unsigned int irq)
-{
- return -EINVAL;
-}
-
-#endif
diff --git a/kernel/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/kernel/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
index 25737655d..dd2995488 100644
--- a/kernel/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+++ b/kernel/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
@@ -7,48 +7,4 @@
int __init bcm63xx_spi_register(void);
-struct bcm63xx_spi_pdata {
- unsigned int fifo_size;
- unsigned int msg_type_shift;
- unsigned int msg_ctl_width;
- int bus_num;
- int num_chipselect;
-};
-
-enum bcm63xx_regs_spi {
- SPI_CMD,
- SPI_INT_STATUS,
- SPI_INT_MASK_ST,
- SPI_INT_MASK,
- SPI_ST,
- SPI_CLK_CFG,
- SPI_FILL_BYTE,
- SPI_MSG_TAIL,
- SPI_RX_TAIL,
- SPI_MSG_CTL,
- SPI_MSG_DATA,
- SPI_RX_DATA,
-};
-
-#define __GEN_SPI_REGS_TABLE(__cpu) \
- [SPI_CMD] = SPI_## __cpu ##_CMD, \
- [SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \
- [SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \
- [SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \
- [SPI_ST] = SPI_## __cpu ##_ST, \
- [SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \
- [SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \
- [SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \
- [SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \
- [SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \
- [SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \
- [SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA,
-
-static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
-{
- extern const unsigned long *bcm63xx_regs_spi;
-
- return bcm63xx_regs_spi[reg];
-}
-
#endif /* BCM63XX_DEV_SPI_H */
diff --git a/kernel/arch/mips/include/asm/mach-bcm63xx/gpio.h b/kernel/arch/mips/include/asm/mach-bcm63xx/gpio.h
deleted file mode 100644
index 1eb534de8..000000000
--- a/kernel/arch/mips/include/asm/mach-bcm63xx/gpio.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_MIPS_MACH_BCM63XX_GPIO_H
-#define __ASM_MIPS_MACH_BCM63XX_GPIO_H
-
-#include <bcm63xx_gpio.h>
-
-#define gpio_to_irq(gpio) -1
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_MIPS_MACH_BCM63XX_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-bcm63xx/spaces.h b/kernel/arch/mips/include/asm/mach-bcm63xx/spaces.h
index 61e750fb4..1410ed0da 100644
--- a/kernel/arch/mips/include/asm/mach-bcm63xx/spaces.h
+++ b/kernel/arch/mips/include/asm/mach-bcm63xx/spaces.h
@@ -10,7 +10,7 @@
#ifndef _ASM_BCM63XX_SPACES_H
#define _ASM_BCM63XX_SPACES_H
-#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000)
+#include <asm/bmips-spaces.h>
#include <asm/mach-generic/spaces.h>
diff --git a/kernel/arch/mips/include/asm/mach-bmips/spaces.h b/kernel/arch/mips/include/asm/mach-bmips/spaces.h
index 1b05bddc8..c59b28fd9 100644
--- a/kernel/arch/mips/include/asm/mach-bmips/spaces.h
+++ b/kernel/arch/mips/include/asm/mach-bmips/spaces.h
@@ -11,7 +11,7 @@
#define _ASM_BMIPS_SPACES_H
/* Avoid collisions with system base register (SBR) region on BMIPS3300 */
-#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000)
+#include <asm/bmips-spaces.h>
#include <asm/mach-generic/spaces.h>
diff --git a/kernel/arch/mips/include/asm/mach-cavium-octeon/gpio.h b/kernel/arch/mips/include/asm/mach-cavium-octeon/gpio.h
deleted file mode 100644
index 34e9f7aab..000000000
--- a/kernel/arch/mips/include/asm/mach-cavium-octeon/gpio.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __ASM_MACH_CAVIUM_OCTEON_GPIO_H
-#define __ASM_MACH_CAVIUM_OCTEON_GPIO_H
-
-#ifdef CONFIG_GPIOLIB
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#else
-int gpio_request(unsigned gpio, const char *label);
-void gpio_free(unsigned gpio);
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-#endif
-
-#include <asm-generic/gpio.h>
-
-#define gpio_to_irq __gpio_to_irq
-
-#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/kernel/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
index bdf045fb0..21eae03d7 100644
--- a/kernel/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
+++ b/kernel/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
@@ -14,6 +14,13 @@
/* Generic ones first. */
#define cpu_has_tlb 1
+#define cpu_has_tlbinv 0
+#define cpu_has_segments 0
+#define cpu_has_eva 0
+#define cpu_has_htw 0
+#define cpu_has_rixiex 0
+#define cpu_has_maar 0
+#define cpu_has_rw_llb 0
#define cpu_has_tx39_cache 0
#define cpu_has_divec 0
#define cpu_has_prefetch 0
@@ -24,6 +31,7 @@
#define cpu_has_mips3d 0
#define cpu_has_smartmips 0
#define cpu_has_rixi 0
+#define cpu_has_xpa 0
#define cpu_has_vtag_icache 0
#define cpu_has_ic_fills_f_dc 0
#define cpu_has_pindexed_dcache 0
@@ -36,11 +44,18 @@
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
#define cpu_has_dsp 0
+#define cpu_has_dsp2 0
#define cpu_has_mipsmt 0
#define cpu_has_userlocal 0
+#define cpu_hwrena_impl_bits 0
+#define cpu_has_perf_cntr_intr_bit 0
+#define cpu_has_vz 0
+#define cpu_has_fre 0
+#define cpu_has_cdmm 0
/* R3k-specific ones. */
#ifdef CONFIG_CPU_R3000
+#define cpu_has_3kex 1
#define cpu_has_4kex 0
#define cpu_has_3k_cache 1
#define cpu_has_4k_cache 0
@@ -63,6 +78,7 @@
/* R4k-specific ones. */
#ifdef CONFIG_CPU_R4X00
+#define cpu_has_3kex 0
#define cpu_has_4kex 1
#define cpu_has_3k_cache 0
#define cpu_has_4k_cache 1
diff --git a/kernel/arch/mips/include/asm/mach-generic/gpio.h b/kernel/arch/mips/include/asm/mach-generic/gpio.h
deleted file mode 100644
index b4e70208d..000000000
--- a/kernel/arch/mips/include/asm/mach-generic/gpio.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __ASM_MACH_GENERIC_GPIO_H
-#define __ASM_MACH_GENERIC_GPIO_H
-
-#ifdef CONFIG_GPIOLIB
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#else
-int gpio_request(unsigned gpio, const char *label);
-void gpio_free(unsigned gpio);
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-void gpio_set_value(unsigned gpio, int value);
-#endif
-int gpio_to_irq(unsigned gpio);
-int irq_to_gpio(unsigned irq);
-
-#include <asm-generic/gpio.h> /* cansleep wrappers */
-
-#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-generic/irq.h b/kernel/arch/mips/include/asm/mach-generic/irq.h
index 050e18bb1..be546a0f6 100644
--- a/kernel/arch/mips/include/asm/mach-generic/irq.h
+++ b/kernel/arch/mips/include/asm/mach-generic/irq.h
@@ -18,7 +18,7 @@
#endif
#endif
-#ifdef CONFIG_IRQ_CPU
+#ifdef CONFIG_IRQ_MIPS_CPU
#ifndef MIPS_CPU_IRQ_BASE
#ifdef CONFIG_I8259
@@ -34,7 +34,7 @@
#endif
#endif
-#endif /* CONFIG_IRQ_CPU */
+#endif /* CONFIG_IRQ_MIPS_CPU */
#ifdef CONFIG_MIPS_GIC
#ifndef MIPS_GIC_IRQ_BASE
diff --git a/kernel/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h b/kernel/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
index d6111aa2e..7449794ea 100644
--- a/kernel/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
+++ b/kernel/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
@@ -11,47 +11,69 @@
#include <asm/cpu.h>
/*
- * IP27 only comes with R10000 family processors all using the same config
+ * IP27 only comes with R1x000 family processors, all using the same config
*/
-#define cpu_has_watch 1
-#define cpu_has_mips16 0
-#define cpu_has_divec 0
-#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 0
-#define cpu_has_ejtag 0
+#define cpu_has_tlb 1
+#define cpu_has_tlbinv 0
+#define cpu_has_segments 0
+#define cpu_has_eva 0
+#define cpu_has_htw 0
+#define cpu_has_rixiex 0
+#define cpu_has_maar 0
+#define cpu_has_rw_llb 0
+#define cpu_has_3kex 0
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_6k_cache 0
+#define cpu_has_8k_cache 0
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 1
+#define cpu_has_nofpuex 0
+#define cpu_has_32fpr 1
+#define cpu_has_counter 1
+#define cpu_has_watch 1
+#define cpu_has_64bits 1
+#define cpu_has_divec 0
+#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 0
+#define cpu_has_ejtag 0
+#define cpu_has_llsc 1
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+#define cpu_has_rixi 0
+#define cpu_has_xpa 0
+#define cpu_has_vtag_icache 0
+#define cpu_has_dc_aliases 0
+#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_llsc 1
-#define cpu_has_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_dsp 0
-#define cpu_has_dsp2 0
#define cpu_icache_snoops_remote_store 1
-#define cpu_has_mipsmt 0
-#define cpu_has_userlocal 0
-#define cpu_has_nofpuex 0
-#define cpu_has_64bits 1
-
-#define cpu_has_4kex 1
-#define cpu_has_3k_cache 0
-#define cpu_has_6k_cache 0
-#define cpu_has_4k_cache 1
-#define cpu_has_8k_cache 0
-#define cpu_has_tx39_cache 0
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+#define cpu_has_mips32r6 0
+#define cpu_has_mips64r6 0
+#define cpu_has_dsp 0
+#define cpu_has_dsp2 0
+#define cpu_has_mipsmt 0
+#define cpu_has_userlocal 0
#define cpu_has_inclusive_pcaches 1
+#define cpu_hwrena_impl_bits 0
+#define cpu_has_perf_cntr_intr_bit 0
+#define cpu_has_vz 0
+#define cpu_has_fre 0
+#define cpu_has_cdmm 0
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 64
-#define cpu_scache_line_size() 128
-
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 0
-#define cpu_has_mips64r1 0
-#define cpu_has_mips64r2 0
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 64
+#define cpu_scache_line_size() 128
#endif /* __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H */
diff --git a/kernel/arch/mips/include/asm/mach-jz4740/clock.h b/kernel/arch/mips/include/asm/mach-jz4740/clock.h
index 16659cd76..104d2dfe1 100644
--- a/kernel/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/kernel/arch/mips/include/asm/mach-jz4740/clock.h
@@ -22,6 +22,9 @@ enum jz4740_wait_mode {
void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
+void jz4740_clock_suspend(void);
+void jz4740_clock_resume(void);
+
void jz4740_clock_udc_enable_auto_suspend(void);
void jz4740_clock_udc_disable_auto_suspend(void);
diff --git a/kernel/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h b/kernel/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
index a225baaa2..0933f94a1 100644
--- a/kernel/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
+++ b/kernel/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
@@ -12,8 +12,6 @@
#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 0
#define cpu_has_watch 1
#define cpu_has_divec 1
@@ -34,7 +32,6 @@
#define cpu_has_ic_fills_f_dc 0
#define cpu_has_pindexed_dcache 0
#define cpu_has_mips32r1 1
-#define cpu_has_mips32r2 0
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
#define cpu_has_dsp 0
diff --git a/kernel/arch/mips/include/asm/mach-jz4740/gpio.h b/kernel/arch/mips/include/asm/mach-jz4740/gpio.h
index eaacba79c..bf8c3e186 100644
--- a/kernel/arch/mips/include/asm/mach-jz4740/gpio.h
+++ b/kernel/arch/mips/include/asm/mach-jz4740/gpio.h
@@ -73,8 +73,6 @@ int jz_gpio_port_direction_output(int port, uint32_t mask);
void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask);
uint32_t jz_gpio_port_get_value(int port, uint32_t mask);
-#include <asm/mach-generic/gpio.h>
-
#define JZ_GPIO_PORTA(x) ((x) + 32 * 0)
#define JZ_GPIO_PORTB(x) ((x) + 32 * 1)
#define JZ_GPIO_PORTC(x) ((x) + 32 * 2)
diff --git a/kernel/arch/mips/include/asm/mach-jz4740/irq.h b/kernel/arch/mips/include/asm/mach-jz4740/irq.h
index df5073674..9b439fc21 100644
--- a/kernel/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/kernel/arch/mips/include/asm/mach-jz4740/irq.h
@@ -19,6 +19,12 @@
#define MIPS_CPU_IRQ_BASE 0
#define JZ4740_IRQ_BASE 8
+#ifdef CONFIG_MACH_JZ4740
+# define NR_INTC_IRQS 32
+#else
+# define NR_INTC_IRQS 64
+#endif
+
/* 1st-level interrupts */
#define JZ4740_IRQ(x) (JZ4740_IRQ_BASE + (x))
#define JZ4740_IRQ_I2C JZ4740_IRQ(1)
@@ -44,13 +50,15 @@
#define JZ4740_IRQ_IPU JZ4740_IRQ(29)
#define JZ4740_IRQ_LCD JZ4740_IRQ(30)
+#define JZ4780_IRQ_TCU2 JZ4740_IRQ(25)
+
/* 2nd-level interrupts */
-#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (x))
+#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(NR_INTC_IRQS) + (x))
#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
-#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x))
+#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(NR_INTC_IRQS + 16) + (x))
-#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(176)
+#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(NR_INTC_IRQS + 144)
#define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
diff --git a/kernel/arch/mips/include/asm/mach-jz4740/platform.h b/kernel/arch/mips/include/asm/mach-jz4740/platform.h
index 069b43a9d..32cfbe6a1 100644
--- a/kernel/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/kernel/arch/mips/include/asm/mach-jz4740/platform.h
@@ -35,6 +35,4 @@ extern struct platform_device jz4740_wdt_device;
extern struct platform_device jz4740_pwm_device;
extern struct platform_device jz4740_dma_device;
-void jz4740_serial_device_register(void);
-
#endif
diff --git a/kernel/arch/mips/include/asm/mach-lantiq/gpio.h b/kernel/arch/mips/include/asm/mach-lantiq/gpio.h
deleted file mode 100644
index 9ba1caebc..000000000
--- a/kernel/arch/mips/include/asm/mach-lantiq/gpio.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H
-#define __ASM_MIPS_MACH_LANTIQ_GPIO_H
-
-#define gpio_to_irq __gpio_to_irq
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-#include <asm-generic/gpio.h>
-
-#endif
diff --git a/kernel/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/kernel/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 133336b49..dd6005b75 100644
--- a/kernel/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/kernel/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -35,6 +35,17 @@
#define SOC_ID_VRX268_2 0x00C /* v1.2 */
#define SOC_ID_GRX288_2 0x00D /* v1.2 */
#define SOC_ID_GRX282_2 0x00E /* v1.2 */
+#define SOC_ID_VRX220 0x000
+
+#define SOC_ID_ARX362 0x004
+#define SOC_ID_ARX368 0x005
+#define SOC_ID_ARX382 0x007
+#define SOC_ID_ARX388 0x008
+#define SOC_ID_URX388 0x009
+#define SOC_ID_GRX383 0x010
+#define SOC_ID_GRX369 0x011
+#define SOC_ID_GRX387 0x00F
+#define SOC_ID_GRX389 0x012
/* SoC Types */
#define SOC_TYPE_DANUBE 0x01
@@ -43,6 +54,9 @@
#define SOC_TYPE_VR9 0x04 /* v1.1 */
#define SOC_TYPE_VR9_2 0x05 /* v1.2 */
#define SOC_TYPE_AMAZON_SE 0x06
+#define SOC_TYPE_AR10 0x07
+#define SOC_TYPE_GRX390 0x08
+#define SOC_TYPE_VRX220 0x09
/* BOOT_SEL - find what boot media we have */
#define BS_EXT_ROM 0x0
diff --git a/kernel/arch/mips/include/asm/mach-loongson/gpio.h b/kernel/arch/mips/include/asm/mach-loongson/gpio.h
deleted file mode 100644
index b3b216904..000000000
--- a/kernel/arch/mips/include/asm/mach-loongson/gpio.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Loongson GPIO Support
- *
- * Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
- * Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
- * Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __LOONGSON_GPIO_H
-#define __LOONGSON_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-/* The chip can do interrupt
- * but it has not been tested and doc not clear
- */
-static inline int gpio_to_irq(int gpio)
-{
- return -EINVAL;
-}
-
-static inline int irq_to_gpio(int gpio)
-{
- return -EINVAL;
-}
-
-#endif /* __LOONGSON_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/workarounds.h b/kernel/arch/mips/include/asm/mach-loongson/workarounds.h
deleted file mode 100644
index e180c1422..000000000
--- a/kernel/arch/mips/include/asm/mach-loongson/workarounds.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_
-#define __ASM_MACH_LOONGSON_WORKAROUNDS_H_
-
-#define WORKAROUND_CPUFREQ 0x00000001
-#define WORKAROUND_CPUHOTPLUG 0x00000002
-
-#endif
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/cpufreq.h b/kernel/arch/mips/include/asm/mach-loongson32/cpufreq.h
index e7765ce30..6843fa1a6 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/cpufreq.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/cpufreq.h
@@ -10,8 +10,8 @@
*/
-#ifndef __ASM_MACH_LOONGSON1_CPUFREQ_H
-#define __ASM_MACH_LOONGSON1_CPUFREQ_H
+#ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H
+#define __ASM_MACH_LOONGSON32_CPUFREQ_H
struct plat_ls1x_cpufreq {
const char *clk_name; /* CPU clk */
@@ -20,4 +20,4 @@ struct plat_ls1x_cpufreq {
unsigned int min_freq; /* in kHz */
};
-#endif /* __ASM_MACH_LOONGSON1_CPUFREQ_H */
+#endif /* __ASM_MACH_LOONGSON32_CPUFREQ_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/irq.h b/kernel/arch/mips/include/asm/mach-loongson32/irq.h
index 96bfb1c1c..0d35b994e 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/irq.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/irq.h
@@ -10,8 +10,8 @@
*/
-#ifndef __ASM_MACH_LOONGSON1_IRQ_H
-#define __ASM_MACH_LOONGSON1_IRQ_H
+#ifndef __ASM_MACH_LOONGSON32_IRQ_H
+#define __ASM_MACH_LOONGSON32_IRQ_H
/*
* CPU core Interrupt Numbers
@@ -70,4 +70,4 @@
#define NR_IRQS (MIPS_CPU_IRQS + LS1X_IRQS)
-#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
+#endif /* __ASM_MACH_LOONGSON32_IRQ_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/loongson1.h b/kernel/arch/mips/include/asm/mach-loongson32/loongson1.h
index 20e0c2b15..12aa129aa 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/loongson1.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/loongson1.h
@@ -10,8 +10,8 @@
*/
-#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
-#define __ASM_MACH_LOONGSON1_LOONGSON1_H
+#ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H
+#define __ASM_MACH_LOONGSON32_LOONGSON1_H
#define DEFAULT_MEMSIZE 256 /* If no memsize provided */
@@ -47,4 +47,4 @@
#include <regs-pwm.h>
#include <regs-wdt.h>
-#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
+#endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/platform.h b/kernel/arch/mips/include/asm/mach-loongson32/platform.h
index 47de55e0c..c32f03f3f 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/platform.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/platform.h
@@ -8,8 +8,8 @@
*/
-#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H
-#define __ASM_MACH_LOONGSON1_PLATFORM_H
+#ifndef __ASM_MACH_LOONGSON32_PLATFORM_H
+#define __ASM_MACH_LOONGSON32_PLATFORM_H
#include <linux/platform_device.h>
@@ -23,4 +23,4 @@ extern struct platform_device ls1x_rtc_pdev;
extern void __init ls1x_clk_init(void);
extern void __init ls1x_serial_setup(struct platform_device *pdev);
-#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
+#endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/prom.h b/kernel/arch/mips/include/asm/mach-loongson32/prom.h
index 34859a4d4..a08503c0b 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/prom.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/prom.h
@@ -7,8 +7,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON1_PROM_H
-#define __ASM_MACH_LOONGSON1_PROM_H
+#ifndef __ASM_MACH_LOONGSON32_PROM_H
+#define __ASM_MACH_LOONGSON32_PROM_H
#include <linux/io.h>
#include <linux/init.h>
@@ -21,4 +21,4 @@ extern unsigned long memsize, highmemsize;
extern char *prom_getenv(char *name);
extern void __init prom_init_cmdline(void);
-#endif /* __ASM_MACH_LOONGSON1_PROM_H */
+#endif /* __ASM_MACH_LOONGSON32_PROM_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/regs-clk.h b/kernel/arch/mips/include/asm/mach-loongson32/regs-clk.h
index ee2445b10..1f5a715ac 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/regs-clk.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/regs-clk.h
@@ -9,8 +9,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
-#define __ASM_MACH_LOONGSON1_REGS_CLK_H
+#ifndef __ASM_MACH_LOONGSON32_REGS_CLK_H
+#define __ASM_MACH_LOONGSON32_REGS_CLK_H
#define LS1X_CLK_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x)))
@@ -48,4 +48,4 @@
#define BYPASS_DDR_WIDTH 1
#define BYPASS_CPU_WIDTH 1
-#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
+#endif /* __ASM_MACH_LOONGSON32_REGS_CLK_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/regs-mux.h b/kernel/arch/mips/include/asm/mach-loongson32/regs-mux.h
index fb1e36efa..8302d92f2 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/regs-mux.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/regs-mux.h
@@ -9,8 +9,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON1_REGS_MUX_H
-#define __ASM_MACH_LOONGSON1_REGS_MUX_H
+#ifndef __ASM_MACH_LOONGSON32_REGS_MUX_H
+#define __ASM_MACH_LOONGSON32_REGS_MUX_H
#define LS1X_MUX_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x)))
@@ -64,4 +64,4 @@
#define GMAC1_USE_PWM23 (0x1 << 1)
#define GMAC0_USE_PWM01 0x1
-#endif /* __ASM_MACH_LOONGSON1_REGS_MUX_H */
+#endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/regs-pwm.h b/kernel/arch/mips/include/asm/mach-loongson32/regs-pwm.h
index 99f2bcc58..69f174ed1 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/regs-pwm.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/regs-pwm.h
@@ -9,8 +9,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON1_REGS_PWM_H
-#define __ASM_MACH_LOONGSON1_REGS_PWM_H
+#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H
+#define __ASM_MACH_LOONGSON32_REGS_PWM_H
/* Loongson 1 PWM Timer Register Definitions */
#define PWM_CNT 0x0
@@ -26,4 +26,4 @@
#define PWM_OE (0x1 << 3)
#define CNT_EN 0x1
-#endif /* __ASM_MACH_LOONGSON1_REGS_PWM_H */
+#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/kernel/arch/mips/include/asm/mach-loongson32/regs-wdt.h
index c39ee982a..6644ab6d3 100644
--- a/kernel/arch/mips/include/asm/mach-loongson1/regs-wdt.h
+++ b/kernel/arch/mips/include/asm/mach-loongson32/regs-wdt.h
@@ -9,11 +9,11 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
-#define __ASM_MACH_LOONGSON1_REGS_WDT_H
+#ifndef __ASM_MACH_LOONGSON32_REGS_WDT_H
+#define __ASM_MACH_LOONGSON32_REGS_WDT_H
#define WDT_EN 0x0
#define WDT_TIMER 0x4
#define WDT_SET 0x8
-#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
+#endif /* __ASM_MACH_LOONGSON32_REGS_WDT_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/boot_param.h b/kernel/arch/mips/include/asm/mach-loongson64/boot_param.h
index fa8029265..d3f3258b7 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
-#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
+#ifndef __ASM_MACH_LOONGSON64_BOOT_PARAM_H_
+#define __ASM_MACH_LOONGSON64_BOOT_PARAM_H_
#define SYSTEM_RAM_LOW 1
#define SYSTEM_RAM_HIGH 2
diff --git a/kernel/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/kernel/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
index acc376897..98963c2c7 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
@@ -13,8 +13,8 @@
* loongson2f user manual.
*/
-#ifndef __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H
+#ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
#define cpu_dcache_line_size() 32
#define cpu_icache_line_size() 32
@@ -58,4 +58,4 @@
#define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3)
-#endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */
+#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536.h
index a0ee0cb77..a0ee0cb77 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_mfgpt.h
index 021d0172d..021d0172d 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_mfgpt.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_pci.h
index 8a7ecb4d5..8a7ecb4d5 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_pci.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_vsm.h
index 1f17c1815..1f17c1815 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/cs5536/cs5536_vsm.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson/dma-coherence.h b/kernel/arch/mips/include/asm/mach-loongson64/dma-coherence.h
index 4bf4e19f7..1602a9e9e 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/dma-coherence.h
@@ -8,8 +8,8 @@
* Author: Fuxin Zhang, zhangfx@lemote.com
*
*/
-#ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
-#define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
+#ifndef __ASM_MACH_LOONGSON64_DMA_COHERENCE_H
+#define __ASM_MACH_LOONGSON64_DMA_COHERENCE_H
#ifdef CONFIG_SWIOTLB
#include <linux/swiotlb.h>
@@ -82,4 +82,4 @@ static inline void plat_post_dma_flush(struct device *dev)
{
}
-#endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
+#endif /* __ASM_MACH_LOONGSON64_DMA_COHERENCE_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/irq.h b/kernel/arch/mips/include/asm/mach-loongson64/irq.h
index a281cca5f..d18c45c7c 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/irq.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/irq.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_LOONGSON_IRQ_H_
-#define __ASM_MACH_LOONGSON_IRQ_H_
+#ifndef __ASM_MACH_LOONGSON64_IRQ_H_
+#define __ASM_MACH_LOONGSON64_IRQ_H_
#include <boot_param.h>
@@ -40,4 +40,4 @@ extern void fixup_irqs(void);
extern void loongson3_ipi_interrupt(struct pt_regs *regs);
#include_next <irq.h>
-#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
+#endif /* __ASM_MACH_LOONGSON64_IRQ_H_ */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/kernel/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
index df5fca8ee..3f2f84f6c 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
@@ -8,8 +8,8 @@
* Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
* Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
*/
-#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
-#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+#ifndef __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H
+#define __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H
/*
* Override macros used in arch/mips/kernel/head.S.
@@ -49,4 +49,4 @@
#endif
.endm
-#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
+#endif /* __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/loongson.h b/kernel/arch/mips/include/asm/mach-loongson64/loongson.h
index 9783103fd..d1ff774ac 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -8,8 +8,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON_LOONGSON_H
-#define __ASM_MACH_LOONGSON_LOONGSON_H
+#ifndef __ASM_MACH_LOONGSON64_LOONGSON_H
+#define __ASM_MACH_LOONGSON64_LOONGSON_H
#include <linux/io.h>
#include <linux/init.h>
@@ -357,4 +357,4 @@ extern unsigned long _loongson_addrwincfg_base;
#endif /* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */
-#endif /* __ASM_MACH_LOONGSON_LOONGSON_H */
+#endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/loongson_hwmon.h b/kernel/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h
index 4431fc54a..4431fc54a 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/loongson_hwmon.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson/machine.h b/kernel/arch/mips/include/asm/mach-loongson64/machine.h
index cb2b60249..c52549bb4 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/machine.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/machine.h
@@ -8,8 +8,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON_MACHINE_H
-#define __ASM_MACH_LOONGSON_MACHINE_H
+#ifndef __ASM_MACH_LOONGSON64_MACHINE_H
+#define __ASM_MACH_LOONGSON64_MACHINE_H
#ifdef CONFIG_LEMOTE_FULOONG2E
@@ -30,4 +30,4 @@
#endif /* CONFIG_LOONGSON_MACH3X */
-#endif /* __ASM_MACH_LOONGSON_MACHINE_H */
+#endif /* __ASM_MACH_LOONGSON64_MACHINE_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/mc146818rtc.h b/kernel/arch/mips/include/asm/mach-loongson64/mc146818rtc.h
index ed7fe9783..ebdccfee5 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/mc146818rtc.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/mc146818rtc.h
@@ -7,8 +7,8 @@
*
* RTC routines for PC style attached Dallas chip.
*/
-#ifndef __ASM_MACH_LOONGSON_MC146818RTC_H
-#define __ASM_MACH_LOONGSON_MC146818RTC_H
+#ifndef __ASM_MACH_LOONGSON64_MC146818RTC_H
+#define __ASM_MACH_LOONGSON64_MC146818RTC_H
#include <linux/io.h>
@@ -33,4 +33,4 @@ static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
#endif
-#endif /* __ASM_MACH_LOONGSON_MC146818RTC_H */
+#endif /* __ASM_MACH_LOONGSON64_MC146818RTC_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/mem.h b/kernel/arch/mips/include/asm/mach-loongson64/mem.h
index f4a36d7db..75c16bead 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/mem.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/mem.h
@@ -8,8 +8,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON_MEM_H
-#define __ASM_MACH_LOONGSON_MEM_H
+#ifndef __ASM_MACH_LOONGSON64_MEM_H
+#define __ASM_MACH_LOONGSON64_MEM_H
/*
* high memory space
@@ -38,4 +38,4 @@
#define LOONGSON_MMIO_MEM_END 0x80000000
#endif
-#endif /* __ASM_MACH_LOONGSON_MEM_H */
+#endif /* __ASM_MACH_LOONGSON64_MEM_H */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/mmzone.h b/kernel/arch/mips/include/asm/mach-loongson64/mmzone.h
index 37c08a27b..c9f7e231e 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/mmzone.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/mmzone.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
- * Insititute of Computing Technology
+ * Institute of Computing Technology
* Author: Xiang Gao, gaoxiang@ict.ac.cn
* Huacai Chen, chenhc@lemote.com
* Xiaofu Meng, Shuangshuang Zhang
diff --git a/kernel/arch/mips/include/asm/mach-loongson/pci.h b/kernel/arch/mips/include/asm/mach-loongson64/pci.h
index 1212774f6..3401f5574 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/pci.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/pci.h
@@ -9,8 +9,8 @@
* option) any later version.
*/
-#ifndef __ASM_MACH_LOONGSON_PCI_H_
-#define __ASM_MACH_LOONGSON_PCI_H_
+#ifndef __ASM_MACH_LOONGSON64_PCI_H_
+#define __ASM_MACH_LOONGSON64_PCI_H_
extern struct pci_ops loongson_pci_ops;
@@ -52,4 +52,4 @@ extern struct pci_ops loongson_pci_ops;
#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
-#endif /* !__ASM_MACH_LOONGSON_PCI_H_ */
+#endif /* !__ASM_MACH_LOONGSON64_PCI_H_ */
diff --git a/kernel/arch/mips/include/asm/mach-loongson/spaces.h b/kernel/arch/mips/include/asm/mach-loongson64/spaces.h
index e2506ee90..c6040b9fc 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/spaces.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/spaces.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_MACH_LOONGSON_SPACES_H_
-#define __ASM_MACH_LOONGSON_SPACES_H_
+#ifndef __ASM_MACH_LOONGSON64_SPACES_H_
+#define __ASM_MACH_LOONGSON64_SPACES_H_
#if defined(CONFIG_64BIT)
#define CAC_BASE _AC(0x9800000000000000, UL)
diff --git a/kernel/arch/mips/include/asm/mach-loongson/topology.h b/kernel/arch/mips/include/asm/mach-loongson64/topology.h
index 0d8f3b55b..0d8f3b55b 100644
--- a/kernel/arch/mips/include/asm/mach-loongson/topology.h
+++ b/kernel/arch/mips/include/asm/mach-loongson64/topology.h
diff --git a/kernel/arch/mips/include/asm/mach-loongson64/workarounds.h b/kernel/arch/mips/include/asm/mach-loongson64/workarounds.h
new file mode 100644
index 000000000..e659f041e
--- /dev/null
+++ b/kernel/arch/mips/include/asm/mach-loongson64/workarounds.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_LOONGSON64_WORKAROUNDS_H_
+#define __ASM_MACH_LOONGSON64_WORKAROUNDS_H_
+
+#define WORKAROUND_CPUFREQ 0x00000001
+#define WORKAROUND_CPUHOTPLUG 0x00000002
+
+#endif
diff --git a/kernel/arch/mips/include/asm/mach-malta/malta-dtshim.h b/kernel/arch/mips/include/asm/mach-malta/malta-dtshim.h
new file mode 100644
index 000000000..cfd777663
--- /dev/null
+++ b/kernel/arch/mips/include/asm/mach-malta/malta-dtshim.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_MALTA_DTSHIM_H__
+#define __MIPS_MALTA_DTSHIM_H__
+
+#include <linux/init.h>
+
+#ifdef CONFIG_MIPS_MALTA
+
+extern void __init *malta_dt_shim(void *fdt);
+
+#else /* !CONFIG_MIPS_MALTA */
+
+static inline void *malta_dt_shim(void *fdt)
+{
+ return fdt;
+}
+
+#endif /* !CONFIG_MIPS_MALTA */
+
+#endif /* __MIPS_MALTA_DTSHIM_H__ */
diff --git a/kernel/arch/mips/include/asm/mach-pistachio/gpio.h b/kernel/arch/mips/include/asm/mach-pistachio/gpio.h
deleted file mode 100644
index 6c1649c27..000000000
--- a/kernel/arch/mips/include/asm/mach-pistachio/gpio.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Pistachio IRQ setup
- *
- * Copyright (C) 2014 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- */
-
-#ifndef __ASM_MACH_PISTACHIO_GPIO_H
-#define __ASM_MACH_PISTACHIO_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-#endif /* __ASM_MACH_PISTACHIO_GPIO_H */
diff --git a/kernel/arch/mips/include/asm/mach-ralink/mt7620.h b/kernel/arch/mips/include/asm/mach-ralink/mt7620.h
index 1976fb815..455d406e8 100644
--- a/kernel/arch/mips/include/asm/mach-ralink/mt7620.h
+++ b/kernel/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -13,17 +13,11 @@
#ifndef _MT7620_REGS_H_
#define _MT7620_REGS_H_
-enum mt762x_soc_type {
- MT762X_SOC_UNKNOWN = 0,
- MT762X_SOC_MT7620A,
- MT762X_SOC_MT7620N,
- MT762X_SOC_MT7628AN,
-};
-
#define MT7620_SYSC_BASE 0x10000000
#define SYSC_REG_CHIP_NAME0 0x00
#define SYSC_REG_CHIP_NAME1 0x04
+#define SYSC_REG_EFUSE_CFG 0x08
#define SYSC_REG_CHIP_REV 0x0c
#define SYSC_REG_SYSTEM_CONFIG0 0x10
#define SYSC_REG_SYSTEM_CONFIG1 0x14
diff --git a/kernel/arch/mips/include/asm/mach-ralink/ralink_regs.h b/kernel/arch/mips/include/asm/mach-ralink/ralink_regs.h
index bd9301449..4c9fba68c 100644
--- a/kernel/arch/mips/include/asm/mach-ralink/ralink_regs.h
+++ b/kernel/arch/mips/include/asm/mach-ralink/ralink_regs.h
@@ -13,6 +13,23 @@
#ifndef _RALINK_REGS_H_
#define _RALINK_REGS_H_
+enum ralink_soc_type {
+ RALINK_UNKNOWN = 0,
+ RT2880_SOC,
+ RT3883_SOC,
+ RT305X_SOC_RT3050,
+ RT305X_SOC_RT3052,
+ RT305X_SOC_RT3350,
+ RT305X_SOC_RT3352,
+ RT305X_SOC_RT5350,
+ MT762X_SOC_MT7620A,
+ MT762X_SOC_MT7620N,
+ MT762X_SOC_MT7621AT,
+ MT762X_SOC_MT7628AN,
+ MT762X_SOC_MT7688,
+};
+extern enum ralink_soc_type ralink_soc;
+
extern __iomem void *rt_sysc_membase;
extern __iomem void *rt_memc_membase;
diff --git a/kernel/arch/mips/include/asm/mach-ralink/rt305x.h b/kernel/arch/mips/include/asm/mach-ralink/rt305x.h
index 96f731bac..2eea79331 100644
--- a/kernel/arch/mips/include/asm/mach-ralink/rt305x.h
+++ b/kernel/arch/mips/include/asm/mach-ralink/rt305x.h
@@ -13,25 +13,16 @@
#ifndef _RT305X_REGS_H_
#define _RT305X_REGS_H_
-enum rt305x_soc_type {
- RT305X_SOC_UNKNOWN = 0,
- RT305X_SOC_RT3050,
- RT305X_SOC_RT3052,
- RT305X_SOC_RT3350,
- RT305X_SOC_RT3352,
- RT305X_SOC_RT5350,
-};
-
-extern enum rt305x_soc_type rt305x_soc;
+extern enum ralink_soc_type ralink_soc;
static inline int soc_is_rt3050(void)
{
- return rt305x_soc == RT305X_SOC_RT3050;
+ return ralink_soc == RT305X_SOC_RT3050;
}
static inline int soc_is_rt3052(void)
{
- return rt305x_soc == RT305X_SOC_RT3052;
+ return ralink_soc == RT305X_SOC_RT3052;
}
static inline int soc_is_rt305x(void)
@@ -41,17 +32,17 @@ static inline int soc_is_rt305x(void)
static inline int soc_is_rt3350(void)
{
- return rt305x_soc == RT305X_SOC_RT3350;
+ return ralink_soc == RT305X_SOC_RT3350;
}
static inline int soc_is_rt3352(void)
{
- return rt305x_soc == RT305X_SOC_RT3352;
+ return ralink_soc == RT305X_SOC_RT3352;
}
static inline int soc_is_rt5350(void)
{
- return rt305x_soc == RT305X_SOC_RT5350;
+ return ralink_soc == RT305X_SOC_RT5350;
}
#define RT305X_SYSC_BASE 0x10000000
diff --git a/kernel/arch/mips/include/asm/mach-rc32434/gpio.h b/kernel/arch/mips/include/asm/mach-rc32434/gpio.h
index 4dee0a342..db211212c 100644
--- a/kernel/arch/mips/include/asm/mach-rc32434/gpio.h
+++ b/kernel/arch/mips/include/asm/mach-rc32434/gpio.h
@@ -13,18 +13,6 @@
#ifndef _RC32434_GPIO_H_
#define _RC32434_GPIO_H_
-#include <linux/types.h>
-#include <asm-generic/gpio.h>
-
-#define NR_BUILTIN_GPIO 32
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-
-#define gpio_to_irq(gpio) (8 + 4 * 32 + gpio)
-#define irq_to_gpio(irq) (irq - (8 + 4 * 32))
-
struct rb532_gpio_reg {
u32 gpiofunc; /* GPIO Function Register
* gpiofunc[x]==0 bit = gpio
diff --git a/kernel/arch/mips/include/asm/mach-sibyte/war.h b/kernel/arch/mips/include/asm/mach-sibyte/war.h
index 0a227d426..520f8fc2c 100644
--- a/kernel/arch/mips/include/asm/mach-sibyte/war.h
+++ b/kernel/arch/mips/include/asm/mach-sibyte/war.h
@@ -13,8 +13,7 @@
#define R4600_V2_HIT_CACHEOP_WAR 0
#define R5432_CP0_INTERRUPT_WAR 0
-#if defined(CONFIG_SB1_PASS_1_WORKAROUNDS) || \
- defined(CONFIG_SB1_PASS_2_WORKAROUNDS)
+#if defined(CONFIG_SB1_PASS_2_WORKAROUNDS)
#ifndef __ASSEMBLY__
extern int sb1250_m3_workaround_needed(void);
diff --git a/kernel/arch/mips/include/asm/mach-xilfpga/irq.h b/kernel/arch/mips/include/asm/mach-xilfpga/irq.h
new file mode 100644
index 000000000..0132a5b91
--- /dev/null
+++ b/kernel/arch/mips/include/asm/mach-xilfpga/irq.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+#define __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+
+#define NR_IRQS 32
+
+#include_next <irq.h>
+
+#endif /* __MIPS_ASM_MACH_XILFPGA_IRQ_H__ */
diff --git a/kernel/arch/mips/include/asm/mips-cm.h b/kernel/arch/mips/include/asm/mips-cm.h
index 59c0901bd..6516e9da5 100644
--- a/kernel/arch/mips/include/asm/mips-cm.h
+++ b/kernel/arch/mips/include/asm/mips-cm.h
@@ -11,6 +11,8 @@
#ifndef __MIPS_ASM_MIPS_CM_H__
#define __MIPS_ASM_MIPS_CM_H__
+#include <linux/bitops.h>
+#include <linux/errno.h>
#include <linux/io.h>
#include <linux/types.h>
@@ -32,6 +34,29 @@ extern void __iomem *mips_cm_l2sync_base;
*/
extern phys_addr_t __mips_cm_phys_base(void);
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is determined by the version of the CM, with CM3
+ * introducing 64 bit GCRs and all prior CM versions having 32 bit GCRs.
+ * However we may run a kernel built for MIPS32 on a system with 64 bit GCRs,
+ * or vice-versa. This variable indicates the width of the memory accesses
+ * that the kernel will perform to GCRs, which may differ from the actual
+ * width of the GCRs.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
+/**
+ * mips_cm_error_report - Report CM cache errors
+ */
+#ifdef CONFIG_MIPS_CM
+extern void mips_cm_error_report(void);
+#else
+static inline void mips_cm_error_report(void) {}
+#endif
+
/**
* mips_cm_probe - probe for a Coherence Manager
*
@@ -89,20 +114,56 @@ static inline bool mips_cm_has_l2sync(void)
/* Macros to ease the creation of register access functions */
#define BUILD_CM_R_(name, off) \
-static inline u32 __iomem *addr_gcr_##name(void) \
+static inline unsigned long __iomem *addr_gcr_##name(void) \
{ \
- return (u32 __iomem *)(mips_cm_base + (off)); \
+ return (unsigned long __iomem *)(mips_cm_base + (off)); \
} \
\
-static inline u32 read_gcr_##name(void) \
+static inline u32 read32_gcr_##name(void) \
{ \
return __raw_readl(addr_gcr_##name()); \
+} \
+ \
+static inline u64 read64_gcr_##name(void) \
+{ \
+ void __iomem *addr = addr_gcr_##name(); \
+ u64 ret; \
+ \
+ if (mips_cm_is64) { \
+ ret = __raw_readq(addr); \
+ } else { \
+ ret = __raw_readl(addr); \
+ ret |= (u64)__raw_readl(addr + 0x4) << 32; \
+ } \
+ \
+ return ret; \
+} \
+ \
+static inline unsigned long read_gcr_##name(void) \
+{ \
+ if (mips_cm_is64) \
+ return read64_gcr_##name(); \
+ else \
+ return read32_gcr_##name(); \
}
#define BUILD_CM__W(name, off) \
-static inline void write_gcr_##name(u32 value) \
+static inline void write32_gcr_##name(u32 value) \
{ \
__raw_writel(value, addr_gcr_##name()); \
+} \
+ \
+static inline void write64_gcr_##name(u64 value) \
+{ \
+ __raw_writeq(value, addr_gcr_##name()); \
+} \
+ \
+static inline void write_gcr_##name(unsigned long value) \
+{ \
+ if (mips_cm_is64) \
+ write64_gcr_##name(value); \
+ else \
+ write32_gcr_##name(value); \
}
#define BUILD_CM_RW(name, off) \
@@ -143,6 +204,10 @@ BUILD_CM_RW(reg3_base, MIPS_CM_GCB_OFS + 0xc0)
BUILD_CM_RW(reg3_mask, MIPS_CM_GCB_OFS + 0xc8)
BUILD_CM_R_(gic_status, MIPS_CM_GCB_OFS + 0xd0)
BUILD_CM_R_(cpc_status, MIPS_CM_GCB_OFS + 0xf0)
+BUILD_CM_RW(l2_config, MIPS_CM_GCB_OFS + 0x130)
+BUILD_CM_RW(sys_config2, MIPS_CM_GCB_OFS + 0x150)
+BUILD_CM_RW(l2_pft_control, MIPS_CM_GCB_OFS + 0x300)
+BUILD_CM_RW(l2_pft_control_b, MIPS_CM_GCB_OFS + 0x308)
/* Core Local & Core Other register accessor functions */
BUILD_CM_Cx_RW(reset_release, 0x00)
@@ -188,9 +253,19 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_REV_MINOR_SHF 0
#define CM_GCR_REV_MINOR_MSK (_ULCAST_(0xff) << 0)
+#define CM_ENCODE_REV(major, minor) \
+ (((major) << CM_GCR_REV_MAJOR_SHF) | \
+ ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2 CM_ENCODE_REV(6, 0)
+#define CM_REV_CM2_5 CM_ENCODE_REV(7, 0)
+#define CM_REV_CM3 CM_ENCODE_REV(8, 0)
+
/* GCR_ERROR_CAUSE register fields */
#define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF 27
#define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK (_ULCAST_(0x1f) << 27)
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF 58
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_MSK GENMASK_ULL(63, 58)
#define CM_GCR_ERROR_CAUSE_ERRINFO_SHF 0
#define CM_GCR_ERROR_CAUSE_ERRINGO_MSK (_ULCAST_(0x7ffffff) << 0)
@@ -216,6 +291,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_CPC_BASE_CPCEN_SHF 0
#define CM_GCR_CPC_BASE_CPCEN_MSK (_ULCAST_(0x1) << 0)
+/* GCR_GIC_STATUS register fields */
+#define CM_GCR_GIC_STATUS_GICEX_SHF 0
+#define CM_GCR_GIC_STATUS_GICEX_MSK (_ULCAST_(0x1) << 0)
+
/* GCR_REGn_BASE register fields */
#define CM_GCR_REGn_BASE_BASEADDR_SHF 16
#define CM_GCR_REGn_BASE_BASEADDR_MSK (_ULCAST_(0xffff) << 16)
@@ -244,6 +323,34 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_CPC_STATUS_EX_SHF 0
#define CM_GCR_CPC_STATUS_EX_MSK (_ULCAST_(0x1) << 0)
+/* GCR_L2_CONFIG register fields */
+#define CM_GCR_L2_CONFIG_BYPASS_SHF 20
+#define CM_GCR_L2_CONFIG_BYPASS_MSK (_ULCAST_(0x1) << 20)
+#define CM_GCR_L2_CONFIG_SET_SIZE_SHF 12
+#define CM_GCR_L2_CONFIG_SET_SIZE_MSK (_ULCAST_(0xf) << 12)
+#define CM_GCR_L2_CONFIG_LINE_SIZE_SHF 8
+#define CM_GCR_L2_CONFIG_LINE_SIZE_MSK (_ULCAST_(0xf) << 8)
+#define CM_GCR_L2_CONFIG_ASSOC_SHF 0
+#define CM_GCR_L2_CONFIG_ASSOC_MSK (_ULCAST_(0xff) << 0)
+
+/* GCR_SYS_CONFIG2 register fields */
+#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF 0
+#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK (_ULCAST_(0xf) << 0)
+
+/* GCR_L2_PFT_CONTROL register fields */
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_SHF 12
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK (_ULCAST_(0xfffff) << 12)
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_SHF 8
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_MSK (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_NPFT_SHF 0
+#define CM_GCR_L2_PFT_CONTROL_NPFT_MSK (_ULCAST_(0xff) << 0)
+
+/* GCR_L2_PFT_CONTROL_B register fields */
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_SHF 8
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_MSK (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_SHF 0
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK (_ULCAST_(0xff) << 0)
+
/* GCR_Cx_COHERENCE register fields */
#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF 0
#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK (_ULCAST_(0xff) << 0)
@@ -252,11 +359,15 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_Cx_CONFIG_IOCUTYPE_SHF 10
#define CM_GCR_Cx_CONFIG_IOCUTYPE_MSK (_ULCAST_(0x3) << 10)
#define CM_GCR_Cx_CONFIG_PVPE_SHF 0
-#define CM_GCR_Cx_CONFIG_PVPE_MSK (_ULCAST_(0x1ff) << 0)
+#define CM_GCR_Cx_CONFIG_PVPE_MSK (_ULCAST_(0x3ff) << 0)
/* GCR_Cx_OTHER register fields */
#define CM_GCR_Cx_OTHER_CORENUM_SHF 16
#define CM_GCR_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xffff) << 16)
+#define CM3_GCR_Cx_OTHER_CORE_SHF 8
+#define CM3_GCR_Cx_OTHER_CORE_MSK (_ULCAST_(0x3f) << 8)
+#define CM3_GCR_Cx_OTHER_VP_SHF 0
+#define CM3_GCR_Cx_OTHER_VP_MSK (_ULCAST_(0x7) << 0)
/* GCR_Cx_RESET_BASE register fields */
#define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF 12
@@ -319,4 +430,80 @@ static inline int mips_cm_l2sync(void)
return 0;
}
+/**
+ * mips_cm_revision() - return CM revision
+ *
+ * Return: The revision of the CM, from GCR_REV, or 0 if no CM is present. The
+ * return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+ if (!mips_cm_present())
+ return 0;
+
+ return read_gcr_rev();
+}
+
+/**
+ * mips_cm_max_vp_width() - return the width in bits of VP indices
+ *
+ * Return: the width, in bits, of VP indices in fields that combine core & VP
+ * indices.
+ */
+static inline unsigned int mips_cm_max_vp_width(void)
+{
+ extern int smp_num_siblings;
+
+ if (mips_cm_revision() >= CM_REV_CM3)
+ return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
+
+ return smp_num_siblings;
+}
+
+/**
+ * mips_cm_vp_id() - calculate the hardware VP ID for a CPU
+ * @cpu: the CPU whose VP ID to calculate
+ *
+ * Hardware such as the GIC uses identifiers for VPs which may not match the
+ * CPU numbers used by Linux. This function calculates the hardware VP
+ * identifier corresponding to a given CPU.
+ *
+ * Return: the VP ID for the CPU.
+ */
+static inline unsigned int mips_cm_vp_id(unsigned int cpu)
+{
+ unsigned int core = cpu_data[cpu].core;
+ unsigned int vp = cpu_vpe_id(&cpu_data[cpu]);
+
+ return (core * mips_cm_max_vp_width()) + vp;
+}
+
+#ifdef CONFIG_MIPS_CM
+
+/**
+ * mips_cm_lock_other - lock access to another core
+ * @core: the other core to be accessed
+ * @vp: the VP within the other core to be accessed
+ *
+ * Call before operating upon a core via the 'other' register region in
+ * order to prevent the region being moved during access. Must be followed
+ * by a call to mips_cm_unlock_other.
+ */
+extern void mips_cm_lock_other(unsigned int core, unsigned int vp);
+
+/**
+ * mips_cm_unlock_other - unlock access to another core
+ *
+ * Call after operating upon another core via the 'other' register region.
+ * Must be called after mips_cm_lock_other.
+ */
+extern void mips_cm_unlock_other(void);
+
+#else /* !CONFIG_MIPS_CM */
+
+static inline void mips_cm_lock_other(unsigned int core) { }
+static inline void mips_cm_unlock_other(void) { }
+
+#endif /* !CONFIG_MIPS_CM */
+
#endif /* __MIPS_ASM_MIPS_CM_H__ */
diff --git a/kernel/arch/mips/include/asm/mips-cpc.h b/kernel/arch/mips/include/asm/mips-cpc.h
index 1cebe8c79..e09035239 100644
--- a/kernel/arch/mips/include/asm/mips-cpc.h
+++ b/kernel/arch/mips/include/asm/mips-cpc.h
@@ -28,16 +28,6 @@ extern void __iomem *mips_cpc_base;
extern phys_addr_t mips_cpc_default_phys_base(void);
/**
- * mips_cpc_phys_base - retrieve the physical base address of the CPC
- *
- * This function returns the physical base address of the Cluster Power
- * Controller memory mapped registers, or 0 if no Cluster Power Controller
- * is present. It may be overriden by individual platforms which determine
- * this address in a different way.
- */
-extern phys_addr_t __weak mips_cpc_phys_base(void);
-
-/**
* mips_cpc_probe - probe for a Cluster Power Controller
*
* Attempt to detect the presence of a Cluster Power Controller. Returns 0 if
@@ -159,7 +149,8 @@ BUILD_CPC_Cx_RW(other, 0x10)
* core: the other core to be accessed
*
* Call before operating upon a core via the 'other' register region in
- * order to prevent the region being moved during access. Must be followed
+ * order to prevent the region being moved during access. Must be called
+ * within the bounds of a mips_cm_{lock,unlock}_other pair, and followed
* by a call to mips_cpc_unlock_other.
*/
extern void mips_cpc_lock_other(unsigned int core);
diff --git a/kernel/arch/mips/include/asm/mipsregs.h b/kernel/arch/mips/include/asm/mipsregs.h
index 764e2756b..e43aca183 100644
--- a/kernel/arch/mips/include/asm/mipsregs.h
+++ b/kernel/arch/mips/include/asm/mipsregs.h
@@ -50,7 +50,9 @@
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_INFO $7
+#define CP0_HWRENA $7, 0
#define CP0_BADVADDR $8
+#define CP0_BADINSTR $8, 1
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
@@ -58,7 +60,11 @@
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
+#define CP0_EBASE $15, 1
+#define CP0_CMGCRBASE $15, 3
#define CP0_CONFIG $16
+#define CP0_CONFIG3 $16, 3
+#define CP0_CONFIG5 $16, 5
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
@@ -112,6 +118,24 @@
#define CP0_TX39_CACHE $7
+/* Generic EntryLo bit definitions */
+#define ENTRYLO_G (_ULCAST_(1) << 0)
+#define ENTRYLO_V (_ULCAST_(1) << 1)
+#define ENTRYLO_D (_ULCAST_(1) << 2)
+#define ENTRYLO_C_SHIFT 3
+#define ENTRYLO_C (_ULCAST_(7) << ENTRYLO_C_SHIFT)
+
+/* R3000 EntryLo bit definitions */
+#define R3K_ENTRYLO_G (_ULCAST_(1) << 8)
+#define R3K_ENTRYLO_V (_ULCAST_(1) << 9)
+#define R3K_ENTRYLO_D (_ULCAST_(1) << 10)
+#define R3K_ENTRYLO_N (_ULCAST_(1) << 11)
+
+/* MIPS32/64 EntryLo bit definitions */
+#define MIPS_ENTRYLO_PFN_SHIFT 6
+#define MIPS_ENTRYLO_XI (_ULCAST_(1) << (BITS_PER_LONG - 2))
+#define MIPS_ENTRYLO_RI (_ULCAST_(1) << (BITS_PER_LONG - 1))
+
/*
* Values for PageMask register
*/
@@ -203,6 +227,9 @@
#define PG_ESP (_ULCAST_(1) << 28)
#define PG_IEC (_ULCAST_(1) << 27)
+/* MIPS32/64 EntryHI bit definitions */
+#define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10)
+
/*
* R4x00 interrupt enable / cause bits
*/
@@ -460,6 +487,8 @@
/* Bits specific to the MIPS32/64 PRA. */
#define MIPS_CONF_MT (_ULCAST_(7) << 7)
+#define MIPS_CONF_MT_TLB (_ULCAST_(1) << 7)
+#define MIPS_CONF_MT_FTLB (_ULCAST_(4) << 7)
#define MIPS_CONF_AR (_ULCAST_(7) << 10)
#define MIPS_CONF_AT (_ULCAST_(3) << 13)
#define MIPS_CONF_M (_ULCAST_(1) << 31)
@@ -579,6 +608,8 @@
#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
+/* FTLB probability bits for R6 */
+#define MIPS_CONF7_FTLBP_SHIFT (18)
/* MAAR bit definitions */
#define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
@@ -586,9 +617,6 @@
#define MIPS_MAAR_S (_ULCAST_(1) << 1)
#define MIPS_MAAR_V (_ULCAST_(1) << 0)
-/* EntryHI bit definition */
-#define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10)
-
/* CMGCRBase bit definitions */
#define MIPS_CMGCRB_BASE 11
#define MIPS_CMGCRF_BASE (~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
@@ -685,6 +713,15 @@
#define TX39_CONF_DRSIZE_SHIFT 0
#define TX39_CONF_DRSIZE_MASK 0x00000003
+/*
+ * Interesting Bits in the R10K CP0 Branch Diagnostic Register
+ */
+/* Disable Branch Target Address Cache */
+#define R10K_DIAG_D_BTAC (_ULCAST_(1) << 27)
+/* Enable Branch Prediction Global History */
+#define R10K_DIAG_E_GHIST (_ULCAST_(1) << 26)
+/* Disable Branch Return Cache */
+#define R10K_DIAG_D_BRC (_ULCAST_(1) << 22)
/*
* Coprocessor 1 (FPU) register names
@@ -901,7 +938,7 @@ do { \
*/
#define __read_32bit_c0_register(source, sel) \
-({ int __res; \
+({ unsigned int __res; \
if (sel == 0) \
__asm__ __volatile__( \
"mfc0\t%0, " #source "\n\t" \
@@ -983,7 +1020,7 @@ do { \
* On RM7000/RM9000 these are uses to access cop0 set 1 registers
*/
#define __read_32bit_c0_ctrl_register(source) \
-({ int __res; \
+({ unsigned int __res; \
__asm__ __volatile__( \
"cfc0\t%0, " #source "\n\t" \
: "=r" (__res)); \
@@ -1247,6 +1284,10 @@ do { \
#define read_c0_diag() __read_32bit_c0_register($22, 0)
#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val)
+/* R10K CP0 Branch Diagnostic register is 64bits wide */
+#define read_c0_r10k_diag() __read_64bit_c0_register($22, 0)
+#define write_c0_r10k_diag(val) __write_64bit_c0_register($22, 0, val)
+
#define read_c0_diag1() __read_32bit_c0_register($22, 1)
#define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val)
@@ -1436,7 +1477,7 @@ do { \
*/
#define _read_32bit_cp1_register(source, gas_hardfloat) \
({ \
- int __res; \
+ unsigned int __res; \
\
__asm__ __volatile__( \
" .set push \n" \
diff --git a/kernel/arch/mips/include/asm/msa.h b/kernel/arch/mips/include/asm/msa.h
index af5638b12..bbb85fe21 100644
--- a/kernel/arch/mips/include/asm/msa.h
+++ b/kernel/arch/mips/include/asm/msa.h
@@ -14,10 +14,90 @@
#ifndef __ASSEMBLY__
+#include <asm/inst.h>
+
extern void _save_msa(struct task_struct *);
extern void _restore_msa(struct task_struct *);
extern void _init_msa_upper(void);
+extern void read_msa_wr_b(unsigned idx, union fpureg *to);
+extern void read_msa_wr_h(unsigned idx, union fpureg *to);
+extern void read_msa_wr_w(unsigned idx, union fpureg *to);
+extern void read_msa_wr_d(unsigned idx, union fpureg *to);
+
+/**
+ * read_msa_wr() - Read a single MSA vector register
+ * @idx: The index of the vector register to read
+ * @to: The FPU register union to store the registers value in
+ * @fmt: The format of the data in the vector register
+ *
+ * Read the value of MSA vector register idx into the FPU register
+ * union to, using the format fmt.
+ */
+static inline void read_msa_wr(unsigned idx, union fpureg *to,
+ enum msa_2b_fmt fmt)
+{
+ switch (fmt) {
+ case msa_fmt_b:
+ read_msa_wr_b(idx, to);
+ break;
+
+ case msa_fmt_h:
+ read_msa_wr_h(idx, to);
+ break;
+
+ case msa_fmt_w:
+ read_msa_wr_w(idx, to);
+ break;
+
+ case msa_fmt_d:
+ read_msa_wr_d(idx, to);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+extern void write_msa_wr_b(unsigned idx, union fpureg *from);
+extern void write_msa_wr_h(unsigned idx, union fpureg *from);
+extern void write_msa_wr_w(unsigned idx, union fpureg *from);
+extern void write_msa_wr_d(unsigned idx, union fpureg *from);
+
+/**
+ * write_msa_wr() - Write a single MSA vector register
+ * @idx: The index of the vector register to write
+ * @from: The FPU register union to take the registers value from
+ * @fmt: The format of the data in the vector register
+ *
+ * Write the value from the FPU register union from into MSA vector
+ * register idx, using the format fmt.
+ */
+static inline void write_msa_wr(unsigned idx, union fpureg *from,
+ enum msa_2b_fmt fmt)
+{
+ switch (fmt) {
+ case msa_fmt_b:
+ write_msa_wr_b(idx, from);
+ break;
+
+ case msa_fmt_h:
+ write_msa_wr_h(idx, from);
+ break;
+
+ case msa_fmt_w:
+ write_msa_wr_w(idx, from);
+ break;
+
+ case msa_fmt_d:
+ write_msa_wr_d(idx, from);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
static inline void enable_msa(void)
{
if (cpu_has_msa) {
diff --git a/kernel/arch/mips/include/asm/netlogic/common.h b/kernel/arch/mips/include/asm/netlogic/common.h
index 2a4c12827..be52c2125 100644
--- a/kernel/arch/mips/include/asm/netlogic/common.h
+++ b/kernel/arch/mips/include/asm/netlogic/common.h
@@ -57,8 +57,8 @@
#include <asm/mach-netlogic/multi-node.h>
struct irq_desc;
-void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
-void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
+void nlm_smp_function_ipi_handler(struct irq_desc *desc);
+void nlm_smp_resched_ipi_handler(struct irq_desc *desc);
void nlm_smp_irq_init(int hwcpuid);
void nlm_boot_secondary_cpus(void);
int nlm_wakeup_secondary_cpus(void);
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/kernel/arch/mips/include/asm/octeon/cvmx-bootinfo.h
index c373d95b5..d92cf59bd 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-bootinfo.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-bootinfo.h
@@ -284,6 +284,7 @@ enum cvmx_board_types_enum {
CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
CVMX_BOARD_TYPE_UBNT_E100 = 20002,
CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
+ CVMX_BOARD_TYPE_KONTRON_S1901 = 21901,
CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
/* The remaining range is reserved for future use. */
@@ -384,6 +385,7 @@ static inline const char *cvmx_board_type_to_string(enum
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
}
return "Unsupported Board";
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-pip.h b/kernel/arch/mips/include/asm/octeon/cvmx-pip.h
index df69bfd2b..c210154ad 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-pip.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-pip.h
@@ -37,7 +37,7 @@
#include <asm/octeon/cvmx-fpa.h>
#include <asm/octeon/cvmx-pip-defs.h>
-#define CVMX_PIP_NUM_INPUT_PORTS 40
+#define CVMX_PIP_NUM_INPUT_PORTS 48
#define CVMX_PIP_NUM_WATCHERS 4
/*
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-pko.h b/kernel/arch/mips/include/asm/octeon/cvmx-pko.h
index 3da59bb8c..5f47f76ed 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-pko.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-pko.h
@@ -542,6 +542,9 @@ static inline int cvmx_pko_get_base_queue_per_core(int port, int core)
*/
static inline int cvmx_pko_get_base_queue(int port)
{
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ return port;
+
return cvmx_pko_get_base_queue_per_core(port, 0);
}
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-pow-defs.h b/kernel/arch/mips/include/asm/octeon/cvmx-pow-defs.h
index 9020ef443..6a3db4b06 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-pow-defs.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-pow-defs.h
@@ -52,6 +52,12 @@
#define CVMX_POW_WQ_INT_THRX(offset) (CVMX_ADD_IO_SEG(0x0001670000000080ull) + ((offset) & 15) * 8)
#define CVMX_POW_WS_PCX(offset) (CVMX_ADD_IO_SEG(0x0001670000000280ull) + ((offset) & 15) * 8)
+#define CVMX_SSO_WQ_INT (CVMX_ADD_IO_SEG(0x0001670000001000ull))
+#define CVMX_SSO_WQ_IQ_DIS (CVMX_ADD_IO_SEG(0x0001670000001010ull))
+#define CVMX_SSO_WQ_INT_PC (CVMX_ADD_IO_SEG(0x0001670000001020ull))
+#define CVMX_SSO_PPX_GRP_MSK(offset) (CVMX_ADD_IO_SEG(0x0001670000006000ull) + ((offset) & 31) * 8)
+#define CVMX_SSO_WQ_INT_THRX(offset) (CVMX_ADD_IO_SEG(0x0001670000007000ull) + ((offset) & 63) * 8)
+
union cvmx_pow_bist_stat {
uint64_t u64;
struct cvmx_pow_bist_stat_s {
@@ -1286,4 +1292,27 @@ union cvmx_pow_ws_pcx {
struct cvmx_pow_ws_pcx_s cnf71xx;
};
+union cvmx_sso_wq_int_thrx {
+ uint64_t u64;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint64_t reserved_33_63:31;
+ uint64_t tc_en:1;
+ uint64_t tc_thr:4;
+ uint64_t reserved_26_27:2;
+ uint64_t ds_thr:12;
+ uint64_t reserved_12_13:2;
+ uint64_t iq_thr:12;
+#else
+ uint64_t iq_thr:12;
+ uint64_t reserved_12_13:2;
+ uint64_t ds_thr:12;
+ uint64_t reserved_26_27:2;
+ uint64_t tc_thr:4;
+ uint64_t tc_en:1;
+ uint64_t reserved_33_63:31;
+#endif
+ } s;
+};
+
#endif
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-pow.h b/kernel/arch/mips/include/asm/octeon/cvmx-pow.h
index d5565d758..51531563f 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-pow.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-pow.h
@@ -1810,10 +1810,11 @@ static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag,
cvmx_addr_t ptr;
cvmx_pow_tag_req_t tag_req;
- wqp->qos = qos;
- wqp->tag = tag;
- wqp->tag_type = tag_type;
- wqp->grp = grp;
+ wqp->word1.tag = tag;
+ wqp->word1.tag_type = tag_type;
+
+ cvmx_wqe_set_qos(wqp, qos);
+ cvmx_wqe_set_grp(wqp, grp);
tag_req.u64 = 0;
tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ;
diff --git a/kernel/arch/mips/include/asm/octeon/cvmx-wqe.h b/kernel/arch/mips/include/asm/octeon/cvmx-wqe.h
index 2d6d0c712..0d697aa78 100644
--- a/kernel/arch/mips/include/asm/octeon/cvmx-wqe.h
+++ b/kernel/arch/mips/include/asm/octeon/cvmx-wqe.h
@@ -193,6 +193,53 @@ typedef union {
uint64_t bufs:8;
#endif
} s;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint64_t bufs:8;
+ uint64_t ip_offset:8;
+ uint64_t vlan_valid:1;
+ uint64_t vlan_stacked:1;
+ uint64_t unassigned:1;
+ uint64_t vlan_cfi:1;
+ uint64_t vlan_id:12;
+ uint64_t port:12; /* MAC/PIP port number. */
+ uint64_t dec_ipcomp:1;
+ uint64_t tcp_or_udp:1;
+ uint64_t dec_ipsec:1;
+ uint64_t is_v6:1;
+ uint64_t software:1;
+ uint64_t L4_error:1;
+ uint64_t is_frag:1;
+ uint64_t IP_exc:1;
+ uint64_t is_bcast:1;
+ uint64_t is_mcast:1;
+ uint64_t not_IP:1;
+ uint64_t rcv_error:1;
+ uint64_t err_code:8;
+#else
+ uint64_t err_code:8;
+ uint64_t rcv_error:1;
+ uint64_t not_IP:1;
+ uint64_t is_mcast:1;
+ uint64_t is_bcast:1;
+ uint64_t IP_exc:1;
+ uint64_t is_frag:1;
+ uint64_t L4_error:1;
+ uint64_t software:1;
+ uint64_t is_v6:1;
+ uint64_t dec_ipsec:1;
+ uint64_t tcp_or_udp:1;
+ uint64_t dec_ipcomp:1;
+ uint64_t port:12;
+ uint64_t vlan_id:12;
+ uint64_t vlan_cfi:1;
+ uint64_t unassigned:1;
+ uint64_t vlan_stacked:1;
+ uint64_t vlan_valid:1;
+ uint64_t ip_offset:8;
+ uint64_t bufs:8;
+#endif
+ } s_cn68xx;
/* use this to get at the 16 vlan bits */
struct {
@@ -355,6 +402,146 @@ typedef union {
} cvmx_pip_wqe_word2;
+union cvmx_pip_wqe_word0 {
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ /**
+ * raw chksum result generated by the HW
+ */
+ uint16_t hw_chksum;
+ /**
+ * Field unused by hardware - available for software
+ */
+ uint8_t unused;
+ /**
+ * Next pointer used by hardware for list maintenance.
+ * May be written/read by HW before the work queue
+ * entry is scheduled to a PP (Only 36 bits used in
+ * Octeon 1)
+ */
+ uint64_t next_ptr:40;
+#else
+ uint64_t next_ptr:40;
+ uint8_t unused;
+ uint16_t hw_chksum;
+#endif
+ } cn38xx;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint64_t l4ptr:8; /* 56..63 */
+ uint64_t unused0:8; /* 48..55 */
+ uint64_t l3ptr:8; /* 40..47 */
+ uint64_t l2ptr:8; /* 32..39 */
+ uint64_t unused1:18; /* 14..31 */
+ uint64_t bpid:6; /* 8..13 */
+ uint64_t unused2:2; /* 6..7 */
+ uint64_t pknd:6; /* 0..5 */
+#else
+ uint64_t pknd:6; /* 0..5 */
+ uint64_t unused2:2; /* 6..7 */
+ uint64_t bpid:6; /* 8..13 */
+ uint64_t unused1:18; /* 14..31 */
+ uint64_t l2ptr:8; /* 32..39 */
+ uint64_t l3ptr:8; /* 40..47 */
+ uint64_t unused0:8; /* 48..55 */
+ uint64_t l4ptr:8; /* 56..63 */
+#endif
+ } cn68xx;
+};
+
+union cvmx_wqe_word0 {
+ uint64_t u64;
+ union cvmx_pip_wqe_word0 pip;
+};
+
+union cvmx_wqe_word1 {
+ uint64_t u64;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint64_t len:16;
+ uint64_t varies:14;
+ /**
+ * the type of the tag (ORDERED, ATOMIC, NULL)
+ */
+ uint64_t tag_type:2;
+ uint64_t tag:32;
+#else
+ uint64_t tag:32;
+ uint64_t tag_type:2;
+ uint64_t varies:14;
+ uint64_t len:16;
+#endif
+ };
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ uint64_t len:16;
+ uint64_t zero_0:1;
+ /**
+ * HW sets this to what it thought the priority of
+ * the input packet was
+ */
+ uint64_t qos:3;
+
+ uint64_t zero_1:1;
+ /**
+ * the group that the work queue entry will be scheduled to
+ */
+ uint64_t grp:6;
+ uint64_t zero_2:3;
+ uint64_t tag_type:2;
+ uint64_t tag:32;
+#else
+ uint64_t tag:32;
+ uint64_t tag_type:2;
+ uint64_t zero_2:3;
+ uint64_t grp:6;
+ uint64_t zero_1:1;
+ uint64_t qos:3;
+ uint64_t zero_0:1;
+ uint64_t len:16;
+#endif
+ } cn68xx;
+ struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+ /**
+ * HW sets to the total number of bytes in the packet
+ */
+ uint64_t len:16;
+ /**
+ * HW sets this to input physical port
+ */
+ uint64_t ipprt:6;
+
+ /**
+ * HW sets this to what it thought the priority of
+ * the input packet was
+ */
+ uint64_t qos:3;
+
+ /**
+ * the group that the work queue entry will be scheduled to
+ */
+ uint64_t grp:4;
+ /**
+ * the type of the tag (ORDERED, ATOMIC, NULL)
+ */
+ uint64_t tag_type:3;
+ /**
+ * the synchronization/ordering tag
+ */
+ uint64_t tag:32;
+#else
+ uint64_t tag:32;
+ uint64_t tag_type:2;
+ uint64_t zero_2:1;
+ uint64_t grp:4;
+ uint64_t qos:3;
+ uint64_t ipprt:6;
+ uint64_t len:16;
+#endif
+ } cn38xx;
+};
+
/**
* Work queue entry format
*
@@ -366,70 +553,13 @@ typedef struct {
* WORD 0
* HW WRITE: the following 64 bits are filled by HW when a packet arrives
*/
-
-#ifdef __BIG_ENDIAN_BITFIELD
- /**
- * raw chksum result generated by the HW
- */
- uint16_t hw_chksum;
- /**
- * Field unused by hardware - available for software
- */
- uint8_t unused;
- /**
- * Next pointer used by hardware for list maintenance.
- * May be written/read by HW before the work queue
- * entry is scheduled to a PP
- * (Only 36 bits used in Octeon 1)
- */
- uint64_t next_ptr:40;
-#else
- uint64_t next_ptr:40;
- uint8_t unused;
- uint16_t hw_chksum;
-#endif
+ union cvmx_wqe_word0 word0;
/*****************************************************************
* WORD 1
* HW WRITE: the following 64 bits are filled by HW when a packet arrives
*/
-
-#ifdef __BIG_ENDIAN_BITFIELD
- /**
- * HW sets to the total number of bytes in the packet
- */
- uint64_t len:16;
- /**
- * HW sets this to input physical port
- */
- uint64_t ipprt:6;
-
- /**
- * HW sets this to what it thought the priority of the input packet was
- */
- uint64_t qos:3;
-
- /**
- * the group that the work queue entry will be scheduled to
- */
- uint64_t grp:4;
- /**
- * the type of the tag (ORDERED, ATOMIC, NULL)
- */
- uint64_t tag_type:3;
- /**
- * the synchronization/ordering tag
- */
- uint64_t tag:32;
-#else
- uint64_t tag:32;
- uint64_t tag_type:2;
- uint64_t zero_2:1;
- uint64_t grp:4;
- uint64_t qos:3;
- uint64_t ipprt:6;
- uint64_t len:16;
-#endif
+ union cvmx_wqe_word1 word1;
/**
* WORD 2 HW WRITE: the following 64-bits are filled in by
@@ -465,4 +595,64 @@ typedef struct {
} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t;
+static inline int cvmx_wqe_get_port(cvmx_wqe_t *work)
+{
+ int port;
+
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ port = work->word2.s_cn68xx.port;
+ else
+ port = work->word1.cn38xx.ipprt;
+
+ return port;
+}
+
+static inline void cvmx_wqe_set_port(cvmx_wqe_t *work, int port)
+{
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ work->word2.s_cn68xx.port = port;
+ else
+ work->word1.cn38xx.ipprt = port;
+}
+
+static inline int cvmx_wqe_get_grp(cvmx_wqe_t *work)
+{
+ int grp;
+
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ grp = work->word1.cn68xx.grp;
+ else
+ grp = work->word1.cn38xx.grp;
+
+ return grp;
+}
+
+static inline void cvmx_wqe_set_grp(cvmx_wqe_t *work, int grp)
+{
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ work->word1.cn68xx.grp = grp;
+ else
+ work->word1.cn38xx.grp = grp;
+}
+
+static inline int cvmx_wqe_get_qos(cvmx_wqe_t *work)
+{
+ int qos;
+
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ qos = work->word1.cn68xx.qos;
+ else
+ qos = work->word1.cn38xx.qos;
+
+ return qos;
+}
+
+static inline void cvmx_wqe_set_qos(cvmx_wqe_t *work, int qos)
+{
+ if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE))
+ work->word1.cn68xx.qos = qos;
+ else
+ work->word1.cn38xx.qos = qos;
+}
+
#endif /* __CVMX_WQE_H__ */
diff --git a/kernel/arch/mips/include/asm/page.h b/kernel/arch/mips/include/asm/page.h
index 89dd7fed1..21ed7150f 100644
--- a/kernel/arch/mips/include/asm/page.h
+++ b/kernel/arch/mips/include/asm/page.h
@@ -200,8 +200,9 @@ static inline int pfn_valid(unsigned long pfn)
{
/* avoid <linux/mm.h> include hell */
extern unsigned long max_mapnr;
+ unsigned long pfn_offset = ARCH_PFN_OFFSET;
- return pfn >= ARCH_PFN_OFFSET && pfn < max_mapnr;
+ return pfn >= pfn_offset && pfn < max_mapnr;
}
#elif defined(CONFIG_SPARSEMEM)
diff --git a/kernel/arch/mips/include/asm/pci.h b/kernel/arch/mips/include/asm/pci.h
index d9692993f..98c31e5d9 100644
--- a/kernel/arch/mips/include/asm/pci.h
+++ b/kernel/arch/mips/include/asm/pci.h
@@ -99,7 +99,7 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
#include <linux/types.h>
#include <linux/slab.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm-generic/pci-bridge.h>
@@ -113,16 +113,6 @@ struct pci_dev;
*/
extern unsigned int PCI_DMA_BUS_IS_PHYS;
-#ifdef CONFIG_PCI
-static inline void pci_dma_burst_advice(struct pci_dev *pdev,
- enum pci_dma_burst_strategy *strat,
- unsigned long *strategy_parameter)
-{
- *strat = PCI_DMA_BURST_INFINITY;
- *strategy_parameter = ~0UL;
-}
-#endif
-
#ifdef CONFIG_PCI_DOMAINS
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
diff --git a/kernel/arch/mips/include/asm/pgtable-32.h b/kernel/arch/mips/include/asm/pgtable-32.h
index 7d56686c0..832e2167d 100644
--- a/kernel/arch/mips/include/asm/pgtable-32.h
+++ b/kernel/arch/mips/include/asm/pgtable-32.h
@@ -18,7 +18,7 @@
#include <asm-generic/pgtable-nopmd.h>
-extern int temp_tlb_entry __cpuinitdata;
+extern int temp_tlb_entry;
/*
* - add_temporary_entry() add a temporary TLB entry. We use TLB entries
diff --git a/kernel/arch/mips/include/asm/pgtable-bits.h b/kernel/arch/mips/include/asm/pgtable-bits.h
index c28a8499a..ff7ad91c8 100644
--- a/kernel/arch/mips/include/asm/pgtable-bits.h
+++ b/kernel/arch/mips/include/asm/pgtable-bits.h
@@ -133,20 +133,13 @@
#define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT)
#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT + 1)
#define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT)
-
-/* Only R2 or newer cores have the XI bit */
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-#define _PAGE_NO_EXEC_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
-#else
-#define _PAGE_GLOBAL_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
-#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
-#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
-
#endif /* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
/* XI - page cannot be executed */
-#ifndef _PAGE_NO_EXEC_SHIFT
+#ifdef _PAGE_SPLITTING_SHIFT
+#define _PAGE_NO_EXEC_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
+#else
#define _PAGE_NO_EXEC_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
#endif
#define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0)
@@ -156,14 +149,16 @@
#define _PAGE_READ (cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT))
#define _PAGE_NO_READ_SHIFT _PAGE_READ_SHIFT
#define _PAGE_NO_READ (cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0)
+#endif /* defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) */
+#if defined(_PAGE_NO_READ_SHIFT)
#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1)
-#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
-
-#else /* !CONFIG_CPU_MIPSR2 && !CONFIG_CPU_MIPSR6 */
+#elif defined(_PAGE_SPLITTING_SHIFT)
+#define _PAGE_GLOBAL_SHIFT (_PAGE_SPLITTING_SHIFT + 1)
+#else
#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
+#endif
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
-#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1)
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
@@ -249,7 +244,7 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT) /* LOONGSON */
#define _CACHE_CACHABLE_COHERENT (3<<_CACHE_SHIFT) /* LOONGSON-3 */
-#elif defined(CONFIG_MACH_JZ4740)
+#elif defined(CONFIG_MACH_INGENIC)
/* Ingenic uses the WA bit to achieve write-combine memory writes */
#define _CACHE_UNCACHED_ACCELERATED (1<<_CACHE_SHIFT)
diff --git a/kernel/arch/mips/include/asm/pgtable.h b/kernel/arch/mips/include/asm/pgtable.h
index 70f6e7f07..18826aa15 100644
--- a/kernel/arch/mips/include/asm/pgtable.h
+++ b/kernel/arch/mips/include/asm/pgtable.h
@@ -353,7 +353,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pte_val(pte) & _PAGE_NO_READ))
pte_val(pte) |= _PAGE_SILENT_READ;
else
@@ -393,6 +393,8 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
return __pgprot(prot);
}
+#define pgprot_writecombine pgprot_writecombine
+
static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
{
unsigned long prot = pgprot_val(_prot);
@@ -558,7 +560,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
{
pmd_val(pmd) |= _PAGE_ACCESSED;
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pmd_val(pmd) & _PAGE_NO_READ))
pmd_val(pmd) |= _PAGE_SILENT_READ;
else
@@ -599,12 +601,12 @@ static inline pmd_t pmd_mknotpresent(pmd_t pmd)
}
/*
- * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a
+ * The generic version pmdp_huge_get_and_clear uses a version of pmd_clear() with a
* different prototype.
*/
-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
- unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+ unsigned long address, pmd_t *pmdp)
{
pmd_t old = *pmdp;
diff --git a/kernel/arch/mips/include/asm/processor.h b/kernel/arch/mips/include/asm/processor.h
index 9b3b48e21..3f832c3dd 100644
--- a/kernel/arch/mips/include/asm/processor.h
+++ b/kernel/arch/mips/include/asm/processor.h
@@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count;
*/
#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
-/*
- * A special page (the vdso) is mapped into all processes at the very
- * top of the virtual memory space.
- */
-#define SPECIAL_PAGES_SIZE PAGE_SIZE
-
#ifdef CONFIG_32BIT
#ifdef CONFIG_KVM_GUEST
/* User space process size is limited to 1GB in KVM Guest Mode */
@@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count;
#endif
-#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
+#define STACK_TOP (TASK_SIZE & PAGE_MASK)
/*
* This decides where the kernel will search for a free chunk of vm
@@ -275,6 +269,7 @@ struct thread_struct {
unsigned long cp0_badvaddr; /* Last user fault */
unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */
unsigned long error_code;
+ unsigned long trap_nr;
#ifdef CONFIG_CPU_CAVIUM_OCTEON
struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
@@ -341,6 +336,7 @@ struct thread_struct {
.cp0_badvaddr = 0, \
.cp0_baduaddr = 0, \
.error_code = 0, \
+ .trap_nr = 0, \
/* \
* Platform specific cop2 registers(null if no COP2) \
*/ \
diff --git a/kernel/arch/mips/include/asm/prom.h b/kernel/arch/mips/include/asm/prom.h
index 8ebc2aa5f..0b4b66892 100644
--- a/kernel/arch/mips/include/asm/prom.h
+++ b/kernel/arch/mips/include/asm/prom.h
@@ -11,7 +11,7 @@
#ifndef __ASM_PROM_H
#define __ASM_PROM_H
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
#include <linux/bug.h>
#include <linux/io.h>
#include <linux/types.h>
diff --git a/kernel/arch/mips/include/asm/ptrace.h b/kernel/arch/mips/include/asm/ptrace.h
index ffc320389..f6fc6aac5 100644
--- a/kernel/arch/mips/include/asm/ptrace.h
+++ b/kernel/arch/mips/include/asm/ptrace.h
@@ -14,11 +14,16 @@
#include <linux/linkage.h>
#include <linux/types.h>
#include <asm/isadep.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
#include <uapi/asm/ptrace.h>
/*
* This struct defines the way the registers are stored on the stack during a
* system call/exception. As usual the registers k0/k1 aren't being saved.
+ *
+ * If you add a register here, also add it to regoffset_table[] in
+ * arch/mips/kernel/ptrace.c.
*/
struct pt_regs {
#ifdef CONFIG_32BIT
@@ -43,8 +48,83 @@ struct pt_regs {
unsigned long long mpl[6]; /* MTM{0-5} */
unsigned long long mtp[6]; /* MTP{0-5} */
#endif
+ unsigned long __last[0];
} __aligned(8);
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+ return regs->regs[31];
+}
+
+/*
+ * Don't use asm-generic/ptrace.h it defines FP accessors that don't make
+ * sense on MIPS. We rather want an error if they get invoked.
+ */
+
+static inline void instruction_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->cp0_epc = val;
+}
+
+/* Query offset/name of register from its name/offset */
+extern int regs_query_register_offset(const char *name);
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs: pt_regs from which register value is gotten.
+ * @offset: offset number of the register.
+ *
+ * regs_get_register returns the value of a register. The @offset is the
+ * offset of the register in struct pt_regs address which specified by @regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned int offset)
+{
+ if (unlikely(offset > MAX_REG_OFFSET))
+ return 0;
+
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @addr: address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+static inline int regs_within_kernel_stack(struct pt_regs *regs,
+ unsigned long addr)
+{
+ return ((addr & ~(THREAD_SIZE - 1)) ==
+ (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @n: stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+ unsigned int n)
+{
+ unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+
+ addr += n;
+ if (regs_within_kernel_stack(regs, (unsigned long)addr))
+ return *addr;
+ else
+ return 0;
+}
+
struct task_struct;
extern int ptrace_getregs(struct task_struct *child,
diff --git a/kernel/arch/mips/include/asm/signal.h b/kernel/arch/mips/include/asm/signal.h
index 8efe5a9e2..003e273ef 100644
--- a/kernel/arch/mips/include/asm/signal.h
+++ b/kernel/arch/mips/include/asm/signal.h
@@ -23,4 +23,7 @@
#define __ARCH_HAS_IRIX_SIGACTION
+extern int protected_save_fp_context(void __user *sc);
+extern int protected_restore_fp_context(void __user *sc);
+
#endif /* _ASM_SIGNAL_H */
diff --git a/kernel/arch/mips/include/asm/smp.h b/kernel/arch/mips/include/asm/smp.h
index 16f1ea9ab..03722d432 100644
--- a/kernel/arch/mips/include/asm/smp.h
+++ b/kernel/arch/mips/include/asm/smp.h
@@ -83,8 +83,6 @@ static inline void __cpu_die(unsigned int cpu)
extern void play_dead(void);
#endif
-extern asmlinkage void smp_call_function_interrupt(void);
-
static inline void arch_send_call_function_single_ipi(int cpu)
{
extern struct plat_smp_ops *mp_ops; /* private */
diff --git a/kernel/arch/mips/include/asm/spinlock.h b/kernel/arch/mips/include/asm/spinlock.h
index 1fca2e079..40196bebe 100644
--- a/kernel/arch/mips/include/asm/spinlock.h
+++ b/kernel/arch/mips/include/asm/spinlock.h
@@ -42,6 +42,11 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
return ((counters >> 16) ^ counters) & 0xffff;
}
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+ return lock.h.serving_now == lock.h.ticket;
+}
+
#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
#define arch_spin_unlock_wait(x) \
while (arch_spin_is_locked(x)) { cpu_relax(); }
@@ -109,7 +114,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
" subu %[ticket], %[my_ticket], %[ticket] \n"
"2: \n"
" .subsection 2 \n"
- "4: andi %[ticket], %[ticket], 0x1fff \n"
+ "4: andi %[ticket], %[ticket], 0xffff \n"
" sll %[ticket], 5 \n"
" \n"
"6: bnez %[ticket], 6b \n"
@@ -317,7 +322,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
static inline void arch_write_unlock(arch_rwlock_t *rw)
{
- smp_mb();
+ smp_mb__before_llsc();
__asm__ __volatile__(
" # arch_write_unlock \n"
diff --git a/kernel/arch/mips/include/asm/switch_to.h b/kernel/arch/mips/include/asm/switch_to.h
index 7163cd7fd..28b5d84a5 100644
--- a/kernel/arch/mips/include/asm/switch_to.h
+++ b/kernel/arch/mips/include/asm/switch_to.h
@@ -16,29 +16,21 @@
#include <asm/watch.h>
#include <asm/dsp.h>
#include <asm/cop2.h>
-#include <asm/msa.h>
+#include <asm/fpu.h>
struct task_struct;
-enum {
- FP_SAVE_NONE = 0,
- FP_SAVE_VECTOR = -1,
- FP_SAVE_SCALAR = 1,
-};
-
/**
* resume - resume execution of a task
* @prev: The task previously executed.
* @next: The task to begin executing.
* @next_ti: task_thread_info(next).
- * @fp_save: Which, if any, FP context to save for prev.
*
* This function is used whilst scheduling to save the context of prev & load
* the context of next. Returns prev.
*/
extern asmlinkage struct task_struct *resume(struct task_struct *prev,
- struct task_struct *next, struct thread_info *next_ti,
- s32 fp_save);
+ struct task_struct *next, struct thread_info *next_ti);
extern unsigned int ll_bit;
extern struct task_struct *ll_task;
@@ -83,45 +75,38 @@ do { if (cpu_has_rw_llb) { \
} \
} while (0)
+/*
+ * For newly created kernel threads switch_to() will return to
+ * ret_from_kernel_thread, newly created user threads to ret_from_fork.
+ * That is, everything following resume() will be skipped for new threads.
+ * So everything that matters to new threads should be placed before resume().
+ */
#define switch_to(prev, next, last) \
do { \
- u32 __c0_stat; \
- s32 __fpsave = FP_SAVE_NONE; \
__mips_mt_fpaff_switch_to(prev); \
- if (cpu_has_dsp) \
+ lose_fpu_inatomic(1, prev); \
+ if (cpu_has_dsp) { \
__save_dsp(prev); \
- if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) { \
- if (cop2_lazy_restore) \
- KSTK_STATUS(prev) &= ~ST0_CU2; \
- __c0_stat = read_c0_status(); \
- write_c0_status(__c0_stat | ST0_CU2); \
- cop2_save(prev); \
- write_c0_status(__c0_stat & ~ST0_CU2); \
+ __restore_dsp(next); \
} \
- __clear_software_ll_bit(); \
- if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU)) \
- __fpsave = FP_SAVE_SCALAR; \
- if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA)) \
- __fpsave = FP_SAVE_VECTOR; \
- (last) = resume(prev, next, task_thread_info(next), __fpsave); \
-} while (0)
-
-#define finish_arch_switch(prev) \
-do { \
- u32 __c0_stat; \
- if (cop2_present && !cop2_lazy_restore && \
- (KSTK_STATUS(current) & ST0_CU2)) { \
- __c0_stat = read_c0_status(); \
- write_c0_status(__c0_stat | ST0_CU2); \
- cop2_restore(current); \
- write_c0_status(__c0_stat & ~ST0_CU2); \
+ if (cop2_present) { \
+ set_c0_status(ST0_CU2); \
+ if ((KSTK_STATUS(prev) & ST0_CU2)) { \
+ if (cop2_lazy_restore) \
+ KSTK_STATUS(prev) &= ~ST0_CU2; \
+ cop2_save(prev); \
+ } \
+ if (KSTK_STATUS(next) & ST0_CU2 && \
+ !cop2_lazy_restore) { \
+ cop2_restore(next); \
+ } \
+ clear_c0_status(ST0_CU2); \
} \
- if (cpu_has_dsp) \
- __restore_dsp(current); \
+ __clear_software_ll_bit(); \
if (cpu_has_userlocal) \
- write_c0_userlocal(current_thread_info()->tp_value); \
+ write_c0_userlocal(task_thread_info(next)->tp_value); \
__restore_watch(); \
- disable_msa(); \
+ (last) = resume(prev, next, task_thread_info(next)); \
} while (0)
#endif /* _ASM_SWITCH_TO_H */
diff --git a/kernel/arch/mips/include/asm/syscall.h b/kernel/arch/mips/include/asm/syscall.h
index 6499d93ae..47bc45a67 100644
--- a/kernel/arch/mips/include/asm/syscall.h
+++ b/kernel/arch/mips/include/asm/syscall.h
@@ -101,10 +101,8 @@ static inline void syscall_get_arguments(struct task_struct *task,
/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
if ((config_enabled(CONFIG_32BIT) ||
test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
- (regs->regs[2] == __NR_syscall)) {
+ (regs->regs[2] == __NR_syscall))
i++;
- n++;
- }
while (n--)
ret |= mips_get_syscall_arg(args++, task, regs, i++);
diff --git a/kernel/arch/mips/include/asm/thread_info.h b/kernel/arch/mips/include/asm/thread_info.h
index 9c0014e87..e309d8fcb 100644
--- a/kernel/arch/mips/include/asm/thread_info.h
+++ b/kernel/arch/mips/include/asm/thread_info.h
@@ -99,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 3 /* syscall auditing active */
#define TIF_SECCOMP 4 /* secure computing */
#define TIF_NOTIFY_RESUME 5 /* callback before returning to user */
+#define TIF_UPROBE 6 /* breakpointed or singlestepping */
#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
@@ -122,6 +123,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE (1<<TIF_UPROBE)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_NOHZ (1<<TIF_NOHZ)
#define _TIF_FIXADE (1<<TIF_FIXADE)
@@ -146,7 +148,8 @@ static inline struct thread_info *current_thread_info(void)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
- (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
+ (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME | \
+ _TIF_UPROBE)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_NOHZ | _TIF_WORK_MASK | \
_TIF_WORK_SYSCALL_EXIT | \
diff --git a/kernel/arch/mips/include/asm/time.h b/kernel/arch/mips/include/asm/time.h
index 8ab287422..17d4cd20f 100644
--- a/kernel/arch/mips/include/asm/time.h
+++ b/kernel/arch/mips/include/asm/time.h
@@ -51,7 +51,7 @@ extern int __weak get_c0_perfcount_int(void);
/*
* Initialize the calling CPU's compare interrupt as clockevent device
*/
-extern unsigned int __weak get_c0_compare_int(void);
+extern unsigned int get_c0_compare_int(void);
extern int r4k_clockevent_init(void);
static inline int mips_clockevent_init(void)
diff --git a/kernel/arch/mips/include/asm/tlbdebug.h b/kernel/arch/mips/include/asm/tlbdebug.h
index bb8f5c29c..3a25a8780 100644
--- a/kernel/arch/mips/include/asm/tlbdebug.h
+++ b/kernel/arch/mips/include/asm/tlbdebug.h
@@ -11,6 +11,7 @@
/*
* TLB debugging functions:
*/
+extern void dump_tlb_regs(void);
extern void dump_tlb_all(void);
#endif /* __ASM_TLBDEBUG_H */
diff --git a/kernel/arch/mips/include/asm/topology.h b/kernel/arch/mips/include/asm/topology.h
index 3e307ec2a..7afda4150 100644
--- a/kernel/arch/mips/include/asm/topology.h
+++ b/kernel/arch/mips/include/asm/topology.h
@@ -15,7 +15,7 @@
#define topology_physical_package_id(cpu) (cpu_data[cpu].package)
#define topology_core_id(cpu) (cpu_data[cpu].core)
#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
-#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu])
+#define topology_sibling_cpumask(cpu) (&cpu_sibling_map[cpu])
#endif
#endif /* __ASM_TOPOLOGY_H */
diff --git a/kernel/arch/mips/include/asm/txx9irq.h b/kernel/arch/mips/include/asm/txx9irq.h
index 5620879be..68a6650a4 100644
--- a/kernel/arch/mips/include/asm/txx9irq.h
+++ b/kernel/arch/mips/include/asm/txx9irq.h
@@ -11,7 +11,7 @@
#include <irq.h>
-#ifdef CONFIG_IRQ_CPU
+#ifdef CONFIG_IRQ_MIPS_CPU
#define TXX9_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
#else
#ifdef CONFIG_I8259
diff --git a/kernel/arch/mips/include/asm/uaccess.h b/kernel/arch/mips/include/asm/uaccess.h
index 9722357d2..095ecafe6 100644
--- a/kernel/arch/mips/include/asm/uaccess.h
+++ b/kernel/arch/mips/include/asm/uaccess.h
@@ -78,6 +78,21 @@ extern u64 __ua_limit;
#define segment_eq(a, b) ((a).seg == (b).seg)
+/*
+ * eva_kernel_access() - determine whether kernel memory access on an EVA system
+ *
+ * Determines whether memory accesses should be performed to kernel memory
+ * on a system using Extended Virtual Addressing (EVA).
+ *
+ * Return: true if a kernel memory access on an EVA system, else false.
+ */
+static inline bool eva_kernel_access(void)
+{
+ if (!config_enabled(CONFIG_EVA))
+ return false;
+
+ return segment_eq(get_fs(), get_ds());
+}
/*
* Is a address valid? This does a straighforward calculation rather
@@ -286,7 +301,7 @@ do { \
({ \
int __gu_err; \
\
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__get_kernel_common((x), size, ptr); \
} else { \
__chk_user_ptr(ptr); \
@@ -302,7 +317,7 @@ do { \
\
might_fault(); \
if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) { \
- if (segment_eq(get_fs(), get_ds())) \
+ if (eva_kernel_access()) \
__get_kernel_common((x), size, __gu_ptr); \
else \
__get_user_common((x), size, __gu_ptr); \
@@ -427,7 +442,7 @@ do { \
int __pu_err = 0; \
\
__pu_val = (x); \
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__put_kernel_common(ptr, size); \
} else { \
__chk_user_ptr(ptr); \
@@ -444,7 +459,7 @@ do { \
\
might_fault(); \
if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \
- if (segment_eq(get_fs(), get_ds())) \
+ if (eva_kernel_access()) \
__put_kernel_common(__pu_addr, size); \
else \
__put_user_common(__pu_addr, size); \
@@ -584,7 +599,7 @@ extern void __put_user_unknown(void);
* On error, the variable @x is set to zero.
*/
#define __get_user_unaligned(x,ptr) \
- __get_user__unalignednocheck((x),(ptr),sizeof(*(ptr)))
+ __get_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr)))
/*
* Yuck. We need two variants, one for 64bit operation and one
@@ -605,8 +620,8 @@ extern void __get_user_unaligned_unknown(void);
do { \
switch (size) { \
case 1: __get_data_asm(val, "lb", ptr); break; \
- case 2: __get_user_unaligned_asm(val, "ulh", ptr); break; \
- case 4: __get_user_unaligned_asm(val, "ulw", ptr); break; \
+ case 2: __get_data_unaligned_asm(val, "ulh", ptr); break; \
+ case 4: __get_data_unaligned_asm(val, "ulw", ptr); break; \
case 8: __GET_USER_UNALIGNED_DW(val, ptr); break; \
default: __get_user_unaligned_unknown(); break; \
} \
@@ -843,7 +858,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
__cu_from = (from); \
__cu_len = (n); \
might_fault(); \
- if (segment_eq(get_fs(), get_ds())) \
+ if (eva_kernel_access()) \
__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
__cu_len); \
else \
@@ -863,7 +878,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) \
+ if (eva_kernel_access()) \
__cu_len = __invoke_copy_to_kernel(__cu_to, __cu_from, \
__cu_len); \
else \
@@ -881,7 +896,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) \
+ if (eva_kernel_access()) \
__cu_len = __invoke_copy_from_kernel_inatomic(__cu_to, \
__cu_from,\
__cu_len);\
@@ -915,7 +930,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__cu_len = __invoke_copy_to_kernel(__cu_to, \
__cu_from, \
__cu_len); \
@@ -1107,9 +1122,15 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- might_fault(); \
- __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \
- __cu_len); \
+ if (eva_kernel_access()) { \
+ __cu_len = __invoke_copy_from_kernel(__cu_to, \
+ __cu_from, \
+ __cu_len); \
+ } else { \
+ might_fault(); \
+ __cu_len = __invoke_copy_from_user(__cu_to, __cu_from, \
+ __cu_len); \
+ } \
__cu_len; \
})
@@ -1139,7 +1160,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__cu_len = __invoke_copy_from_kernel(__cu_to, \
__cu_from, \
__cu_len); \
@@ -1163,7 +1184,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__cu_len = ___invoke_copy_in_kernel(__cu_to, __cu_from, \
__cu_len); \
} else { \
@@ -1183,7 +1204,7 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
__cu_to = (to); \
__cu_from = (from); \
__cu_len = (n); \
- if (segment_eq(get_fs(), get_ds())) { \
+ if (eva_kernel_access()) { \
__cu_len = ___invoke_copy_in_kernel(__cu_to,__cu_from, \
__cu_len); \
} else { \
@@ -1214,16 +1235,28 @@ __clear_user(void __user *addr, __kernel_size_t size)
{
__kernel_size_t res;
- might_fault();
- __asm__ __volatile__(
- "move\t$4, %1\n\t"
- "move\t$5, $0\n\t"
- "move\t$6, %2\n\t"
- __MODULE_JAL(__bzero)
- "move\t%0, $6"
- : "=r" (res)
- : "r" (addr), "r" (size)
- : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+ if (eva_kernel_access()) {
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, $0\n\t"
+ "move\t$6, %2\n\t"
+ __MODULE_JAL(__bzero_kernel)
+ "move\t%0, $6"
+ : "=r" (res)
+ : "r" (addr), "r" (size)
+ : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+ } else {
+ might_fault();
+ __asm__ __volatile__(
+ "move\t$4, %1\n\t"
+ "move\t$5, $0\n\t"
+ "move\t$6, %2\n\t"
+ __MODULE_JAL(__bzero)
+ "move\t%0, $6"
+ : "=r" (res)
+ : "r" (addr), "r" (size)
+ : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+ }
return res;
}
@@ -1263,7 +1296,7 @@ __strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;
- if (segment_eq(get_fs(), get_ds())) {
+ if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
@@ -1312,7 +1345,7 @@ strncpy_from_user(char *__to, const char __user *__from, long __len)
{
long res;
- if (segment_eq(get_fs(), get_ds())) {
+ if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
@@ -1357,7 +1390,7 @@ static inline long strlen_user(const char __user *s)
{
long res;
- if (segment_eq(get_fs(), get_ds())) {
+ if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
__MODULE_JAL(__strlen_kernel_asm)
@@ -1369,7 +1402,7 @@ static inline long strlen_user(const char __user *s)
might_fault();
__asm__ __volatile__(
"move\t$4, %1\n\t"
- __MODULE_JAL(__strlen_kernel_asm)
+ __MODULE_JAL(__strlen_user_asm)
"move\t%0, $2"
: "=r" (res)
: "r" (s)
@@ -1384,7 +1417,7 @@ static inline long __strnlen_user(const char __user *s, long n)
{
long res;
- if (segment_eq(get_fs(), get_ds())) {
+ if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
@@ -1426,7 +1459,7 @@ static inline long strnlen_user(const char __user *s, long n)
long res;
might_fault();
- if (segment_eq(get_fs(), get_ds())) {
+ if (eva_kernel_access()) {
__asm__ __volatile__(
"move\t$4, %1\n\t"
"move\t$5, %2\n\t"
diff --git a/kernel/arch/mips/include/asm/uprobes.h b/kernel/arch/mips/include/asm/uprobes.h
new file mode 100644
index 000000000..34c325c67
--- /dev/null
+++ b/kernel/arch/mips/include/asm/uprobes.h
@@ -0,0 +1,58 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_UPROBES_H
+#define __ASM_UPROBES_H
+
+#include <linux/notifier.h>
+#include <linux/types.h>
+
+#include <asm/break.h>
+#include <asm/inst.h>
+
+/*
+ * We want this to be defined as union mips_instruction but that makes the
+ * generic code blow up.
+ */
+typedef u32 uprobe_opcode_t;
+
+/*
+ * Classic MIPS (note this implementation doesn't consider microMIPS yet)
+ * instructions are always 4 bytes but in order to deal with branches and
+ * their delay slots, we treat instructions as having 8 bytes maximum.
+ */
+#define MAX_UINSN_BYTES 8
+#define UPROBE_XOL_SLOT_BYTES 128 /* Max. cache line size */
+
+#define UPROBE_BRK_UPROBE 0x000d000d /* break 13 */
+#define UPROBE_BRK_UPROBE_XOL 0x000e000d /* break 14 */
+
+#define UPROBE_SWBP_INSN UPROBE_BRK_UPROBE
+#define UPROBE_SWBP_INSN_SIZE 4
+
+struct arch_uprobe {
+ unsigned long resume_epc;
+ u32 insn[2];
+ u32 ixol[2];
+ union mips_instruction orig_inst[MAX_UINSN_BYTES / 4];
+};
+
+struct arch_uprobe_task {
+ unsigned long saved_trap_nr;
+};
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
+ struct mm_struct *mm, unsigned long addr);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup,
+ struct pt_regs *regs);
+extern unsigned long arch_uretprobe_hijack_return_addr(
+ unsigned long trampoline_vaddr, struct pt_regs *regs);
+
+#endif /* __ASM_UPROBES_H */
diff --git a/kernel/arch/mips/include/asm/vdso.h b/kernel/arch/mips/include/asm/vdso.h
index cca56aa40..8f4ca5dd9 100644
--- a/kernel/arch/mips/include/asm/vdso.h
+++ b/kernel/arch/mips/include/asm/vdso.h
@@ -1,29 +1,136 @@
/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
*
- * Copyright (C) 2009 Cavium Networks
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
-#include <linux/types.h>
+#include <linux/mm_types.h>
+#include <asm/barrier.h>
-#ifdef CONFIG_32BIT
-struct mips_vdso {
- u32 signal_trampoline[2];
- u32 rt_signal_trampoline[2];
+/**
+ * struct mips_vdso_image - Details of a VDSO image.
+ * @data: Pointer to VDSO image data (page-aligned).
+ * @size: Size of the VDSO image data (page-aligned).
+ * @off_sigreturn: Offset of the sigreturn() trampoline.
+ * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
+ * @mapping: Special mapping structure.
+ *
+ * This structure contains details of a VDSO image, including the image data
+ * and offsets of certain symbols required by the kernel. It is generated as
+ * part of the VDSO build process, aside from the mapping page array, which is
+ * populated at runtime.
+ */
+struct mips_vdso_image {
+ void *data;
+ unsigned long size;
+
+ unsigned long off_sigreturn;
+ unsigned long off_rt_sigreturn;
+
+ struct vm_special_mapping mapping;
};
-#else /* !CONFIG_32BIT */
-struct mips_vdso {
- u32 o32_signal_trampoline[2];
- u32 o32_rt_signal_trampoline[2];
- u32 rt_signal_trampoline[2];
- u32 n32_rt_signal_trampoline[2];
+
+/*
+ * The following structures are auto-generated as part of the build for each
+ * ABI by genvdso, see arch/mips/vdso/Makefile.
+ */
+
+extern struct mips_vdso_image vdso_image;
+
+#ifdef CONFIG_MIPS32_O32
+extern struct mips_vdso_image vdso_image_o32;
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+extern struct mips_vdso_image vdso_image_n32;
+#endif
+
+/**
+ * union mips_vdso_data - Data provided by the kernel for the VDSO.
+ * @xtime_sec: Current real time (seconds part).
+ * @xtime_nsec: Current real time (nanoseconds part, shifted).
+ * @wall_to_mono_sec: Wall-to-monotonic offset (seconds part).
+ * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part).
+ * @seq_count: Counter to synchronise updates (odd = updating).
+ * @cs_shift: Clocksource shift value.
+ * @clock_mode: Clocksource to use for time functions.
+ * @cs_mult: Clocksource multiplier value.
+ * @cs_cycle_last: Clock cycle value at last update.
+ * @cs_mask: Clocksource mask value.
+ * @tz_minuteswest: Minutes west of Greenwich (from timezone).
+ * @tz_dsttime: Type of DST correction (from timezone).
+ *
+ * This structure contains data needed by functions within the VDSO. It is
+ * populated by the kernel and mapped read-only into user memory. The time
+ * fields are mirrors of internal data from the timekeeping infrastructure.
+ *
+ * Note: Care should be taken when modifying as the layout must remain the same
+ * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
+ */
+union mips_vdso_data {
+ struct {
+ u64 xtime_sec;
+ u64 xtime_nsec;
+ u32 wall_to_mono_sec;
+ u32 wall_to_mono_nsec;
+ u32 seq_count;
+ u32 cs_shift;
+ u8 clock_mode;
+ u32 cs_mult;
+ u64 cs_cycle_last;
+ u64 cs_mask;
+ s32 tz_minuteswest;
+ s32 tz_dsttime;
+ };
+
+ u8 page[PAGE_SIZE];
};
-#endif /* CONFIG_32BIT */
+
+static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
+{
+ u32 seq;
+
+ while (true) {
+ seq = ACCESS_ONCE(data->seq_count);
+ if (likely(!(seq & 1))) {
+ /* Paired with smp_wmb() in vdso_data_write_*(). */
+ smp_rmb();
+ return seq;
+ }
+
+ cpu_relax();
+ }
+}
+
+static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
+ u32 start_seq)
+{
+ /* Paired with smp_wmb() in vdso_data_write_*(). */
+ smp_rmb();
+ return unlikely(data->seq_count != start_seq);
+}
+
+static inline void vdso_data_write_begin(union mips_vdso_data *data)
+{
+ ++data->seq_count;
+
+ /* Ensure sequence update is written before other data page values. */
+ smp_wmb();
+}
+
+static inline void vdso_data_write_end(union mips_vdso_data *data)
+{
+ /* Ensure data values are written before updating sequence again. */
+ smp_wmb();
+ ++data->seq_count;
+}
#endif /* __ASM_VDSO_H */
diff --git a/kernel/arch/mips/include/asm/vpe.h b/kernel/arch/mips/include/asm/vpe.h
index 7849f3978..80e70dbd1 100644
--- a/kernel/arch/mips/include/asm/vpe.h
+++ b/kernel/arch/mips/include/asm/vpe.h
@@ -122,7 +122,7 @@ void release_vpe(struct vpe *v);
void *alloc_progmem(unsigned long len);
void release_progmem(void *ptr);
-int __weak vpe_run(struct vpe *v);
+int vpe_run(struct vpe *v);
void cleanup_tc(struct tc *tc);
int __init vpe_module_init(void);
diff --git a/kernel/arch/mips/include/asm/xtalk/xwidget.h b/kernel/arch/mips/include/asm/xtalk/xwidget.h
index 32e4e884f..24f121da6 100644
--- a/kernel/arch/mips/include/asm/xtalk/xwidget.h
+++ b/kernel/arch/mips/include/asm/xtalk/xwidget.h
@@ -84,6 +84,118 @@
#define WIDGET_LLP_MAXBURST 0x000003ff
#define WIDGET_LLP_MAXBURST_SHFT 0
+/* Xtalk Widget Device Mfgr Nums */
+#define WIDGET_XBOW_MFGR_NUM 0x0 /* IP30 XBow Chip */
+#define WIDGET_XXBOW_MFGR_NUM 0x0 /* IP35 Xbow + XBridge Chip */
+#define WIDGET_ODYS_MFGR_NUM 0x023 /* Odyssey / VPro GFX */
+#define WIDGET_TPU_MFGR_NUM 0x024 /* Tensor Processor Unit */
+#define WIDGET_XBRDG_MFGR_NUM 0x024 /* IP35 XBridge Chip */
+#define WIDGET_HEART_MFGR_NUM 0x036 /* IP30 HEART Chip */
+#define WIDGET_BRIDG_MFGR_NUM 0x036 /* PCI Bridge */
+#define WIDGET_HUB_MFGR_NUM 0x036 /* IP27 Hub Chip */
+#define WIDGET_BDRCK_MFGR_NUM 0x036 /* IP35 Bedrock Chip */
+#define WIDGET_IMPCT_MFGR_NUM 0x2aa /* HQ4 / Impact GFX */
+#define WIDGET_KONA_MFGR_NUM 0x2aa /* InfiniteReality3 / Kona GFX */
+#define WIDGET_NULL_MFGR_NUM -1 /* NULL */
+
+/* Xtalk Widget Device Part Nums */
+#define WIDGET_XBOW_PART_NUM 0x0000
+#define WIDGET_HEART_PART_NUM 0xc001
+#define WIDGET_BRIDG_PART_NUM 0xc002
+#define WIDGET_IMPCT_PART_NUM 0xc003
+#define WIDGET_ODYS_PART_NUM 0xc013
+#define WIDGET_HUB_PART_NUM 0xc101
+#define WIDGET_KONA_PART_NUM 0xc102
+#define WIDGET_BDRCK_PART_NUM 0xc110
+#define WIDGET_TPU_PART_NUM 0xc202
+#define WIDGET_XXBOW_PART_NUM 0xd000
+#define WIDGET_XBRDG_PART_NUM 0xd002
+#define WIDGET_NULL_PART_NUM -1
+
+/* For Xtalk Widget identification */
+struct widget_ident {
+ u32 mfgr;
+ u32 part;
+ char *name;
+ char *revs[16];
+};
+
+/* Known Xtalk Widgets */
+static const struct widget_ident __initconst widget_idents[] = {
+ {
+ WIDGET_XBOW_MFGR_NUM,
+ WIDGET_XBOW_PART_NUM,
+ "xbow",
+ {NULL, "1.0", "1.1", "1.2", "1.3", "2.0", NULL},
+ },
+ {
+ WIDGET_HEART_MFGR_NUM,
+ WIDGET_HEART_PART_NUM,
+ "heart",
+ {NULL, "A", "B", "C", "D", "E", "F", NULL},
+ },
+ {
+ WIDGET_BRIDG_MFGR_NUM,
+ WIDGET_BRIDG_PART_NUM,
+ "bridge",
+ {NULL, "A", "B", "C", "D", NULL},
+ },
+ {
+ WIDGET_IMPCT_MFGR_NUM,
+ WIDGET_IMPCT_PART_NUM,
+ "impact",
+ {NULL, "A", "B", NULL},
+ },
+ {
+ WIDGET_ODYS_MFGR_NUM,
+ WIDGET_ODYS_PART_NUM,
+ "odyssey",
+ {NULL, "A", "B", NULL},
+ },
+ {
+ WIDGET_HUB_MFGR_NUM,
+ WIDGET_HUB_PART_NUM,
+ "hub",
+ {NULL, "1.0", "2.0", "2.1", "2.2", "2.3", "2.4", NULL},
+ },
+ {
+ WIDGET_KONA_MFGR_NUM,
+ WIDGET_KONA_PART_NUM,
+ "kona",
+ {NULL},
+ },
+ {
+ WIDGET_BDRCK_MFGR_NUM,
+ WIDGET_BDRCK_PART_NUM,
+ "bedrock",
+ {NULL, "1.0", "1.1", NULL},
+ },
+ {
+ WIDGET_TPU_MFGR_NUM,
+ WIDGET_TPU_PART_NUM,
+ "tpu",
+ {"0", NULL},
+ },
+ {
+ WIDGET_XXBOW_MFGR_NUM,
+ WIDGET_XXBOW_PART_NUM,
+ "xxbow",
+ {NULL, "1.0", "2.0", NULL},
+ },
+ {
+ WIDGET_XBRDG_MFGR_NUM,
+ WIDGET_XBRDG_PART_NUM,
+ "xbridge",
+ {NULL, "A", "B", NULL},
+ },
+ {
+ WIDGET_NULL_MFGR_NUM,
+ WIDGET_NULL_PART_NUM,
+ NULL,
+ {NULL},
+ }
+};
+
/*
* according to the crosstalk spec, only 32-bits access to the widget
* configuration registers is allowed. some widgets may allow 64-bits
diff --git a/kernel/arch/mips/include/uapi/asm/Kbuild b/kernel/arch/mips/include/uapi/asm/Kbuild
index 96fe7395e..f2cf41461 100644
--- a/kernel/arch/mips/include/uapi/asm/Kbuild
+++ b/kernel/arch/mips/include/uapi/asm/Kbuild
@@ -1,9 +1,9 @@
# UAPI Header export list
include include/uapi/asm-generic/Kbuild.asm
-generic-y += auxvec.h
generic-y += ipcbuf.h
+header-y += auxvec.h
header-y += bitfield.h
header-y += bitsperlong.h
header-y += break.h
diff --git a/kernel/arch/mips/include/uapi/asm/auxvec.h b/kernel/arch/mips/include/uapi/asm/auxvec.h
new file mode 100644
index 000000000..c9c719527
--- /dev/null
+++ b/kernel/arch/mips/include/uapi/asm/auxvec.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* Location of VDSO image. */
+#define AT_SYSINFO_EHDR 33
+
+#endif /* __ASM_AUXVEC_H */
diff --git a/kernel/arch/mips/include/uapi/asm/break.h b/kernel/arch/mips/include/uapi/asm/break.h
index 002c39ea2..9c4265cbf 100644
--- a/kernel/arch/mips/include/uapi/asm/break.h
+++ b/kernel/arch/mips/include/uapi/asm/break.h
@@ -21,6 +21,8 @@
#define BRK_DIVZERO 7 /* Divide by zero check */
#define BRK_RANGE 8 /* Range error check */
#define BRK_BUG 12 /* Used by BUG() */
+#define BRK_UPROBE 13 /* See <asm/uprobes.h> */
+#define BRK_UPROBE_XOL 14 /* See <asm/uprobes.h> */
#define BRK_MEMU 514 /* Used by FPU emulator */
#define BRK_KPROBE_BP 515 /* Kprobe break */
#define BRK_KPROBE_SSTEPBP 516 /* Kprobe single step software implementation */
diff --git a/kernel/arch/mips/include/uapi/asm/hwcap.h b/kernel/arch/mips/include/uapi/asm/hwcap.h
new file mode 100644
index 000000000..c7484a7ca
--- /dev/null
+++ b/kernel/arch/mips/include/uapi/asm/hwcap.h
@@ -0,0 +1,8 @@
+#ifndef _UAPI_ASM_HWCAP_H
+#define _UAPI_ASM_HWCAP_H
+
+/* HWCAP flags */
+#define HWCAP_MIPS_R6 (1 << 0)
+#define HWCAP_MIPS_MSA (1 << 1)
+
+#endif /* _UAPI_ASM_HWCAP_H */
diff --git a/kernel/arch/mips/include/uapi/asm/inst.h b/kernel/arch/mips/include/uapi/asm/inst.h
index fc0cf5ac0..9b44d5a81 100644
--- a/kernel/arch/mips/include/uapi/asm/inst.h
+++ b/kernel/arch/mips/include/uapi/asm/inst.h
@@ -26,7 +26,7 @@ enum major_op {
cop0_op, cop1_op, cop2_op, cop1x_op,
beql_op, bnel_op, blezl_op, bgtzl_op,
daddi_op, cbcond1_op = daddi_op, daddiu_op, ldl_op, ldr_op,
- spec2_op, jalx_op, mdmx_op, spec3_op,
+ spec2_op, jalx_op, mdmx_op, msa_op = mdmx_op, spec3_op,
lb_op, lh_op, lwl_op, lw_op,
lbu_op, lhu_op, lwr_op, lwu_op,
sb_op, sh_op, swl_op, sw_op,
@@ -167,8 +167,13 @@ enum cop1_sdw_func {
fround_op = 0x0c, ftrunc_op = 0x0d,
fceil_op = 0x0e, ffloor_op = 0x0f,
fmovc_op = 0x11, fmovz_op = 0x12,
- fmovn_op = 0x13, frecip_op = 0x15,
- frsqrt_op = 0x16, fcvts_op = 0x20,
+ fmovn_op = 0x13, fseleqz_op = 0x14,
+ frecip_op = 0x15, frsqrt_op = 0x16,
+ fselnez_op = 0x17, fmaddf_op = 0x18,
+ fmsubf_op = 0x19, frint_op = 0x1a,
+ fclass_op = 0x1b, fmin_op = 0x1c,
+ fmina_op = 0x1d, fmax_op = 0x1e,
+ fmaxa_op = 0x1f, fcvts_op = 0x20,
fcvtd_op = 0x21, fcvte_op = 0x22,
fcvtw_op = 0x24, fcvtl_op = 0x25,
fcmp_op = 0x30
@@ -221,6 +226,24 @@ enum bshfl_func {
};
/*
+ * func field for MSA MI10 format.
+ */
+enum msa_mi10_func {
+ msa_ld_op = 8,
+ msa_st_op = 9,
+};
+
+/*
+ * MSA 2 bit format fields.
+ */
+enum msa_2b_fmt {
+ msa_fmt_b = 0,
+ msa_fmt_h = 1,
+ msa_fmt_w = 2,
+ msa_fmt_d = 3,
+};
+
+/*
* (microMIPS) Major opcodes.
*/
enum mm_major_op {
@@ -611,6 +634,16 @@ struct v_format { /* MDMX vector format */
;)))))))
};
+struct msa_mi10_format { /* MSA MI10 */
+ __BITFIELD_FIELD(unsigned int opcode : 6,
+ __BITFIELD_FIELD(signed int s10 : 10,
+ __BITFIELD_FIELD(unsigned int rs : 5,
+ __BITFIELD_FIELD(unsigned int wd : 5,
+ __BITFIELD_FIELD(unsigned int func : 4,
+ __BITFIELD_FIELD(unsigned int df : 2,
+ ;))))))
+};
+
struct spec3_format { /* SPEC3 */
__BITFIELD_FIELD(unsigned int opcode:6,
__BITFIELD_FIELD(unsigned int rs:5,
@@ -888,6 +921,7 @@ union mips_instruction {
struct p_format p_format;
struct f_format f_format;
struct ma_format ma_format;
+ struct msa_mi10_format msa_mi10_format;
struct b_format b_format;
struct ps_format ps_format;
struct v_format v_format;
diff --git a/kernel/arch/mips/include/uapi/asm/mman.h b/kernel/arch/mips/include/uapi/asm/mman.h
index cfcb876ca..97c03f468 100644
--- a/kernel/arch/mips/include/uapi/asm/mman.h
+++ b/kernel/arch/mips/include/uapi/asm/mman.h
@@ -61,6 +61,12 @@
*/
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
+
+/*
+ * Flags for mlock
+ */
+#define MLOCK_ONFAULT 0x01 /* Lock pages in range after they are faulted in, do not prefault */
#define MADV_NORMAL 0 /* no further special treatment */
#define MADV_RANDOM 1 /* expect random page references */
diff --git a/kernel/arch/mips/include/uapi/asm/sigcontext.h b/kernel/arch/mips/include/uapi/asm/sigcontext.h
index 6c9906f59..5cbd9ae64 100644
--- a/kernel/arch/mips/include/uapi/asm/sigcontext.h
+++ b/kernel/arch/mips/include/uapi/asm/sigcontext.h
@@ -12,11 +12,23 @@
#include <linux/types.h>
#include <asm/sgidefs.h>
+/* scalar FP context was used */
+#define USED_FP (1 << 0)
+
+/* the value of Status.FR when context was saved */
+#define USED_FR1 (1 << 1)
+
+/* FR=1, but with odd singles in bits 63:32 of preceding even double */
+#define USED_HYBRID_FPRS (1 << 2)
+
+/* extended context was used, see struct extcontext for details */
+#define USED_EXTCONTEXT (1 << 3)
+
#if _MIPS_SIM == _MIPS_SIM_ABI32
/*
* Keep this struct definition in sync with the sigcontext fragment
- * in arch/mips/tools/offset.c
+ * in arch/mips/kernel/asm-offsets.c
*/
struct sigcontext {
unsigned int sc_regmask; /* Unused */
@@ -46,7 +58,7 @@ struct sigcontext {
#include <linux/posix_types.h>
/*
* Keep this struct definition in sync with the sigcontext fragment
- * in arch/mips/tools/offset.c
+ * in arch/mips/kernel/asm-offsets.c
*
* Warning: this structure illdefined with sc_badvaddr being just an unsigned
* int so it was changed to unsigned long in 2.6.0-test1. This may break
diff --git a/kernel/arch/mips/include/uapi/asm/swab.h b/kernel/arch/mips/include/uapi/asm/swab.h
index 8f2d184db..23cd9b118 100644
--- a/kernel/arch/mips/include/uapi/asm/swab.h
+++ b/kernel/arch/mips/include/uapi/asm/swab.h
@@ -13,8 +13,9 @@
#define __SWAB_64_THRU_32__
-#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) || \
- defined(_MIPS_ARCH_LOONGSON3A)
+#if !defined(__mips16) && \
+ ((defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) || \
+ defined(_MIPS_ARCH_LOONGSON3A))
static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
{
@@ -65,5 +66,5 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
}
#define __arch_swab64 __arch_swab64
#endif /* __mips64 */
-#endif /* MIPS R2 or newer or Loongson 3A */
+#endif /* (not __mips16) and (MIPS R2 or newer or Loongson 3A) */
#endif /* _ASM_SWAB_H */
diff --git a/kernel/arch/mips/include/uapi/asm/ucontext.h b/kernel/arch/mips/include/uapi/asm/ucontext.h
new file mode 100644
index 000000000..2320144ce
--- /dev/null
+++ b/kernel/arch/mips/include/uapi/asm/ucontext.h
@@ -0,0 +1,65 @@
+#ifndef __MIPS_UAPI_ASM_UCONTEXT_H
+#define __MIPS_UAPI_ASM_UCONTEXT_H
+
+/**
+ * struct extcontext - extended context header structure
+ * @magic: magic value identifying the type of extended context
+ * @size: the size in bytes of the enclosing structure
+ *
+ * Extended context structures provide context which does not fit within struct
+ * sigcontext. They are placed sequentially in memory at the end of struct
+ * ucontext and struct sigframe, with each extended context structure beginning
+ * with a header defined by this struct. The type of context represented is
+ * indicated by the magic field. Userland may check each extended context
+ * structure against magic values that it recognises. The size field allows any
+ * unrecognised context to be skipped, allowing for future expansion. The end
+ * of the extended context data is indicated by the magic value
+ * END_EXTCONTEXT_MAGIC.
+ */
+struct extcontext {
+ unsigned int magic;
+ unsigned int size;
+};
+
+/**
+ * struct msa_extcontext - MSA extended context structure
+ * @ext: the extended context header, with magic == MSA_EXTCONTEXT_MAGIC
+ * @wr: the most significant 64 bits of each MSA vector register
+ * @csr: the value of the MSA control & status register
+ *
+ * If MSA context is live for a task at the time a signal is delivered to it,
+ * this structure will hold the MSA context of the task as it was prior to the
+ * signal delivery.
+ */
+struct msa_extcontext {
+ struct extcontext ext;
+#define MSA_EXTCONTEXT_MAGIC 0x784d5341 /* xMSA */
+
+ unsigned long long wr[32];
+ unsigned int csr;
+};
+
+#define END_EXTCONTEXT_MAGIC 0x78454e44 /* xEND */
+
+/**
+ * struct ucontext - user context structure
+ * @uc_flags:
+ * @uc_link:
+ * @uc_stack:
+ * @uc_mcontext: holds basic processor state
+ * @uc_sigmask:
+ * @uc_extcontext: holds extended processor state
+ */
+struct ucontext {
+ /* Historic fields matching asm-generic */
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+
+ /* Extended context structures may follow ucontext */
+ unsigned long long uc_extcontext[0];
+};
+
+#endif /* __MIPS_UAPI_ASM_UCONTEXT_H */
diff --git a/kernel/arch/mips/include/uapi/asm/unistd.h b/kernel/arch/mips/include/uapi/asm/unistd.h
index c03088f9f..90f03a7da 100644
--- a/kernel/arch/mips/include/uapi/asm/unistd.h
+++ b/kernel/arch/mips/include/uapi/asm/unistd.h
@@ -377,16 +377,19 @@
#define __NR_memfd_create (__NR_Linux + 354)
#define __NR_bpf (__NR_Linux + 355)
#define __NR_execveat (__NR_Linux + 356)
+#define __NR_userfaultfd (__NR_Linux + 357)
+#define __NR_membarrier (__NR_Linux + 358)
+#define __NR_mlock2 (__NR_Linux + 359)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 356
+#define __NR_Linux_syscalls 359
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 356
+#define __NR_O32_Linux_syscalls 359
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -711,16 +714,19 @@
#define __NR_memfd_create (__NR_Linux + 314)
#define __NR_bpf (__NR_Linux + 315)
#define __NR_execveat (__NR_Linux + 316)
+#define __NR_userfaultfd (__NR_Linux + 317)
+#define __NR_membarrier (__NR_Linux + 318)
+#define __NR_mlock2 (__NR_Linux + 319)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 316
+#define __NR_Linux_syscalls 319
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 316
+#define __NR_64_Linux_syscalls 319
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -1049,15 +1055,18 @@
#define __NR_memfd_create (__NR_Linux + 318)
#define __NR_bpf (__NR_Linux + 319)
#define __NR_execveat (__NR_Linux + 320)
+#define __NR_userfaultfd (__NR_Linux + 321)
+#define __NR_membarrier (__NR_Linux + 322)
+#define __NR_mlock2 (__NR_Linux + 323)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 320
+#define __NR_Linux_syscalls 323
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 320
+#define __NR_N32_Linux_syscalls 323
#endif /* _UAPI_ASM_UNISTD_H */
diff --git a/kernel/arch/mips/jazz/irq.c b/kernel/arch/mips/jazz/irq.c
index e1ea4f625..5d6828b2a 100644
--- a/kernel/arch/mips/jazz/irq.c
+++ b/kernel/arch/mips/jazz/irq.c
@@ -110,18 +110,11 @@ asmlinkage void plat_irq_dispatch(void)
}
}
-static void r4030_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- /* Nothing to do ... */
-}
-
struct clock_event_device r4030_clockevent = {
.name = "r4030",
.features = CLOCK_EVT_FEAT_PERIODIC,
.rating = 300,
.irq = JAZZ_TIMER_IRQ,
- .set_mode = r4030_set_mode,
};
static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
diff --git a/kernel/arch/mips/jz4740/Kconfig b/kernel/arch/mips/jz4740/Kconfig
index 468903053..36f820176 100644
--- a/kernel/arch/mips/jz4740/Kconfig
+++ b/kernel/arch/mips/jz4740/Kconfig
@@ -1,9 +1,24 @@
choice
prompt "Machine type"
- depends on MACH_JZ4740
+ depends on MACH_INGENIC
default JZ4740_QI_LB60
config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote"
+ select MACH_JZ4740
+
+config JZ4780_CI20
+ bool "MIPS Creator CI20"
+ select MACH_JZ4780
endchoice
+
+config MACH_JZ4740
+ bool
+ select SYS_HAS_CPU_MIPS32_R1
+
+config MACH_JZ4780
+ bool
+ select MIPS_CPU_SCACHE
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_HIGHMEM
diff --git a/kernel/arch/mips/jz4740/Makefile b/kernel/arch/mips/jz4740/Makefile
index 28e5535df..39d70bde8 100644
--- a/kernel/arch/mips/jz4740/Makefile
+++ b/kernel/arch/mips/jz4740/Makefile
@@ -4,10 +4,12 @@
# Object file lists.
-obj-y += prom.o irq.o time.o reset.o setup.o \
- gpio.o clock.o platform.o timer.o serial.o
+obj-y += prom.o time.o reset.o setup.o \
+ platform.o timer.o
-obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
+obj-$(CONFIG_MACH_JZ4740) += gpio.o
+
+CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
# board specific support
diff --git a/kernel/arch/mips/jz4740/Platform b/kernel/arch/mips/jz4740/Platform
index c41d30080..28448d358 100644
--- a/kernel/arch/mips/jz4740/Platform
+++ b/kernel/arch/mips/jz4740/Platform
@@ -1,4 +1,4 @@
-platform-$(CONFIG_MACH_JZ4740) += jz4740/
-cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740
-load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000
-zload-$(CONFIG_MACH_JZ4740) += 0xffffffff80600000
+platform-$(CONFIG_MACH_INGENIC) += jz4740/
+cflags-$(CONFIG_MACH_INGENIC) += -I$(srctree)/arch/mips/include/asm/mach-jz4740
+load-$(CONFIG_MACH_INGENIC) += 0xffffffff80010000
+zload-$(CONFIG_MACH_INGENIC) += 0xffffffff80600000
diff --git a/kernel/arch/mips/jz4740/board-qi_lb60.c b/kernel/arch/mips/jz4740/board-qi_lb60.c
index 9dd051edb..934b15b5b 100644
--- a/kernel/arch/mips/jz4740/board-qi_lb60.c
+++ b/kernel/arch/mips/jz4740/board-qi_lb60.c
@@ -25,7 +25,9 @@
#include <linux/power_supply.h>
#include <linux/power/jz4740-battery.h>
#include <linux/power/gpio-charger.h>
+#include <linux/pwm.h>
+#include <asm/mach-jz4740/gpio.h>
#include <asm/mach-jz4740/jz4740_fb.h>
#include <asm/mach-jz4740/jz4740_mmc.h>
#include <asm/mach-jz4740/jz4740_nand.h>
@@ -33,8 +35,6 @@
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
-#include <linux/leds_pwm.h>
-
#include <asm/mach-jz4740/platform.h>
#include "clock.h"
@@ -398,13 +398,15 @@ static struct platform_device avt2_usb_regulator_device = {
}
};
+static struct pwm_lookup qi_lb60_pwm_lookup[] = {
+ PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
+ PWM_POLARITY_NORMAL),
+};
+
/* beeper */
static struct platform_device qi_lb60_pwm_beeper = {
.name = "pwm-beeper",
.id = -1,
- .dev = {
- .platform_data = (void *)4,
- },
};
/* charger */
@@ -482,8 +484,6 @@ static int __init qi_lb60_init_platform_devices(void)
gpiod_add_lookup_table(&qi_lb60_audio_gpio_table);
gpiod_add_lookup_table(&qi_lb60_nand_gpio_table);
- jz4740_serial_device_register();
-
spi_register_board_info(qi_lb60_spi_board_info,
ARRAY_SIZE(qi_lb60_spi_board_info));
@@ -492,16 +492,13 @@ static int __init qi_lb60_init_platform_devices(void)
platform_device_register(&jz4740_usb_ohci_device);
}
+ pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
+
return platform_add_devices(jz_platform_devices,
ARRAY_SIZE(jz_platform_devices));
}
-struct jz4740_clock_board_data jz4740_clock_bdata = {
- .ext_rate = 12000000,
- .rtc_rate = 32768,
-};
-
static __init int board_avt2(char *str)
{
qi_lb60_mmc_pdata.card_detect_active_low = 1;
diff --git a/kernel/arch/mips/jz4740/clock-debugfs.c b/kernel/arch/mips/jz4740/clock-debugfs.c
deleted file mode 100644
index 325422d0d..000000000
--- a/kernel/arch/mips/jz4740/clock-debugfs.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 SoC clock support debugfs entries
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include "clock.h"
-
-static struct dentry *jz4740_clock_debugfs;
-
-static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value)
-{
- struct clk *clk = data;
- *value = clk_is_enabled(clk);
-
- return 0;
-}
-
-static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value)
-{
- struct clk *clk = data;
-
- if (value)
- return clk_enable(clk);
- else
- clk_disable(clk);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled,
- jz4740_clock_debugfs_show_enabled,
- jz4740_clock_debugfs_set_enabled,
- "%llu\n");
-
-static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value)
-{
- struct clk *clk = data;
- *value = clk_get_rate(clk);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate,
- jz4740_clock_debugfs_show_rate,
- NULL,
- "%llu\n");
-
-void jz4740_clock_debugfs_add_clk(struct clk *clk)
-{
- if (!jz4740_clock_debugfs)
- return;
-
- clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs);
- debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk,
- &jz4740_clock_debugfs_ops_rate);
- debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk,
- &jz4740_clock_debugfs_ops_enabled);
-
- if (clk->parent) {
- char parent_path[100];
- snprintf(parent_path, 100, "../%s", clk->parent->name);
- clk->debugfs_parent_entry = debugfs_create_symlink("parent",
- clk->debugfs_entry,
- parent_path);
- }
-}
-
-/* TODO: Locking */
-void jz4740_clock_debugfs_update_parent(struct clk *clk)
-{
- debugfs_remove(clk->debugfs_parent_entry);
-
- if (clk->parent) {
- char parent_path[100];
- snprintf(parent_path, 100, "../%s", clk->parent->name);
- clk->debugfs_parent_entry = debugfs_create_symlink("parent",
- clk->debugfs_entry,
- parent_path);
- } else {
- clk->debugfs_parent_entry = NULL;
- }
-}
-
-void jz4740_clock_debugfs_init(void)
-{
- jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL);
- if (IS_ERR(jz4740_clock_debugfs))
- jz4740_clock_debugfs = NULL;
-}
diff --git a/kernel/arch/mips/jz4740/clock.c b/kernel/arch/mips/jz4740/clock.c
deleted file mode 100644
index 1b5f55426..000000000
--- a/kernel/arch/mips/jz4740/clock.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 SoC clock support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/err.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include <asm/mach-jz4740/base.h>
-
-#include "clock.h"
-
-#define JZ_REG_CLOCK_CTRL 0x00
-#define JZ_REG_CLOCK_LOW_POWER 0x04
-#define JZ_REG_CLOCK_PLL 0x10
-#define JZ_REG_CLOCK_GATE 0x20
-#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
-#define JZ_REG_CLOCK_I2S 0x60
-#define JZ_REG_CLOCK_LCD 0x64
-#define JZ_REG_CLOCK_MMC 0x68
-#define JZ_REG_CLOCK_UHC 0x6C
-#define JZ_REG_CLOCK_SPI 0x74
-
-#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
-#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
-#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
-#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
-#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
-#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
-#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
-#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
-#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
-#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
-#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
-#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
-#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
-
-#define JZ_CLOCK_GATE_UART0 BIT(0)
-#define JZ_CLOCK_GATE_TCU BIT(1)
-#define JZ_CLOCK_GATE_RTC BIT(2)
-#define JZ_CLOCK_GATE_I2C BIT(3)
-#define JZ_CLOCK_GATE_SPI BIT(4)
-#define JZ_CLOCK_GATE_AIC BIT(5)
-#define JZ_CLOCK_GATE_I2S BIT(6)
-#define JZ_CLOCK_GATE_MMC BIT(7)
-#define JZ_CLOCK_GATE_ADC BIT(8)
-#define JZ_CLOCK_GATE_CIM BIT(9)
-#define JZ_CLOCK_GATE_LCD BIT(10)
-#define JZ_CLOCK_GATE_UDC BIT(11)
-#define JZ_CLOCK_GATE_DMAC BIT(12)
-#define JZ_CLOCK_GATE_IPU BIT(13)
-#define JZ_CLOCK_GATE_UHC BIT(14)
-#define JZ_CLOCK_GATE_UART1 BIT(15)
-
-#define JZ_CLOCK_I2S_DIV_MASK 0x01ff
-
-#define JZ_CLOCK_LCD_DIV_MASK 0x01ff
-
-#define JZ_CLOCK_MMC_DIV_MASK 0x001f
-
-#define JZ_CLOCK_UHC_DIV_MASK 0x000f
-
-#define JZ_CLOCK_SPI_SRC_PLL BIT(31)
-#define JZ_CLOCK_SPI_DIV_MASK 0x000f
-
-#define JZ_CLOCK_PLL_M_MASK 0x01ff
-#define JZ_CLOCK_PLL_N_MASK 0x001f
-#define JZ_CLOCK_PLL_OD_MASK 0x0003
-#define JZ_CLOCK_PLL_STABLE BIT(10)
-#define JZ_CLOCK_PLL_BYPASS BIT(9)
-#define JZ_CLOCK_PLL_ENABLED BIT(8)
-#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
-#define JZ_CLOCK_PLL_M_OFFSET 23
-#define JZ_CLOCK_PLL_N_OFFSET 18
-#define JZ_CLOCK_PLL_OD_OFFSET 16
-
-#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
-#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
-
-#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
-#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
-
-static void __iomem *jz_clock_base;
-static spinlock_t jz_clock_lock;
-static LIST_HEAD(jz_clocks);
-
-struct main_clk {
- struct clk clk;
- uint32_t div_offset;
-};
-
-struct divided_clk {
- struct clk clk;
- uint32_t reg;
- uint32_t mask;
-};
-
-struct static_clk {
- struct clk clk;
- unsigned long rate;
-};
-
-static uint32_t jz_clk_reg_read(int reg)
-{
- return readl(jz_clock_base + reg);
-}
-
-static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
-{
- uint32_t val2;
-
- spin_lock(&jz_clock_lock);
- val2 = readl(jz_clock_base + reg);
- val2 &= ~mask;
- val2 |= val;
- writel(val2, jz_clock_base + reg);
- spin_unlock(&jz_clock_lock);
-}
-
-static void jz_clk_reg_set_bits(int reg, uint32_t mask)
-{
- uint32_t val;
-
- spin_lock(&jz_clock_lock);
- val = readl(jz_clock_base + reg);
- val |= mask;
- writel(val, jz_clock_base + reg);
- spin_unlock(&jz_clock_lock);
-}
-
-static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
-{
- uint32_t val;
-
- spin_lock(&jz_clock_lock);
- val = readl(jz_clock_base + reg);
- val &= ~mask;
- writel(val, jz_clock_base + reg);
- spin_unlock(&jz_clock_lock);
-}
-
-static int jz_clk_enable_gating(struct clk *clk)
-{
- if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
- return -EINVAL;
-
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
- return 0;
-}
-
-static int jz_clk_disable_gating(struct clk *clk)
-{
- if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
- return -EINVAL;
-
- jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
- return 0;
-}
-
-static int jz_clk_is_enabled_gating(struct clk *clk)
-{
- if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
- return 1;
-
- return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
-}
-
-static unsigned long jz_clk_static_get_rate(struct clk *clk)
-{
- return ((struct static_clk *)clk)->rate;
-}
-
-static int jz_clk_ko_enable(struct clk *clk)
-{
- jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
- return 0;
-}
-
-static int jz_clk_ko_disable(struct clk *clk)
-{
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
- return 0;
-}
-
-static int jz_clk_ko_is_enabled(struct clk *clk)
-{
- return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
-}
-
-static const int pllno[] = {1, 2, 2, 4};
-
-static unsigned long jz_clk_pll_get_rate(struct clk *clk)
-{
- uint32_t val;
- int m;
- int n;
- int od;
-
- val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-
- if (val & JZ_CLOCK_PLL_BYPASS)
- return clk_get_rate(clk->parent);
-
- m = ((val >> 23) & 0x1ff) + 2;
- n = ((val >> 18) & 0x1f) + 2;
- od = (val >> 16) & 0x3;
-
- return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
-}
-
-static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
-{
- uint32_t reg;
-
- reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
- if (reg & JZ_CLOCK_CTRL_PLL_HALF)
- return jz_clk_pll_get_rate(clk->parent);
- return jz_clk_pll_get_rate(clk->parent) >> 1;
-}
-
-static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
-
-static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
- int div;
-
- div = parent_rate / rate;
- if (div > 32)
- return parent_rate / 32;
- else if (div < 1)
- return parent_rate;
-
- div &= (0x3 << (ffs(div) - 1));
-
- return parent_rate / div;
-}
-
-static unsigned long jz_clk_main_get_rate(struct clk *clk)
-{
- struct main_clk *mclk = (struct main_clk *)clk;
- uint32_t div;
-
- div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
- div >>= mclk->div_offset;
- div &= 0xf;
-
- if (div >= ARRAY_SIZE(jz_clk_main_divs))
- div = ARRAY_SIZE(jz_clk_main_divs) - 1;
-
- return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
-}
-
-static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
-{
- struct main_clk *mclk = (struct main_clk *)clk;
- int i;
- int div;
- unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
-
- rate = jz_clk_main_round_rate(clk, rate);
-
- div = parent_rate / rate;
-
- i = (ffs(div) - 1) << 1;
- if (i > 0 && !(div & BIT(i-1)))
- i -= 1;
-
- jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
- 0xf << mclk->div_offset);
-
- return 0;
-}
-
-static struct clk_ops jz_clk_static_ops = {
- .get_rate = jz_clk_static_get_rate,
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct static_clk jz_clk_ext = {
- .clk = {
- .name = "ext",
- .gate_bit = JZ4740_CLK_NOT_GATED,
- .ops = &jz_clk_static_ops,
- },
-};
-
-static struct clk_ops jz_clk_pll_ops = {
- .get_rate = jz_clk_pll_get_rate,
-};
-
-static struct clk jz_clk_pll = {
- .name = "pll",
- .parent = &jz_clk_ext.clk,
- .ops = &jz_clk_pll_ops,
-};
-
-static struct clk_ops jz_clk_pll_half_ops = {
- .get_rate = jz_clk_pll_half_get_rate,
-};
-
-static struct clk jz_clk_pll_half = {
- .name = "pll half",
- .parent = &jz_clk_pll,
- .ops = &jz_clk_pll_half_ops,
-};
-
-static const struct clk_ops jz_clk_main_ops = {
- .get_rate = jz_clk_main_get_rate,
- .set_rate = jz_clk_main_set_rate,
- .round_rate = jz_clk_main_round_rate,
-};
-
-static struct main_clk jz_clk_cpu = {
- .clk = {
- .name = "cclk",
- .parent = &jz_clk_pll,
- .ops = &jz_clk_main_ops,
- },
- .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_memory = {
- .clk = {
- .name = "mclk",
- .parent = &jz_clk_pll,
- .ops = &jz_clk_main_ops,
- },
- .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_high_speed_peripheral = {
- .clk = {
- .name = "hclk",
- .parent = &jz_clk_pll,
- .ops = &jz_clk_main_ops,
- },
- .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
-};
-
-
-static struct main_clk jz_clk_low_speed_peripheral = {
- .clk = {
- .name = "pclk",
- .parent = &jz_clk_pll,
- .ops = &jz_clk_main_ops,
- },
- .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
-};
-
-static const struct clk_ops jz_clk_ko_ops = {
- .enable = jz_clk_ko_enable,
- .disable = jz_clk_ko_disable,
- .is_enabled = jz_clk_ko_is_enabled,
-};
-
-static struct clk jz_clk_ko = {
- .name = "cko",
- .parent = &jz_clk_memory.clk,
- .ops = &jz_clk_ko_ops,
-};
-
-static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
-{
- if (parent == &jz_clk_pll)
- jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
- else if (parent == &jz_clk_ext.clk)
- jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
- else
- return -EINVAL;
-
- clk->parent = parent;
-
- return 0;
-}
-
-static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
-{
- if (parent == &jz_clk_pll_half)
- jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
- else if (parent == &jz_clk_ext.clk)
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
- else
- return -EINVAL;
-
- clk->parent = parent;
-
- return 0;
-}
-
-static int jz_clk_udc_enable(struct clk *clk)
-{
- jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
- JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
- return 0;
-}
-
-static int jz_clk_udc_disable(struct clk *clk)
-{
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
- JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
- return 0;
-}
-
-static int jz_clk_udc_is_enabled(struct clk *clk)
-{
- return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
- JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-}
-
-static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
-{
- if (parent == &jz_clk_pll_half)
- jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
- else if (parent == &jz_clk_ext.clk)
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
- else
- return -EINVAL;
-
- clk->parent = parent;
-
- return 0;
-}
-
-static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
-{
- int div;
-
- if (clk->parent == &jz_clk_ext.clk)
- return -EINVAL;
-
- div = clk_get_rate(clk->parent) / rate - 1;
-
- if (div < 0)
- div = 0;
- else if (div > 63)
- div = 63;
-
- jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
- JZ_CLOCK_CTRL_UDIV_MASK);
- return 0;
-}
-
-static unsigned long jz_clk_udc_get_rate(struct clk *clk)
-{
- int div;
-
- if (clk->parent == &jz_clk_ext.clk)
- return clk_get_rate(clk->parent);
-
- div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
- div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
- div += 1;
-
- return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long jz_clk_divided_get_rate(struct clk *clk)
-{
- struct divided_clk *dclk = (struct divided_clk *)clk;
- int div;
-
- if (clk->parent == &jz_clk_ext.clk)
- return clk_get_rate(clk->parent);
-
- div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
-
- return clk_get_rate(clk->parent) / div;
-}
-
-static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
-{
- struct divided_clk *dclk = (struct divided_clk *)clk;
- int div;
-
- if (clk->parent == &jz_clk_ext.clk)
- return -EINVAL;
-
- div = clk_get_rate(clk->parent) / rate - 1;
-
- if (div < 0)
- div = 0;
- else if (div > dclk->mask)
- div = dclk->mask;
-
- jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
-
- return 0;
-}
-
-static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
-{
- int div;
- unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
-
- if (rate > 150000000)
- return 150000000;
-
- div = parent_rate / rate;
- if (div < 1)
- div = 1;
- else if (div > 32)
- div = 32;
-
- return parent_rate / div;
-}
-
-static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
-{
- int div;
-
- if (rate > 150000000)
- return -EINVAL;
-
- div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
- if (div < 0)
- div = 0;
- else if (div > 31)
- div = 31;
-
- jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
- JZ_CLOCK_CTRL_LDIV_MASK);
-
- return 0;
-}
-
-static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
-{
- int div;
-
- div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
- div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
-
- return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
-}
-
-static const struct clk_ops jz_clk_ops_ld = {
- .set_rate = jz_clk_ldclk_set_rate,
- .get_rate = jz_clk_ldclk_get_rate,
- .round_rate = jz_clk_ldclk_round_rate,
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz_clk_ld = {
- .name = "lcd",
- .gate_bit = JZ_CLOCK_GATE_LCD,
- .parent = &jz_clk_pll_half,
- .ops = &jz_clk_ops_ld,
-};
-
-static const struct clk_ops jz_clk_i2s_ops = {
- .set_rate = jz_clk_divided_set_rate,
- .get_rate = jz_clk_divided_get_rate,
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
- .set_parent = jz_clk_i2s_set_parent,
-};
-
-static const struct clk_ops jz_clk_spi_ops = {
- .set_rate = jz_clk_divided_set_rate,
- .get_rate = jz_clk_divided_get_rate,
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
- .set_parent = jz_clk_spi_set_parent,
-};
-
-static const struct clk_ops jz_clk_divided_ops = {
- .set_rate = jz_clk_divided_set_rate,
- .get_rate = jz_clk_divided_get_rate,
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct divided_clk jz4740_clock_divided_clks[] = {
- [0] = {
- .clk = {
- .name = "i2s",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_I2S,
- .ops = &jz_clk_i2s_ops,
- },
- .reg = JZ_REG_CLOCK_I2S,
- .mask = JZ_CLOCK_I2S_DIV_MASK,
- },
- [1] = {
- .clk = {
- .name = "spi",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_SPI,
- .ops = &jz_clk_spi_ops,
- },
- .reg = JZ_REG_CLOCK_SPI,
- .mask = JZ_CLOCK_SPI_DIV_MASK,
- },
- [2] = {
- .clk = {
- .name = "lcd_pclk",
- .parent = &jz_clk_pll_half,
- .gate_bit = JZ4740_CLK_NOT_GATED,
- .ops = &jz_clk_divided_ops,
- },
- .reg = JZ_REG_CLOCK_LCD,
- .mask = JZ_CLOCK_LCD_DIV_MASK,
- },
- [3] = {
- .clk = {
- .name = "mmc",
- .parent = &jz_clk_pll_half,
- .gate_bit = JZ_CLOCK_GATE_MMC,
- .ops = &jz_clk_divided_ops,
- },
- .reg = JZ_REG_CLOCK_MMC,
- .mask = JZ_CLOCK_MMC_DIV_MASK,
- },
- [4] = {
- .clk = {
- .name = "uhc",
- .parent = &jz_clk_pll_half,
- .gate_bit = JZ_CLOCK_GATE_UHC,
- .ops = &jz_clk_divided_ops,
- },
- .reg = JZ_REG_CLOCK_UHC,
- .mask = JZ_CLOCK_UHC_DIV_MASK,
- },
-};
-
-static const struct clk_ops jz_clk_udc_ops = {
- .set_parent = jz_clk_udc_set_parent,
- .set_rate = jz_clk_udc_set_rate,
- .get_rate = jz_clk_udc_get_rate,
- .enable = jz_clk_udc_enable,
- .disable = jz_clk_udc_disable,
- .is_enabled = jz_clk_udc_is_enabled,
-};
-
-static const struct clk_ops jz_clk_simple_ops = {
- .enable = jz_clk_enable_gating,
- .disable = jz_clk_disable_gating,
- .is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz4740_clock_simple_clks[] = {
- [0] = {
- .name = "udc",
- .parent = &jz_clk_ext.clk,
- .ops = &jz_clk_udc_ops,
- },
- [1] = {
- .name = "uart0",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_UART0,
- .ops = &jz_clk_simple_ops,
- },
- [2] = {
- .name = "uart1",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_UART1,
- .ops = &jz_clk_simple_ops,
- },
- [3] = {
- .name = "dma",
- .parent = &jz_clk_high_speed_peripheral.clk,
- .gate_bit = JZ_CLOCK_GATE_DMAC,
- .ops = &jz_clk_simple_ops,
- },
- [4] = {
- .name = "ipu",
- .parent = &jz_clk_high_speed_peripheral.clk,
- .gate_bit = JZ_CLOCK_GATE_IPU,
- .ops = &jz_clk_simple_ops,
- },
- [5] = {
- .name = "adc",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_ADC,
- .ops = &jz_clk_simple_ops,
- },
- [6] = {
- .name = "i2c",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_I2C,
- .ops = &jz_clk_simple_ops,
- },
- [7] = {
- .name = "aic",
- .parent = &jz_clk_ext.clk,
- .gate_bit = JZ_CLOCK_GATE_AIC,
- .ops = &jz_clk_simple_ops,
- },
-};
-
-static struct static_clk jz_clk_rtc = {
- .clk = {
- .name = "rtc",
- .gate_bit = JZ_CLOCK_GATE_RTC,
- .ops = &jz_clk_static_ops,
- },
- .rate = 32768,
-};
-
-int clk_enable(struct clk *clk)
-{
- if (!clk->ops->enable)
- return -EINVAL;
-
- return clk->ops->enable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- if (clk->ops->disable)
- clk->ops->disable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_disable);
-
-int clk_is_enabled(struct clk *clk)
-{
- if (clk->ops->is_enabled)
- return clk->ops->is_enabled(clk);
-
- return 1;
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- if (clk->ops->get_rate)
- return clk->ops->get_rate(clk);
- if (clk->parent)
- return clk_get_rate(clk->parent);
-
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- if (!clk->ops->set_rate)
- return -EINVAL;
- return clk->ops->set_rate(clk, rate);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- if (clk->ops->round_rate)
- return clk->ops->round_rate(clk, rate);
-
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_round_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- int ret;
- int enabled;
-
- if (!clk->ops->set_parent)
- return -EINVAL;
-
- enabled = clk_is_enabled(clk);
- if (enabled)
- clk_disable(clk);
- ret = clk->ops->set_parent(clk, parent);
- if (enabled)
- clk_enable(clk);
-
- jz4740_clock_debugfs_update_parent(clk);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_parent);
-
-struct clk *clk_get(struct device *dev, const char *name)
-{
- struct clk *clk;
-
- list_for_each_entry(clk, &jz_clocks, list) {
- if (strcmp(clk->name, name) == 0)
- return clk;
- }
- return ERR_PTR(-ENXIO);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
-
-static inline void clk_add(struct clk *clk)
-{
- list_add_tail(&clk->list, &jz_clocks);
-
- jz4740_clock_debugfs_add_clk(clk);
-}
-
-static void clk_register_clks(void)
-{
- size_t i;
-
- clk_add(&jz_clk_ext.clk);
- clk_add(&jz_clk_pll);
- clk_add(&jz_clk_pll_half);
- clk_add(&jz_clk_cpu.clk);
- clk_add(&jz_clk_high_speed_peripheral.clk);
- clk_add(&jz_clk_low_speed_peripheral.clk);
- clk_add(&jz_clk_ko);
- clk_add(&jz_clk_ld);
- clk_add(&jz_clk_rtc.clk);
-
- for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
- clk_add(&jz4740_clock_divided_clks[i].clk);
-
- for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
- clk_add(&jz4740_clock_simple_clks[i]);
-}
-
-void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
-{
- switch (mode) {
- case JZ4740_WAIT_MODE_IDLE:
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
- break;
- case JZ4740_WAIT_MODE_SLEEP:
- jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
- break;
- }
-}
-
-void jz4740_clock_udc_disable_auto_suspend(void)
-{
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
-
-void jz4740_clock_udc_enable_auto_suspend(void)
-{
- jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
-
-void jz4740_clock_suspend(void)
-{
- jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
- JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-}
-
-void jz4740_clock_resume(void)
-{
- uint32_t pll;
-
- jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-
- do {
- pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
- } while (!(pll & JZ_CLOCK_PLL_STABLE));
-
- jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
- JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-}
-
-static int jz4740_clock_init(void)
-{
- uint32_t val;
-
- jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
- if (!jz_clock_base)
- return -EBUSY;
-
- spin_lock_init(&jz_clock_lock);
-
- jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
- jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
-
- val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
-
- if (val & JZ_CLOCK_SPI_SRC_PLL)
- jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
-
- val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
- if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
- jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
-
- if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
- jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
-
- jz4740_clock_debugfs_init();
-
- clk_register_clks();
-
- return 0;
-}
-arch_initcall(jz4740_clock_init);
diff --git a/kernel/arch/mips/jz4740/clock.h b/kernel/arch/mips/jz4740/clock.h
deleted file mode 100644
index 5d07499d7..000000000
--- a/kernel/arch/mips/jz4740/clock.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 SoC clock support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_CLOCK_H__
-#define __MIPS_JZ4740_CLOCK_H__
-
-#include <linux/list.h>
-
-struct jz4740_clock_board_data {
- unsigned long ext_rate;
- unsigned long rtc_rate;
-};
-
-extern struct jz4740_clock_board_data jz4740_clock_bdata;
-
-void jz4740_clock_suspend(void);
-void jz4740_clock_resume(void);
-
-struct clk;
-
-struct clk_ops {
- unsigned long (*get_rate)(struct clk *clk);
- unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
- int (*set_rate)(struct clk *clk, unsigned long rate);
- int (*enable)(struct clk *clk);
- int (*disable)(struct clk *clk);
- int (*is_enabled)(struct clk *clk);
-
- int (*set_parent)(struct clk *clk, struct clk *parent);
-
-};
-
-struct clk {
- const char *name;
- struct clk *parent;
-
- uint32_t gate_bit;
-
- const struct clk_ops *ops;
-
- struct list_head list;
-
-#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs_entry;
- struct dentry *debugfs_parent_entry;
-#endif
-
-};
-
-#define JZ4740_CLK_NOT_GATED ((uint32_t)-1)
-
-int clk_is_enabled(struct clk *clk);
-
-#ifdef CONFIG_DEBUG_FS
-void jz4740_clock_debugfs_init(void);
-void jz4740_clock_debugfs_add_clk(struct clk *clk);
-void jz4740_clock_debugfs_update_parent(struct clk *clk);
-#else
-static inline void jz4740_clock_debugfs_init(void) {};
-static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {};
-static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {};
-#endif
-
-#endif
diff --git a/kernel/arch/mips/jz4740/gpio.c b/kernel/arch/mips/jz4740/gpio.c
index 00b798d2f..8c6d76c9b 100644
--- a/kernel/arch/mips/jz4740/gpio.c
+++ b/kernel/arch/mips/jz4740/gpio.c
@@ -21,14 +21,14 @@
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/irqchip/ingenic.h>
#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <asm/mach-jz4740/base.h>
-
-#include "irq.h"
+#include <asm/mach-jz4740/gpio.h>
#define JZ4740_GPIO_BASE_A (32*0)
#define JZ4740_GPIO_BASE_B (32*1)
@@ -232,6 +232,13 @@ static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
return 0;
}
+static int jz_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ struct jz_gpio_chip *jz_gpio = gpio_chip_to_jz_gpio_chip(chip);
+
+ return jz_gpio->irq_base + gpio;
+}
+
int jz_gpio_port_direction_input(int port, uint32_t mask)
{
writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR));
@@ -263,18 +270,6 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
}
EXPORT_SYMBOL(jz_gpio_port_get_value);
-int gpio_to_irq(unsigned gpio)
-{
- return JZ4740_IRQ_GPIO(0) + gpio;
-}
-EXPORT_SYMBOL_GPL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
- return irq - JZ4740_IRQ_GPIO(0);
-}
-EXPORT_SYMBOL_GPL(irq_to_gpio);
-
#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
@@ -297,7 +292,7 @@ static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int i
writel(mask, reg);
}
-static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+static void jz_gpio_irq_demux_handler(struct irq_desc *desc)
{
uint32_t flag;
unsigned int gpio_irq;
@@ -404,6 +399,7 @@ static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
.get = jz_gpio_get_value, \
.direction_output = jz_gpio_direction_output, \
.direction_input = jz_gpio_direction_input, \
+ .to_irq = jz_gpio_to_irq, \
.base = JZ4740_GPIO_BASE_ ## _bank, \
.ngpio = JZ4740_GPIO_NUM_ ## _bank, \
}, \
@@ -424,8 +420,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100);
chip->irq = JZ4740_IRQ_INTC_GPIO(id);
- irq_set_handler_data(chip->irq, chip);
- irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+ irq_set_chained_handler_and_data(chip->irq,
+ jz_gpio_irq_demux_handler, chip);
gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base,
chip->base, handle_level_irq);
@@ -442,8 +438,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_unmask = jz_gpio_irq_unmask;
ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_suspend = jz4740_irq_suspend;
- ct->chip.irq_resume = jz4740_irq_resume;
+ ct->chip.irq_suspend = ingenic_intc_irq_suspend;
+ ct->chip.irq_resume = ingenic_intc_irq_resume;
ct->chip.irq_startup = jz_gpio_irq_startup;
ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
ct->chip.irq_set_type = jz_gpio_irq_set_type;
diff --git a/kernel/arch/mips/jz4740/irq.c b/kernel/arch/mips/jz4740/irq.c
deleted file mode 100644
index 97206b3de..000000000
--- a/kernel/arch/mips/jz4740/irq.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 platform IRQ support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/irq_cpu.h>
-
-#include <asm/mach-jz4740/base.h>
-#include <asm/mach-jz4740/irq.h>
-
-#include "irq.h"
-
-static void __iomem *jz_intc_base;
-
-#define JZ_REG_INTC_STATUS 0x00
-#define JZ_REG_INTC_MASK 0x04
-#define JZ_REG_INTC_SET_MASK 0x08
-#define JZ_REG_INTC_CLEAR_MASK 0x0c
-#define JZ_REG_INTC_PENDING 0x10
-
-static irqreturn_t jz4740_cascade(int irq, void *data)
-{
- uint32_t irq_reg;
-
- irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
-
- if (irq_reg)
- generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
-
- return IRQ_HANDLED;
-}
-
-static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
-{
- struct irq_chip_regs *regs = &gc->chip_types->regs;
-
- writel(mask, gc->reg_base + regs->enable);
- writel(~mask, gc->reg_base + regs->disable);
-}
-
-void jz4740_irq_suspend(struct irq_data *data)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
- jz4740_irq_set_mask(gc, gc->wake_active);
-}
-
-void jz4740_irq_resume(struct irq_data *data)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
- jz4740_irq_set_mask(gc, gc->mask_cache);
-}
-
-static struct irqaction jz4740_cascade_action = {
- .handler = jz4740_cascade,
- .name = "JZ4740 cascade interrupt",
-};
-
-void __init arch_init_irq(void)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- mips_cpu_irq_init();
-
- jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
-
- /* Mask all irqs */
- writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
-
- gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
- handle_level_irq);
-
- gc->wake_enabled = IRQ_MSK(32);
-
- ct = gc->chip_types;
- ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
- ct->regs.disable = JZ_REG_INTC_SET_MASK;
- ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
- ct->chip.irq_mask = irq_gc_mask_disable_reg;
- ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
- ct->chip.irq_set_wake = irq_gc_set_wake;
- ct->chip.irq_suspend = jz4740_irq_suspend;
- ct->chip.irq_resume = jz4740_irq_resume;
-
- irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
-
- setup_irq(2, &jz4740_cascade_action);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
- if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- do_IRQ(3);
- else
- spurious_interrupt();
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static inline void intc_seq_reg(struct seq_file *s, const char *name,
- unsigned int reg)
-{
- seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
-}
-
-static int intc_regs_show(struct seq_file *s, void *unused)
-{
- intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
- intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
- intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
-
- return 0;
-}
-
-static int intc_regs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, intc_regs_show, NULL);
-}
-
-static const struct file_operations intc_regs_operations = {
- .open = intc_regs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init intc_debugfs_init(void)
-{
- (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
- NULL, NULL, &intc_regs_operations);
- return 0;
-}
-subsys_initcall(intc_debugfs_init);
-
-#endif
diff --git a/kernel/arch/mips/jz4740/irq.h b/kernel/arch/mips/jz4740/irq.h
deleted file mode 100644
index 0f48720b5..000000000
--- a/kernel/arch/mips/jz4740/irq.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_IRQ_H__
-#define __MIPS_JZ4740_IRQ_H__
-
-#include <linux/irq.h>
-
-extern void jz4740_irq_suspend(struct irq_data *data);
-extern void jz4740_irq_resume(struct irq_data *data);
-
-#endif
diff --git a/kernel/arch/mips/jz4740/platform.c b/kernel/arch/mips/jz4740/platform.c
index 0b12f273c..e8a463b9b 100644
--- a/kernel/arch/mips/jz4740/platform.c
+++ b/kernel/arch/mips/jz4740/platform.c
@@ -13,6 +13,7 @@
*
*/
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
@@ -29,7 +30,6 @@
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
-#include "serial.h"
#include "clock.h"
/* OHCI controller */
@@ -279,42 +279,6 @@ struct platform_device jz4740_adc_device = {
.resource = jz4740_adc_resources,
};
-/* Serial */
-#define JZ4740_UART_DATA(_id) \
- { \
- .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \
- .iotype = UPIO_MEM, \
- .regshift = 2, \
- .serial_out = jz4740_serial_out, \
- .type = PORT_16550, \
- .mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \
- .irq = JZ4740_IRQ_UART ## _id, \
- }
-
-static struct plat_serial8250_port jz4740_uart_data[] = {
- JZ4740_UART_DATA(0),
- JZ4740_UART_DATA(1),
- {},
-};
-
-static struct platform_device jz4740_uart_device = {
- .name = "serial8250",
- .id = 0,
- .dev = {
- .platform_data = jz4740_uart_data,
- },
-};
-
-void jz4740_serial_device_register(void)
-{
- struct plat_serial8250_port *p;
-
- for (p = jz4740_uart_data; p->flags != 0; ++p)
- p->uartclk = jz4740_clock_bdata.ext_rate;
-
- platform_device_register(&jz4740_uart_device);
-}
-
/* Watchdog */
static struct resource jz4740_wdt_resources[] = {
{
diff --git a/kernel/arch/mips/jz4740/pm.c b/kernel/arch/mips/jz4740/pm.c
index d8e213010..2d8653f2f 100644
--- a/kernel/arch/mips/jz4740/pm.c
+++ b/kernel/arch/mips/jz4740/pm.c
@@ -20,8 +20,6 @@
#include <asm/mach-jz4740/clock.h>
-#include "clock.h"
-
static int jz4740_pm_enter(suspend_state_t state)
{
jz4740_clock_suspend();
diff --git a/kernel/arch/mips/jz4740/prom.c b/kernel/arch/mips/jz4740/prom.c
index 5a93f3815..6984683c9 100644
--- a/kernel/arch/mips/jz4740/prom.c
+++ b/kernel/arch/mips/jz4740/prom.c
@@ -53,16 +53,3 @@ void __init prom_init(void)
void __init prom_free_prom_memory(void)
{
}
-
-#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2)))
-
-void prom_putchar(char c)
-{
- uint8_t lsr;
-
- do {
- lsr = readb(UART_REG(UART_LSR));
- } while ((lsr & UART_LSR_TEMT) == 0);
-
- writeb(c, UART_REG(UART_TX));
-}
diff --git a/kernel/arch/mips/jz4740/reset.c b/kernel/arch/mips/jz4740/reset.c
index b6c6343d2..954e669c9 100644
--- a/kernel/arch/mips/jz4740/reset.c
+++ b/kernel/arch/mips/jz4740/reset.c
@@ -12,6 +12,7 @@
*
*/
+#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/pm.h>
@@ -79,12 +80,20 @@ static void jz4740_power_off(void)
void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
unsigned long wakeup_filter_ticks;
unsigned long reset_counter_ticks;
+ struct clk *rtc_clk;
+ unsigned long rtc_rate;
+
+ rtc_clk = clk_get(NULL, "rtc");
+ if (IS_ERR(rtc_clk))
+ panic("unable to get RTC clock");
+ rtc_rate = clk_get_rate(rtc_clk);
+ clk_put(rtc_clk);
/*
* Set minimum wakeup pin assertion time: 100 ms.
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
*/
- wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000;
+ wakeup_filter_ticks = (100 * rtc_rate) / 1000;
if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
else
@@ -96,7 +105,7 @@ static void jz4740_power_off(void)
* Set reset pin low-level assertion time after wakeup: 60 ms.
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
*/
- reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000;
+ reset_counter_ticks = (60 * rtc_rate) / 1000;
if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
else
diff --git a/kernel/arch/mips/jz4740/serial.c b/kernel/arch/mips/jz4740/serial.c
deleted file mode 100644
index d23de4582..000000000
--- a/kernel/arch/mips/jz4740/serial.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 serial support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/io.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value)
-{
- switch (offset) {
- case UART_FCR:
- value |= 0x10; /* Enable uart module */
- break;
- case UART_IER:
- value |= (value & 0x4) << 2;
- break;
- default:
- break;
- }
- writeb(value, p->membase + (offset << p->regshift));
-}
diff --git a/kernel/arch/mips/jz4740/serial.h b/kernel/arch/mips/jz4740/serial.h
deleted file mode 100644
index 8eb715bb1..000000000
--- a/kernel/arch/mips/jz4740/serial.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4740 serial support
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_SERIAL_H__
-#define __MIPS_JZ4740_SERIAL_H__
-
-struct uart_port;
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value);
-
-#endif
diff --git a/kernel/arch/mips/jz4740/setup.c b/kernel/arch/mips/jz4740/setup.c
index ef796f97b..510fc0d96 100644
--- a/kernel/arch/mips/jz4740/setup.c
+++ b/kernel/arch/mips/jz4740/setup.c
@@ -16,9 +16,14 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/irqchip.h>
#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
#include <asm/bootinfo.h>
+#include <asm/prom.h>
#include <asm/mach-jz4740/base.h>
@@ -51,11 +56,40 @@ static void __init jz4740_detect_mem(void)
void __init plat_mem_setup(void)
{
+ int offset;
+
jz4740_reset_init();
- jz4740_detect_mem();
+ __dt_setup_arch(__dtb_start);
+
+ offset = fdt_path_offset(__dtb_start, "/memory");
+ if (offset < 0)
+ jz4740_detect_mem();
}
+void __init device_tree_init(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ unflatten_and_copy_device_tree();
+}
+
+static int __init populate_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ return 0;
+}
+arch_initcall(populate_machine);
+
const char *get_system_type(void)
{
+ if (config_enabled(CONFIG_MACH_JZ4780))
+ return "JZ4780";
+
return "JZ4740";
}
+
+void __init arch_init_irq(void)
+{
+ irqchip_init();
+}
diff --git a/kernel/arch/mips/jz4740/time.c b/kernel/arch/mips/jz4740/time.c
index 72b0cecbc..1f7ca2c9f 100644
--- a/kernel/arch/mips/jz4740/time.c
+++ b/kernel/arch/mips/jz4740/time.c
@@ -13,6 +13,8 @@
*
*/
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/time.h>
@@ -20,6 +22,7 @@
#include <linux/clockchips.h>
#include <linux/sched_clock.h>
+#include <asm/mach-jz4740/clock.h>
#include <asm/mach-jz4740/irq.h>
#include <asm/mach-jz4740/timer.h>
#include <asm/time.h>
@@ -55,7 +58,7 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
jz4740_timer_ack_full(TIMER_CLOCKEVENT);
- if (cd->mode != CLOCK_EVT_MODE_PERIODIC)
+ if (!clockevent_state_periodic(cd))
jz4740_timer_disable(TIMER_CLOCKEVENT);
cd->event_handler(cd);
@@ -63,24 +66,29 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid)
return IRQ_HANDLED;
}
-static void jz4740_clockevent_set_mode(enum clock_event_mode mode,
- struct clock_event_device *cd)
+static int jz4740_clockevent_set_periodic(struct clock_event_device *evt)
{
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
- jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
- case CLOCK_EVT_MODE_RESUME:
- jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
- jz4740_timer_enable(TIMER_CLOCKEVENT);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_SHUTDOWN:
- jz4740_timer_disable(TIMER_CLOCKEVENT);
- break;
- default:
- break;
- }
+ jz4740_timer_set_count(TIMER_CLOCKEVENT, 0);
+ jz4740_timer_set_period(TIMER_CLOCKEVENT, jz4740_jiffies_per_tick);
+ jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+ jz4740_timer_enable(TIMER_CLOCKEVENT);
+
+ return 0;
+}
+
+static int jz4740_clockevent_resume(struct clock_event_device *evt)
+{
+ jz4740_timer_irq_full_enable(TIMER_CLOCKEVENT);
+ jz4740_timer_enable(TIMER_CLOCKEVENT);
+
+ return 0;
+}
+
+static int jz4740_clockevent_shutdown(struct clock_event_device *evt)
+{
+ jz4740_timer_disable(TIMER_CLOCKEVENT);
+
+ return 0;
}
static int jz4740_clockevent_set_next(unsigned long evt,
@@ -97,9 +105,17 @@ static struct clock_event_device jz4740_clockevent = {
.name = "jz4740-timer",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = jz4740_clockevent_set_next,
- .set_mode = jz4740_clockevent_set_mode,
+ .set_state_shutdown = jz4740_clockevent_shutdown,
+ .set_state_periodic = jz4740_clockevent_set_periodic,
+ .set_state_oneshot = jz4740_clockevent_shutdown,
+ .tick_resume = jz4740_clockevent_resume,
.rating = 200,
+#ifdef CONFIG_MACH_JZ4740
.irq = JZ4740_IRQ_TCU0,
+#endif
+#ifdef CONFIG_MACH_JZ4780
+ .irq = JZ4780_IRQ_TCU2,
+#endif
};
static struct irqaction timer_irqaction = {
@@ -114,10 +130,17 @@ void __init plat_time_init(void)
int ret;
uint32_t clk_rate;
uint16_t ctrl;
+ struct clk *ext_clk;
+ of_clk_init(NULL);
jz4740_timer_init();
- clk_rate = jz4740_clock_bdata.ext_rate >> 4;
+ ext_clk = clk_get(NULL, "ext");
+ if (IS_ERR(ext_clk))
+ panic("unable to get ext clock");
+ clk_rate = clk_get_rate(ext_clk) >> 4;
+ clk_put(ext_clk);
+
jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ);
clockevent_set_clock(&jz4740_clockevent, clk_rate);
@@ -134,7 +157,7 @@ void __init plat_time_init(void)
sched_clock_register(jz4740_read_sched_clock, 16, clk_rate);
- setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction);
+ setup_irq(jz4740_clockevent.irq, &timer_irqaction);
ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT;
diff --git a/kernel/arch/mips/kernel/Makefile b/kernel/arch/mips/kernel/Makefile
index d3d2ff2d7..68e2b7db9 100644
--- a/kernel/arch/mips/kernel/Makefile
+++ b/kernel/arch/mips/kernel/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
obj-$(CONFIG_MIPS_CMP) += smp-cmp.o
obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o
+obj-$(CONFIG_MIPS_CPS_NS16550) += cps-vec-ns16550.o
obj-$(CONFIG_MIPS_GIC_IPI) += smp-gic.o
obj-$(CONFIG_MIPS_SPRAM) += spram.o
@@ -61,8 +62,6 @@ 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
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_MIPS_MSC) += irq-msc01.o
obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o
@@ -77,6 +76,7 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_64BIT) += cpu-bugs64.o
@@ -100,6 +100,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_UPROBES) += uprobes.o
obj-$(CONFIG_MIPS_CM) += mips-cm.o
obj-$(CONFIG_MIPS_CPC) += mips-cpc.o
diff --git a/kernel/arch/mips/kernel/asm-offsets.c b/kernel/arch/mips/kernel/asm-offsets.c
index beabe19ff..154e2039e 100644
--- a/kernel/arch/mips/kernel/asm-offsets.c
+++ b/kernel/arch/mips/kernel/asm-offsets.c
@@ -1,5 +1,5 @@
/*
- * offset.c: Calculate pt_regs and task_struct offsets.
+ * asm-offsets.c: Calculate pt_regs and task_struct offsets.
*
* Copyright (C) 1996 David S. Miller
* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
@@ -128,6 +128,7 @@ void output_thread_defines(void)
thread.cp0_baduaddr);
OFFSET(THREAD_ECODE, task_struct, \
thread.error_code);
+ OFFSET(THREAD_TRAPNO, task_struct, thread.trap_nr);
BLANK();
}
@@ -245,17 +246,6 @@ void output_sc_defines(void)
}
#endif
-#ifdef CONFIG_MIPS32_COMPAT
-void output_sc32_defines(void)
-{
- COMMENT("Linux 32-bit sigcontext offsets.");
- OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs);
- OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr);
- OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir);
- BLANK();
-}
-#endif
-
void output_signal_defined(void)
{
COMMENT("Linux signal numbers.");
diff --git a/kernel/arch/mips/kernel/branch.c b/kernel/arch/mips/kernel/branch.c
index c0c5e5972..d8f9b357b 100644
--- a/kernel/arch/mips/kernel/branch.c
+++ b/kernel/arch/mips/kernel/branch.c
@@ -600,7 +600,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
break;
case blezl_op: /* not really i_format */
- if (NO_R6EMU)
+ if (!insn.i_format.rt && NO_R6EMU)
goto sigill_r6;
case blez_op:
/*
@@ -635,7 +635,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
break;
case bgtzl_op:
- if (NO_R6EMU)
+ if (!insn.i_format.rt && NO_R6EMU)
goto sigill_r6;
case bgtz_op:
/*
diff --git a/kernel/arch/mips/kernel/cevt-bcm1480.c b/kernel/arch/mips/kernel/cevt-bcm1480.c
index 797645718..940ac00e9 100644
--- a/kernel/arch/mips/kernel/cevt-bcm1480.c
+++ b/kernel/arch/mips/kernel/cevt-bcm1480.c
@@ -40,8 +40,8 @@
* The general purpose timer ticks at 1MHz independent if
* the rest of the system
*/
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+
+static int sibyte_set_periodic(struct clock_event_device *evt)
{
unsigned int cpu = smp_processor_id();
void __iomem *cfg, *init;
@@ -49,24 +49,22 @@ static void sibyte_set_mode(enum clock_event_mode mode,
cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- case CLOCK_EVT_MODE_RESUME:
- ;
- }
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, cfg);
+ return 0;
+}
+
+static int sibyte_shutdown(struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+
+ /* Stop the timer until we actually program a shot */
+ __raw_writeq(0, cfg);
+ return 0;
}
static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
@@ -91,7 +89,7 @@ static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
void __iomem *cfg;
unsigned long tmode;
- if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ if (clockevent_state_periodic(cd))
tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
else
tmode = 0;
@@ -130,7 +128,9 @@ void sb1480_clockevent_init(void)
cd->irq = irq;
cd->cpumask = cpumask_of(cpu);
cd->set_next_event = sibyte_next_event;
- cd->set_mode = sibyte_set_mode;
+ cd->set_state_shutdown = sibyte_shutdown;
+ cd->set_state_periodic = sibyte_set_periodic;
+ cd->set_state_oneshot = sibyte_shutdown;
clockevents_register_device(cd);
bcm1480_mask_irq(cpu, irq);
diff --git a/kernel/arch/mips/kernel/cevt-ds1287.c b/kernel/arch/mips/kernel/cevt-ds1287.c
index ff1f01b72..77a5ddf53 100644
--- a/kernel/arch/mips/kernel/cevt-ds1287.c
+++ b/kernel/arch/mips/kernel/cevt-ds1287.c
@@ -59,27 +59,32 @@ static int ds1287_set_next_event(unsigned long delta,
return -EINVAL;
}
-static void ds1287_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int ds1287_shutdown(struct clock_event_device *evt)
{
u8 val;
spin_lock(&rtc_lock);
val = CMOS_READ(RTC_REG_B);
+ val &= ~RTC_PIE;
+ CMOS_WRITE(val, RTC_REG_B);
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- val |= RTC_PIE;
- break;
- default:
- val &= ~RTC_PIE;
- break;
- }
+ spin_unlock(&rtc_lock);
+ return 0;
+}
+static int ds1287_set_periodic(struct clock_event_device *evt)
+{
+ u8 val;
+
+ spin_lock(&rtc_lock);
+
+ val = CMOS_READ(RTC_REG_B);
+ val |= RTC_PIE;
CMOS_WRITE(val, RTC_REG_B);
spin_unlock(&rtc_lock);
+ return 0;
}
static void ds1287_event_handler(struct clock_event_device *dev)
@@ -87,11 +92,13 @@ static void ds1287_event_handler(struct clock_event_device *dev)
}
static struct clock_event_device ds1287_clockevent = {
- .name = "ds1287",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .set_next_event = ds1287_set_next_event,
- .set_mode = ds1287_set_mode,
- .event_handler = ds1287_event_handler,
+ .name = "ds1287",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .set_next_event = ds1287_set_next_event,
+ .set_state_shutdown = ds1287_shutdown,
+ .set_state_periodic = ds1287_set_periodic,
+ .tick_resume = ds1287_shutdown,
+ .event_handler = ds1287_event_handler,
};
static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
diff --git a/kernel/arch/mips/kernel/cevt-gt641xx.c b/kernel/arch/mips/kernel/cevt-gt641xx.c
index f06946075..660400511 100644
--- a/kernel/arch/mips/kernel/cevt-gt641xx.c
+++ b/kernel/arch/mips/kernel/cevt-gt641xx.c
@@ -64,8 +64,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
return 0;
}
-static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int gt641xx_timer0_shutdown(struct clock_event_device *evt)
{
u32 ctrl;
@@ -73,21 +72,39 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
ctrl = GT_READ(GT_TC_CONTROL_OFS);
ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
+ GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+ raw_spin_unlock(&gt641xx_timer_lock);
+ return 0;
+}
+
+static int gt641xx_timer0_set_oneshot(struct clock_event_device *evt)
+{
+ u32 ctrl;
+
+ raw_spin_lock(&gt641xx_timer_lock);
+
+ ctrl = GT_READ(GT_TC_CONTROL_OFS);
+ ctrl &= ~GT_TC_CONTROL_SELTC0_MSK;
+ ctrl |= GT_TC_CONTROL_ENTC0_MSK;
+ GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
+
+ raw_spin_unlock(&gt641xx_timer_lock);
+ return 0;
+}
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- ctrl |= GT_TC_CONTROL_ENTC0_MSK;
- break;
- default:
- break;
- }
+static int gt641xx_timer0_set_periodic(struct clock_event_device *evt)
+{
+ u32 ctrl;
+
+ raw_spin_lock(&gt641xx_timer_lock);
+ ctrl = GT_READ(GT_TC_CONTROL_OFS);
+ ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
raw_spin_unlock(&gt641xx_timer_lock);
+ return 0;
}
static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
@@ -95,12 +112,16 @@ static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
}
static struct clock_event_device gt641xx_timer0_clockevent = {
- .name = "gt641xx-timer0",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .irq = GT641XX_TIMER0_IRQ,
- .set_next_event = gt641xx_timer0_set_next_event,
- .set_mode = gt641xx_timer0_set_mode,
- .event_handler = gt641xx_timer0_event_handler,
+ .name = "gt641xx-timer0",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .irq = GT641XX_TIMER0_IRQ,
+ .set_next_event = gt641xx_timer0_set_next_event,
+ .set_state_shutdown = gt641xx_timer0_shutdown,
+ .set_state_periodic = gt641xx_timer0_set_periodic,
+ .set_state_oneshot = gt641xx_timer0_set_oneshot,
+ .tick_resume = gt641xx_timer0_shutdown,
+ .event_handler = gt641xx_timer0_event_handler,
};
static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
diff --git a/kernel/arch/mips/kernel/cevt-r4k.c b/kernel/arch/mips/kernel/cevt-r4k.c
index d70c4d893..8dfe6a6e1 100644
--- a/kernel/arch/mips/kernel/cevt-r4k.c
+++ b/kernel/arch/mips/kernel/cevt-r4k.c
@@ -28,12 +28,6 @@ static int mips_next_event(unsigned long delta,
return res;
}
-void mips_set_clock_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- /* Nothing to do ... */
-}
-
DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
int cp0_timer_irq_installed;
@@ -174,6 +168,11 @@ int c0_compare_int_usable(void)
return 1;
}
+unsigned int __weak get_c0_compare_int(void)
+{
+ return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+}
+
int r4k_clockevent_init(void)
{
unsigned int cpu = smp_processor_id();
@@ -189,11 +188,9 @@ int r4k_clockevent_init(void)
/*
* With vectored interrupts things are getting platform specific.
* get_c0_compare_int is a hook to allow a platform to return the
- * interrupt number of it's liking.
+ * interrupt number of its liking.
*/
- irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
- if (get_c0_compare_int)
- irq = get_c0_compare_int();
+ irq = get_c0_compare_int();
cd = &per_cpu(mips_clockevent_device, cpu);
@@ -212,7 +209,6 @@ int r4k_clockevent_init(void)
cd->irq = irq;
cd->cpumask = cpumask_of(cpu);
cd->set_next_event = mips_next_event;
- cd->set_mode = mips_set_clock_mode;
cd->event_handler = mips_event_handler;
clockevents_register_device(cd);
diff --git a/kernel/arch/mips/kernel/cevt-sb1250.c b/kernel/arch/mips/kernel/cevt-sb1250.c
index 5ea6d6b1d..3d860efd6 100644
--- a/kernel/arch/mips/kernel/cevt-sb1250.c
+++ b/kernel/arch/mips/kernel/cevt-sb1250.c
@@ -38,8 +38,20 @@
* The general purpose timer ticks at 1MHz independent if
* the rest of the system
*/
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+
+static int sibyte_shutdown(struct clock_event_device *evt)
+{
+ void __iomem *cfg;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(smp_processor_id(), R_SCD_TIMER_CFG));
+
+ /* Stop the timer until we actually program a shot */
+ __raw_writeq(0, cfg);
+
+ return 0;
+}
+
+static int sibyte_set_periodic(struct clock_event_device *evt)
{
unsigned int cpu = smp_processor_id();
void __iomem *cfg, *init;
@@ -47,24 +59,11 @@ static void sibyte_set_mode(enum clock_event_mode mode,
cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- case CLOCK_EVT_MODE_RESUME:
- ;
- }
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, cfg);
+
+ return 0;
}
static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
@@ -89,7 +88,7 @@ static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
void __iomem *cfg;
unsigned long tmode;
- if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ if (clockevent_state_periodic(cd))
tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
else
tmode = 0;
@@ -129,7 +128,9 @@ void sb1250_clockevent_init(void)
cd->irq = irq;
cd->cpumask = cpumask_of(cpu);
cd->set_next_event = sibyte_next_event;
- cd->set_mode = sibyte_set_mode;
+ cd->set_state_shutdown = sibyte_shutdown;
+ cd->set_state_periodic = sibyte_set_periodic;
+ cd->set_state_oneshot = sibyte_shutdown;
clockevents_register_device(cd);
sb1250_mask_irq(cpu, irq);
diff --git a/kernel/arch/mips/kernel/cevt-txx9.c b/kernel/arch/mips/kernel/cevt-txx9.c
index 723932441..537eefdf8 100644
--- a/kernel/arch/mips/kernel/cevt-txx9.c
+++ b/kernel/arch/mips/kernel/cevt-txx9.c
@@ -85,36 +85,54 @@ static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
__raw_writel(0, &tmrptr->tisr);
}
-static void txx9tmr_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int txx9tmr_set_state_periodic(struct clock_event_device *evt)
{
struct txx9_clock_event_device *txx9_cd =
container_of(evt, struct txx9_clock_event_device, cd);
struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
txx9tmr_stop_and_clear(tmrptr);
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE,
- &tmrptr->itmr);
- /* start timer */
- __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >>
- evt->shift,
- &tmrptr->cpra);
- __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
- break;
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- __raw_writel(0, &tmrptr->itmr);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
- break;
- case CLOCK_EVT_MODE_RESUME:
- __raw_writel(TIMER_CCD, &tmrptr->ccdr);
- __raw_writel(0, &tmrptr->itmr);
- break;
- }
+
+ __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, &tmrptr->itmr);
+ /* start timer */
+ __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> evt->shift,
+ &tmrptr->cpra);
+ __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
+ return 0;
+}
+
+static int txx9tmr_set_state_oneshot(struct clock_event_device *evt)
+{
+ struct txx9_clock_event_device *txx9_cd =
+ container_of(evt, struct txx9_clock_event_device, cd);
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+ txx9tmr_stop_and_clear(tmrptr);
+ __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
+ return 0;
+}
+
+static int txx9tmr_set_state_shutdown(struct clock_event_device *evt)
+{
+ struct txx9_clock_event_device *txx9_cd =
+ container_of(evt, struct txx9_clock_event_device, cd);
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+ txx9tmr_stop_and_clear(tmrptr);
+ __raw_writel(0, &tmrptr->itmr);
+ return 0;
+}
+
+static int txx9tmr_tick_resume(struct clock_event_device *evt)
+{
+ struct txx9_clock_event_device *txx9_cd =
+ container_of(evt, struct txx9_clock_event_device, cd);
+ struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
+
+ txx9tmr_stop_and_clear(tmrptr);
+ __raw_writel(TIMER_CCD, &tmrptr->ccdr);
+ __raw_writel(0, &tmrptr->itmr);
+ return 0;
}
static int txx9tmr_set_next_event(unsigned long delta,
@@ -133,12 +151,15 @@ static int txx9tmr_set_next_event(unsigned long delta,
static struct txx9_clock_event_device txx9_clock_event_device = {
.cd = {
- .name = "TXx9",
- .features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT,
- .rating = 200,
- .set_mode = txx9tmr_set_mode,
- .set_next_event = txx9tmr_set_next_event,
+ .name = "TXx9",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .set_state_shutdown = txx9tmr_set_state_shutdown,
+ .set_state_periodic = txx9tmr_set_state_periodic,
+ .set_state_oneshot = txx9tmr_set_state_oneshot,
+ .tick_resume = txx9tmr_tick_resume,
+ .set_next_event = txx9tmr_set_next_event,
},
};
diff --git a/kernel/arch/mips/kernel/cps-vec-ns16550.S b/kernel/arch/mips/kernel/cps-vec-ns16550.S
new file mode 100644
index 000000000..6d246ad05
--- /dev/null
+++ b/kernel/arch/mips/kernel/cps-vec-ns16550.S
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <linux/serial_reg.h>
+
+#define UART_TX_OFS (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
+#define UART_LSR_OFS (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
+
+/**
+ * _mips_cps_putc() - write a character to the UART
+ * @a0: ASCII character to write
+ * @t9: UART base address
+ */
+LEAF(_mips_cps_putc)
+1: lw t0, UART_LSR_OFS(t9)
+ andi t0, t0, UART_LSR_TEMT
+ beqz t0, 1b
+ sb a0, UART_TX_OFS(t9)
+ jr ra
+ END(_mips_cps_putc)
+
+/**
+ * _mips_cps_puts() - write a string to the UART
+ * @a0: pointer to NULL-terminated ASCII string
+ * @t9: UART base address
+ *
+ * Write a null-terminated ASCII string to the UART.
+ */
+NESTED(_mips_cps_puts, 0, ra)
+ move s7, ra
+ move s6, a0
+
+1: lb a0, 0(s6)
+ beqz a0, 2f
+ jal _mips_cps_putc
+ PTR_ADDIU s6, s6, 1
+ b 1b
+
+2: jr s7
+ END(_mips_cps_puts)
+
+/**
+ * _mips_cps_putx4 - write a 4b hex value to the UART
+ * @a0: the 4b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a single hexadecimal character to the UART.
+ */
+NESTED(_mips_cps_putx4, 0, ra)
+ andi a0, a0, 0xf
+ li t0, '0'
+ blt a0, 10, 1f
+ li t0, 'a'
+ addiu a0, a0, -10
+1: addu a0, a0, t0
+ b _mips_cps_putc
+ END(_mips_cps_putx4)
+
+/**
+ * _mips_cps_putx8 - write an 8b hex value to the UART
+ * @a0: the 8b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx8, 0, ra)
+ move s3, ra
+ move s2, a0
+ srl a0, a0, 4
+ jal _mips_cps_putx4
+ move a0, s2
+ move ra, s3
+ b _mips_cps_putx4
+ END(_mips_cps_putx8)
+
+/**
+ * _mips_cps_putx16 - write a 16b hex value to the UART
+ * @a0: the 16b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx16, 0, ra)
+ move s5, ra
+ move s4, a0
+ srl a0, a0, 8
+ jal _mips_cps_putx8
+ move a0, s4
+ move ra, s5
+ b _mips_cps_putx8
+ END(_mips_cps_putx16)
+
+/**
+ * _mips_cps_putx32 - write a 32b hex value to the UART
+ * @a0: the 32b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx32, 0, ra)
+ move s7, ra
+ move s6, a0
+ srl a0, a0, 16
+ jal _mips_cps_putx16
+ move a0, s6
+ move ra, s7
+ b _mips_cps_putx16
+ END(_mips_cps_putx32)
+
+#ifdef CONFIG_64BIT
+
+/**
+ * _mips_cps_putx64 - write a 64b hex value to the UART
+ * @a0: the 64b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx64, 0, ra)
+ move sp, ra
+ move s8, a0
+ dsrl32 a0, a0, 0
+ jal _mips_cps_putx32
+ move a0, s8
+ move ra, sp
+ b _mips_cps_putx32
+ END(_mips_cps_putx64)
+
+#define _mips_cps_putxlong _mips_cps_putx64
+
+#else /* !CONFIG_64BIT */
+
+#define _mips_cps_putxlong _mips_cps_putx32
+
+#endif /* !CONFIG_64BIT */
+
+/**
+ * mips_cps_bev_dump() - dump relevant exception state to UART
+ * @a0: pointer to NULL-terminated ASCII string naming the exception
+ *
+ * Write information that may be useful in debugging an exception to the
+ * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
+ * will only be run if something goes horribly wrong very early during
+ * the bringup of a core and it is very likely to be unsafe to perform
+ * memory accesses at that point (cache state indeterminate, EVA may not
+ * be configured, coherence may be disabled) let alone have a stack,
+ * this is all written in assembly using only registers & unmapped
+ * uncached access to the UART registers.
+ */
+LEAF(mips_cps_bev_dump)
+ move s0, ra
+ move s1, a0
+
+ li t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
+
+ PTR_LA a0, str_newline
+ jal _mips_cps_puts
+ PTR_LA a0, str_bev
+ jal _mips_cps_puts
+ move a0, s1
+ jal _mips_cps_puts
+ PTR_LA a0, str_newline
+ jal _mips_cps_puts
+ PTR_LA a0, str_newline
+ jal _mips_cps_puts
+
+#define DUMP_COP0_REG(reg, name, sz, _mfc0) \
+ PTR_LA a0, 8f; \
+ jal _mips_cps_puts; \
+ _mfc0 a0, reg; \
+ jal _mips_cps_putx##sz; \
+ PTR_LA a0, str_newline; \
+ jal _mips_cps_puts; \
+ TEXT(name)
+
+ DUMP_COP0_REG(CP0_CAUSE, "Cause: 0x", 32, mfc0)
+ DUMP_COP0_REG(CP0_STATUS, "Status: 0x", 32, mfc0)
+ DUMP_COP0_REG(CP0_EBASE, "EBase: 0x", long, MFC0)
+ DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
+ DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
+
+ PTR_LA a0, str_newline
+ jal _mips_cps_puts
+ jr s0
+ END(mips_cps_bev_dump)
+
+.pushsection .data
+str_bev: .asciiz "BEV Exception: "
+str_newline: .asciiz "\r\n"
+.popsection
diff --git a/kernel/arch/mips/kernel/cps-vec.S b/kernel/arch/mips/kernel/cps-vec.S
index 55b759a00..ac81edd44 100644
--- a/kernel/arch/mips/kernel/cps-vec.S
+++ b/kernel/arch/mips/kernel/cps-vec.S
@@ -25,20 +25,39 @@
.set noreorder
+#ifdef CONFIG_64BIT
+# define STATUS_BITDEPS ST0_KX
+#else
+# define STATUS_BITDEPS 0
+#endif
+
+#ifdef CONFIG_MIPS_CPS_NS16550
+
+#define DUMP_EXCEP(name) \
+ PTR_LA a0, 8f; \
+ jal mips_cps_bev_dump; \
+ nop; \
+ TEXT(name)
+
+#else /* !CONFIG_MIPS_CPS_NS16550 */
+
+#define DUMP_EXCEP(name)
+
+#endif /* !CONFIG_MIPS_CPS_NS16550 */
+
/*
* Set dest to non-zero if the core supports the MT ASE, else zero. If
* MT is not supported then branch to nomt.
*/
.macro has_mt dest, nomt
- mfc0 \dest, CP0_CONFIG
- bgez \dest, \nomt
- mfc0 \dest, CP0_CONFIG, 1
+ mfc0 \dest, CP0_CONFIG, 1
bgez \dest, \nomt
mfc0 \dest, CP0_CONFIG, 2
bgez \dest, \nomt
mfc0 \dest, CP0_CONFIG, 3
andi \dest, \dest, MIPS_CONF3_MT
beqz \dest, \nomt
+ nop
.endm
.section .text.cps-vec
@@ -46,11 +65,9 @@
LEAF(mips_cps_core_entry)
/*
- * These first 12 bytes will be patched by cps_smp_setup to load the
- * base address of the CM GCRs into register v1 and the CCA to use into
- * register s0.
+ * These first 4 bytes will be patched by cps_smp_setup to load the
+ * CCA to use into register s0.
*/
- .quad 0
.word 0
/* Check whether we're here due to an NMI */
@@ -60,7 +77,7 @@ LEAF(mips_cps_core_entry)
nop
/* This is an NMI */
- la k0, nmi_handler
+ PTR_LA k0, nmi_handler
jr k0
nop
@@ -70,7 +87,7 @@ not_nmi:
mtc0 t0, CP0_CAUSE
/* Setup Status */
- li t0, ST0_CU1 | ST0_CU0
+ li t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
mtc0 t0, CP0_STATUS
/*
@@ -107,10 +124,10 @@ not_nmi:
mul t1, t1, t0
mul t1, t1, t2
- li a0, KSEG0
- add a1, a0, t1
+ li a0, CKSEG0
+ PTR_ADD a1, a0, t1
1: cache Index_Store_Tag_I, 0(a0)
- add a0, a0, t0
+ PTR_ADD a0, a0, t0
bne a0, a1, 1b
nop
icache_done:
@@ -134,12 +151,12 @@ icache_done:
mul t1, t1, t0
mul t1, t1, t2
- li a0, KSEG0
- addu a1, a0, t1
- subu a1, a1, t0
+ li a0, CKSEG0
+ PTR_ADDU a1, a0, t1
+ PTR_SUBU a1, a1, t0
1: cache Index_Store_Tag_D, 0(a0)
bne a0, a1, 1b
- add a0, a0, t0
+ PTR_ADD a0, a0, t0
dcache_done:
/* Set Kseg0 CCA to that in s0 */
@@ -150,13 +167,19 @@ dcache_done:
mtc0 t0, CP0_CONFIG
ehb
+ /* Calculate an uncached address for the CM GCRs */
+ MFC0 v1, CP0_CMGCRBASE
+ PTR_SLL v1, v1, 4
+ PTR_LI t0, UNCAC_BASE
+ PTR_ADDU v1, v1, t0
+
/* Enter the coherent domain */
li t0, 0xff
sw t0, GCR_CL_COHERENCE_OFS(v1)
ehb
/* Jump to kseg0 */
- la t0, 1f
+ PTR_LA t0, 1f
jr t0
nop
@@ -178,58 +201,62 @@ dcache_done:
nop
/* Off we go! */
- lw t1, VPEBOOTCFG_PC(v0)
- lw gp, VPEBOOTCFG_GP(v0)
- lw sp, VPEBOOTCFG_SP(v0)
+ PTR_L t1, VPEBOOTCFG_PC(v0)
+ PTR_L gp, VPEBOOTCFG_GP(v0)
+ PTR_L sp, VPEBOOTCFG_SP(v0)
jr t1
nop
END(mips_cps_core_entry)
.org 0x200
LEAF(excep_tlbfill)
+ DUMP_EXCEP("TLB Fill")
b .
nop
END(excep_tlbfill)
.org 0x280
LEAF(excep_xtlbfill)
+ DUMP_EXCEP("XTLB Fill")
b .
nop
END(excep_xtlbfill)
.org 0x300
LEAF(excep_cache)
+ DUMP_EXCEP("Cache")
b .
nop
END(excep_cache)
.org 0x380
LEAF(excep_genex)
+ DUMP_EXCEP("General")
b .
nop
END(excep_genex)
.org 0x400
LEAF(excep_intex)
+ DUMP_EXCEP("Interrupt")
b .
nop
END(excep_intex)
.org 0x480
LEAF(excep_ejtag)
- la k0, ejtag_debug_handler
+ DUMP_EXCEP("EJTAG")
+ PTR_LA k0, ejtag_debug_handler
jr k0
nop
END(excep_ejtag)
LEAF(mips_cps_core_init)
-#ifdef CONFIG_MIPS_MT
+#ifdef CONFIG_MIPS_MT_SMP
/* Check that the core implements the MT ASE */
has_mt t0, 3f
- nop
.set push
- .set mips32r2
.set mt
/* Only allow 1 TC per VPE to execute... */
@@ -237,7 +264,7 @@ LEAF(mips_cps_core_init)
/* ...and for the moment only 1 VPE */
dvpe
- la t1, 1f
+ PTR_LA t1, 1f
jr.hb t1
nop
@@ -250,25 +277,25 @@ LEAF(mips_cps_core_init)
mfc0 t0, CP0_MVPCONF0
srl t0, t0, MVPCONF0_PVPE_SHIFT
andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
- addiu t7, t0, 1
+ addiu ta3, t0, 1
/* If there's only 1, we're done */
beqz t0, 2f
nop
/* Loop through each VPE within this core */
- li t5, 1
+ li ta1, 1
1: /* Operate on the appropriate TC */
- mtc0 t5, CP0_VPECONTROL
+ mtc0 ta1, CP0_VPECONTROL
ehb
/* Bind TC to VPE (1:1 TC:VPE mapping) */
- mttc0 t5, CP0_TCBIND
+ mttc0 ta1, CP0_TCBIND
/* Set exclusive TC, non-active, master */
li t0, VPECONF0_MVP
- sll t1, t5, VPECONF0_XTC_SHIFT
+ sll t1, ta1, VPECONF0_XTC_SHIFT
or t0, t0, t1
mttc0 t0, CP0_VPECONF0
@@ -280,8 +307,8 @@ LEAF(mips_cps_core_init)
mttc0 t0, CP0_TCHALT
/* Next VPE */
- addiu t5, t5, 1
- slt t0, t5, t7
+ addiu ta1, ta1, 1
+ slt t0, ta1, ta3
bnez t0, 1b
nop
@@ -298,20 +325,21 @@ LEAF(mips_cps_core_init)
LEAF(mips_cps_boot_vpes)
/* Retrieve CM base address */
- la t0, mips_cm_base
- lw t0, 0(t0)
+ PTR_LA t0, mips_cm_base
+ PTR_L t0, 0(t0)
/* Calculate a pointer to this cores struct core_boot_config */
lw t0, GCR_CL_ID_OFS(t0)
li t1, COREBOOTCFG_SIZE
mul t0, t0, t1
- la t1, mips_cps_core_bootcfg
- lw t1, 0(t1)
- addu t0, t0, t1
+ PTR_LA t1, mips_cps_core_bootcfg
+ PTR_L t1, 0(t1)
+ PTR_ADDU t0, t0, t1
/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
- has_mt t6, 1f
- li t9, 0
+ li t9, 0
+#ifdef CONFIG_MIPS_MT_SMP
+ has_mt ta2, 1f
/* Find the number of VPEs present in the core */
mfc0 t1, CP0_MVPCONF0
@@ -330,28 +358,28 @@ LEAF(mips_cps_boot_vpes)
/* Retrieve the VPE ID from EBase.CPUNum */
mfc0 t9, $15, 1
and t9, t9, t1
+#endif
1: /* Calculate a pointer to this VPEs struct vpe_boot_config */
li t1, VPEBOOTCFG_SIZE
mul v0, t9, t1
- lw t7, COREBOOTCFG_VPECONFIG(t0)
- addu v0, v0, t7
+ PTR_L ta3, COREBOOTCFG_VPECONFIG(t0)
+ PTR_ADDU v0, v0, ta3
-#ifdef CONFIG_MIPS_MT
+#ifdef CONFIG_MIPS_MT_SMP
/* If the core doesn't support MT then return */
- bnez t6, 1f
+ bnez ta2, 1f
nop
jr ra
nop
.set push
- .set mips32r2
.set mt
1: /* Enter VPE configuration state */
dvpe
- la t1, 1f
+ PTR_LA t1, 1f
jr.hb t1
nop
1: mfc0 t1, CP0_MVPCONTROL
@@ -360,12 +388,12 @@ LEAF(mips_cps_boot_vpes)
ehb
/* Loop through each VPE */
- lw t6, COREBOOTCFG_VPEMASK(t0)
- move t8, t6
- li t5, 0
+ PTR_L ta2, COREBOOTCFG_VPEMASK(t0)
+ move t8, ta2
+ li ta1, 0
/* Check whether the VPE should be running. If not, skip it */
-1: andi t0, t6, 1
+1: andi t0, ta2, 1
beqz t0, 2f
nop
@@ -373,7 +401,7 @@ LEAF(mips_cps_boot_vpes)
mfc0 t0, CP0_VPECONTROL
ori t0, t0, VPECONTROL_TARGTC
xori t0, t0, VPECONTROL_TARGTC
- or t0, t0, t5
+ or t0, t0, ta1
mtc0 t0, CP0_VPECONTROL
ehb
@@ -384,8 +412,8 @@ LEAF(mips_cps_boot_vpes)
/* Calculate a pointer to the VPEs struct vpe_boot_config */
li t0, VPEBOOTCFG_SIZE
- mul t0, t0, t5
- addu t0, t0, t7
+ mul t0, t0, ta1
+ addu t0, t0, ta3
/* Set the TC restart PC */
lw t1, VPEBOOTCFG_PC(t0)
@@ -423,9 +451,9 @@ LEAF(mips_cps_boot_vpes)
mttc0 t0, CP0_VPECONF0
/* Next VPE */
-2: srl t6, t6, 1
- addiu t5, t5, 1
- bnez t6, 1b
+2: srl ta2, ta2, 1
+ addiu ta1, ta1, 1
+ bnez ta2, 1b
nop
/* Leave VPE configuration state */
@@ -445,13 +473,13 @@ LEAF(mips_cps_boot_vpes)
/* This VPE should be offline, halt the TC */
li t0, TCHALT_H
mtc0 t0, CP0_TCHALT
- la t0, 1f
+ PTR_LA t0, 1f
1: jr.hb t0
nop
2: .set pop
-#endif /* CONFIG_MIPS_MT */
+#endif /* CONFIG_MIPS_MT_SMP */
/* Return */
jr ra
@@ -466,10 +494,10 @@ LEAF(mips_cps_boot_vpes)
.set noat
lw $1, TI_CPU(gp)
sll $1, $1, LONGLOG
- la \dest, __per_cpu_offset
+ PTR_LA \dest, __per_cpu_offset
addu $1, $1, \dest
lw $1, 0($1)
- la \dest, cps_cpu_state
+ PTR_LA \dest, cps_cpu_state
addu \dest, \dest, $1
.set pop
.endm
diff --git a/kernel/arch/mips/kernel/cpu-probe.c b/kernel/arch/mips/kernel/cpu-probe.c
index 209e5b76c..6b9064499 100644
--- a/kernel/arch/mips/kernel/cpu-probe.c
+++ b/kernel/arch/mips/kernel/cpu-probe.c
@@ -32,6 +32,9 @@
#include <asm/spram.h>
#include <asm/uaccess.h>
+/* Hardware capabilities */
+unsigned int elf_hwcap __read_mostly;
+
/*
* Get the FPU Implementation/Revision.
*/
@@ -188,7 +191,7 @@ __setup("nohtw", htw_disable);
static int mips_ftlb_disabled;
static int mips_has_ftlb_configured;
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable);
static int __init ftlb_disable(char *s)
{
@@ -202,7 +205,10 @@ static int __init ftlb_disable(char *s)
return 1;
/* Disable it in the boot cpu */
- set_ftlb_enable(&cpu_data[0], 0);
+ if (set_ftlb_enable(&cpu_data[0], 0)) {
+ pr_warn("Can't turn FTLB off\n");
+ return 1;
+ }
back_to_back_c0_hazard();
@@ -364,45 +370,58 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
return 3;
}
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
{
- unsigned int config6;
+ unsigned int config;
/* It's implementation dependent how the FTLB can be enabled */
switch (c->cputype) {
case CPU_PROAPTIV:
case CPU_P5600:
/* proAptiv & related cores use Config6 to enable the FTLB */
- config6 = read_c0_config6();
+ config = read_c0_config6();
/* Clear the old probability value */
- config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
+ config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
if (enable)
/* Enable FTLB */
- write_c0_config6(config6 |
+ write_c0_config6(config |
(calculate_ftlb_probability(c)
<< MIPS_CONF6_FTLBP_SHIFT)
| MIPS_CONF6_FTLBEN);
else
/* Disable FTLB */
- write_c0_config6(config6 & ~MIPS_CONF6_FTLBEN);
- back_to_back_c0_hazard();
+ write_c0_config6(config & ~MIPS_CONF6_FTLBEN);
+ break;
+ case CPU_I6400:
+ /* I6400 & related cores use Config7 to configure FTLB */
+ config = read_c0_config7();
+ /* Clear the old probability value */
+ config &= ~(3 << MIPS_CONF7_FTLBP_SHIFT);
+ write_c0_config7(config | (calculate_ftlb_probability(c)
+ << MIPS_CONF7_FTLBP_SHIFT));
break;
+ default:
+ return 1;
}
+
+ return 0;
}
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
{
unsigned int config0;
- int isa;
+ int isa, mt;
config0 = read_c0_config();
/*
* Look for Standard TLB or Dual VTLB and FTLB
*/
- if ((((config0 & MIPS_CONF_MT) >> 7) == 1) ||
- (((config0 & MIPS_CONF_MT) >> 7) == 4))
+ mt = config0 & MIPS_CONF_MT;
+ if (mt == MIPS_CONF_MT_TLB)
c->options |= MIPS_CPU_TLB;
+ else if (mt == MIPS_CONF_MT_FTLB)
+ c->options |= MIPS_CPU_TLB | MIPS_CPU_FTLB;
isa = (config0 & MIPS_CONF_AT) >> 13;
switch (isa) {
@@ -517,13 +536,14 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_SEGMENTS;
if (config3 & MIPS_CONF3_MSA)
c->ases |= MIPS_ASE_MSA;
- /* Only tested on 32-bit cores */
- if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
+ if (config3 & MIPS_CONF3_PW) {
c->htw_seq = 0;
c->options |= MIPS_CPU_HTW;
}
if (config3 & MIPS_CONF3_CDMM)
c->options |= MIPS_CPU_CDMM;
+ if (config3 & MIPS_CONF3_SP)
+ c->options |= MIPS_CPU_SP;
return config3 & MIPS_CONF_M;
}
@@ -540,7 +560,19 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
if (cpu_has_tlb) {
if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
c->options |= MIPS_CPU_TLBINV;
- mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+
+ /*
+ * R6 has dropped the MMUExtDef field from config4.
+ * On R6 the fields always describe the FTLB, and only if it is
+ * present according to Config.MT.
+ */
+ if (!cpu_has_mips_r6)
+ mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+ else if (cpu_has_ftlb)
+ mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
+ else
+ mmuextdef = 0;
+
switch (mmuextdef) {
case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
@@ -945,7 +977,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
- MIPS_CPU_LLSC;
+ MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
c->tlbsize = 64;
break;
case PRID_IMP_R14000:
@@ -960,7 +992,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
- MIPS_CPU_LLSC;
+ MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
c->tlbsize = 64;
break;
case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */
@@ -1121,6 +1153,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
c->cputype = CPU_P5600;
__cpu_name[cpu] = "MIPS P5600";
break;
+ case PRID_IMP_I6400:
+ c->cputype = CPU_I6400;
+ __cpu_name[cpu] = "MIPS I6400";
+ break;
case PRID_IMP_M5150:
c->cputype = CPU_M5150;
__cpu_name[cpu] = "MIPS M5150";
@@ -1443,7 +1479,9 @@ void cpu_probe(void)
case PRID_COMP_CAVIUM:
cpu_probe_cavium(c, cpu);
break;
- case PRID_COMP_INGENIC:
+ case PRID_COMP_INGENIC_D0:
+ case PRID_COMP_INGENIC_D1:
+ case PRID_COMP_INGENIC_E1:
cpu_probe_ingenic(c, cpu);
break;
case PRID_COMP_NETLOGIC:
@@ -1478,6 +1516,10 @@ void cpu_probe(void)
else
cpu_set_nofpu_opts(c);
+ if (cpu_has_bp_ghist)
+ write_c0_r10k_diag(read_c0_r10k_diag() |
+ R10K_DIAG_E_GHIST);
+
if (cpu_has_mips_r2_r6) {
c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
/* R2 has Performance Counter Interrupt indicator */
@@ -1486,10 +1528,14 @@ void cpu_probe(void)
else
c->srsets = 1;
+ if (cpu_has_mips_r6)
+ elf_hwcap |= HWCAP_MIPS_R6;
+
if (cpu_has_msa) {
c->msa_id = cpu_get_msa_id();
WARN(c->msa_id & MSA_IR_WRPF,
"Vector register partitioning unimplemented!");
+ elf_hwcap |= HWCAP_MIPS_MSA;
}
cpu_probe_vmbits(c);
diff --git a/kernel/arch/mips/kernel/csrc-r4k.c b/kernel/arch/mips/kernel/csrc-r4k.c
index e5ed7ada1..1f910563f 100644
--- a/kernel/arch/mips/kernel/csrc-r4k.c
+++ b/kernel/arch/mips/kernel/csrc-r4k.c
@@ -28,6 +28,43 @@ static u64 notrace r4k_read_sched_clock(void)
return read_c0_count();
}
+static inline unsigned int rdhwr_count(void)
+{
+ unsigned int count;
+
+ __asm__ __volatile__(
+ " .set push\n"
+ " .set mips32r2\n"
+ " rdhwr %0, $2\n"
+ " .set pop\n"
+ : "=r" (count));
+
+ return count;
+}
+
+static bool rdhwr_count_usable(void)
+{
+ unsigned int prev, curr, i;
+
+ /*
+ * Older QEMUs have a broken implementation of RDHWR for the CP0 count
+ * which always returns a constant value. Try to identify this and don't
+ * use it in the VDSO if it is broken. This workaround can be removed
+ * once the fix has been in QEMU stable for a reasonable amount of time.
+ */
+ for (i = 0, prev = rdhwr_count(); i < 100; i++) {
+ curr = rdhwr_count();
+
+ if (curr != prev)
+ return true;
+
+ prev = curr;
+ }
+
+ pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n");
+ return false;
+}
+
int __init init_r4k_clocksource(void)
{
if (!cpu_has_counter || !mips_hpt_frequency)
@@ -36,6 +73,13 @@ int __init init_r4k_clocksource(void)
/* Calculate a somewhat reasonable rating value */
clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
+ /*
+ * R2 onwards makes the count accessible to user mode so it can be used
+ * by the VDSO (HWREna is configured by configure_hwrena()).
+ */
+ if (cpu_has_mips_r2_r6 && rdhwr_count_usable())
+ clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K;
+
clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
diff --git a/kernel/arch/mips/kernel/genex.S b/kernel/arch/mips/kernel/genex.S
index af42e7003..baa7b6fc0 100644
--- a/kernel/arch/mips/kernel/genex.S
+++ b/kernel/arch/mips/kernel/genex.S
@@ -407,7 +407,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set noat
SAVE_ALL
FEXPORT(handle_\exception\ext)
- __BUILD_clear_\clear
+ __build_clear_\clear
.set at
__BUILD_\verbose \exception
move a0, sp
diff --git a/kernel/arch/mips/kernel/head.S b/kernel/arch/mips/kernel/head.S
index 95afd663c..4e4cc5b9a 100644
--- a/kernel/arch/mips/kernel/head.S
+++ b/kernel/arch/mips/kernel/head.S
@@ -94,6 +94,22 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
jr t0
0:
+#ifdef CONFIG_MIPS_RAW_APPENDED_DTB
+ PTR_LA t0, __appended_dtb
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ li t1, 0xd00dfeed
+#else
+ li t1, 0xedfe0dd0
+#endif
+ lw t2, (t0)
+ bne t1, t2, not_found
+ nop
+
+ move a1, t0
+ PTR_LI a0, -2
+not_found:
+#endif
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
PTR_LA t1, __bss_stop - LONGSIZE
diff --git a/kernel/arch/mips/kernel/i8259.c b/kernel/arch/mips/kernel/i8259.c
deleted file mode 100644
index a74ec3ae5..000000000
--- a/kernel/arch/mips/kernel/i8259.c
+++ /dev/null
@@ -1,345 +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.
- *
- * Code to handle x86 style IRQs plus some generic interrupt stuff.
- *
- * Copyright (C) 1992 Linus Torvalds
- * Copyright (C) 1994 - 2000 Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-#include <linux/irq.h>
-
-#include <asm/i8259.h>
-#include <asm/io.h>
-
-/*
- * This is the 'legacy' 8259A Programmable Interrupt Controller,
- * present in the majority of PC/AT boxes.
- * plus some generic x86 specific things if generic specifics makes
- * any sense at all.
- * this file should become arch/i386/kernel/irq.c when the old irq.c
- * moves to arch independent land
- */
-
-static int i8259A_auto_eoi = -1;
-DEFINE_RAW_SPINLOCK(i8259A_lock);
-static void disable_8259A_irq(struct irq_data *d);
-static void enable_8259A_irq(struct irq_data *d);
-static void mask_and_ack_8259A(struct irq_data *d);
-static void init_8259A(int auto_eoi);
-
-static struct irq_chip i8259A_chip = {
- .name = "XT-PIC",
- .irq_mask = disable_8259A_irq,
- .irq_disable = disable_8259A_irq,
- .irq_unmask = enable_8259A_irq,
- .irq_mask_ack = mask_and_ack_8259A,
-};
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define cached_master_mask (cached_irq_mask)
-#define cached_slave_mask (cached_irq_mask >> 8)
-
-static void disable_8259A_irq(struct irq_data *d)
-{
- unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
- unsigned long flags;
-
- mask = 1 << irq;
- raw_spin_lock_irqsave(&i8259A_lock, flags);
- cached_irq_mask |= mask;
- if (irq & 8)
- outb(cached_slave_mask, PIC_SLAVE_IMR);
- else
- outb(cached_master_mask, PIC_MASTER_IMR);
- raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-}
-
-static void enable_8259A_irq(struct irq_data *d)
-{
- unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
- unsigned long flags;
-
- mask = ~(1 << irq);
- raw_spin_lock_irqsave(&i8259A_lock, flags);
- cached_irq_mask &= mask;
- if (irq & 8)
- outb(cached_slave_mask, PIC_SLAVE_IMR);
- else
- outb(cached_master_mask, PIC_MASTER_IMR);
- raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-}
-
-int i8259A_irq_pending(unsigned int irq)
-{
- unsigned int mask;
- unsigned long flags;
- int ret;
-
- irq -= I8259A_IRQ_BASE;
- mask = 1 << irq;
- raw_spin_lock_irqsave(&i8259A_lock, flags);
- if (irq < 8)
- ret = inb(PIC_MASTER_CMD) & mask;
- else
- ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
- raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-
- return ret;
-}
-
-void make_8259A_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
- enable_irq(irq);
-}
-
-/*
- * This function assumes to be called rarely. Switching between
- * 8259A registers is slow.
- * This has to be protected by the irq controller spinlock
- * before being called.
- */
-static inline int i8259A_irq_real(unsigned int irq)
-{
- int value;
- int irqmask = 1 << irq;
-
- if (irq < 8) {
- outb(0x0B, PIC_MASTER_CMD); /* ISR register */
- value = inb(PIC_MASTER_CMD) & irqmask;
- outb(0x0A, PIC_MASTER_CMD); /* back to the IRR register */
- return value;
- }
- outb(0x0B, PIC_SLAVE_CMD); /* ISR register */
- value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
- outb(0x0A, PIC_SLAVE_CMD); /* back to the IRR register */
- return value;
-}
-
-/*
- * Careful! The 8259A is a fragile beast, it pretty
- * much _has_ to be done exactly like this (mask it
- * first, _then_ send the EOI, and the order of EOI
- * to the two 8259s is important!
- */
-static void mask_and_ack_8259A(struct irq_data *d)
-{
- unsigned int irqmask, irq = d->irq - I8259A_IRQ_BASE;
- unsigned long flags;
-
- irqmask = 1 << irq;
- raw_spin_lock_irqsave(&i8259A_lock, flags);
- /*
- * Lightweight spurious IRQ detection. We do not want
- * to overdo spurious IRQ handling - it's usually a sign
- * of hardware problems, so we only do the checks we can
- * do without slowing down good hardware unnecessarily.
- *
- * Note that IRQ7 and IRQ15 (the two spurious IRQs
- * usually resulting from the 8259A-1|2 PICs) occur
- * even if the IRQ is masked in the 8259A. Thus we
- * can check spurious 8259A IRQs without doing the
- * quite slow i8259A_irq_real() call for every IRQ.
- * This does not cover 100% of spurious interrupts,
- * but should be enough to warn the user that there
- * is something bad going on ...
- */
- if (cached_irq_mask & irqmask)
- goto spurious_8259A_irq;
- cached_irq_mask |= irqmask;
-
-handle_real_irq:
- if (irq & 8) {
- inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */
- outb(cached_slave_mask, PIC_SLAVE_IMR);
- outb(0x60+(irq&7), PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
- outb(0x60+PIC_CASCADE_IR, PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
- } else {
- inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */
- outb(cached_master_mask, PIC_MASTER_IMR);
- outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
- }
- raw_spin_unlock_irqrestore(&i8259A_lock, flags);
- return;
-
-spurious_8259A_irq:
- /*
- * this is the slow path - should happen rarely.
- */
- if (i8259A_irq_real(irq))
- /*
- * oops, the IRQ _is_ in service according to the
- * 8259A - not spurious, go handle it.
- */
- goto handle_real_irq;
-
- {
- static int spurious_irq_mask;
- /*
- * At this point we can be sure the IRQ is spurious,
- * lets ACK and report it. [once per IRQ]
- */
- if (!(spurious_irq_mask & irqmask)) {
- printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
- spurious_irq_mask |= irqmask;
- }
- atomic_inc(&irq_err_count);
- /*
- * Theoretically we do not have to handle this IRQ,
- * but in Linux this does not cause problems and is
- * simpler for us.
- */
- goto handle_real_irq;
- }
-}
-
-static void i8259A_resume(void)
-{
- if (i8259A_auto_eoi >= 0)
- init_8259A(i8259A_auto_eoi);
-}
-
-static void i8259A_shutdown(void)
-{
- /* Put the i8259A into a quiescent state that
- * the kernel initialization code can get it
- * out of.
- */
- if (i8259A_auto_eoi >= 0) {
- outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
- outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
- }
-}
-
-static struct syscore_ops i8259_syscore_ops = {
- .resume = i8259A_resume,
- .shutdown = i8259A_shutdown,
-};
-
-static int __init i8259A_init_sysfs(void)
-{
- register_syscore_ops(&i8259_syscore_ops);
- return 0;
-}
-
-device_initcall(i8259A_init_sysfs);
-
-static void init_8259A(int auto_eoi)
-{
- unsigned long flags;
-
- i8259A_auto_eoi = auto_eoi;
-
- raw_spin_lock_irqsave(&i8259A_lock, flags);
-
- outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
- outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
-
- /*
- * outb_p - this has to work on a wide range of PC hardware.
- */
- outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
- outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */
- outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */
- if (auto_eoi) /* master does Auto EOI */
- outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
- else /* master expects normal EOI */
- outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
-
- outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
- outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */
- outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */
- outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
- if (auto_eoi)
- /*
- * In AEOI mode we just have to mask the interrupt
- * when acking.
- */
- i8259A_chip.irq_mask_ack = disable_8259A_irq;
- else
- i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
-
- udelay(100); /* wait for 8259A to initialize */
-
- outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
- outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
-
- raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-}
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
- .handler = no_action,
- .name = "cascade",
- .flags = IRQF_NO_THREAD,
-};
-
-static struct resource pic1_io_resource = {
- .name = "pic1",
- .start = PIC_MASTER_CMD,
- .end = PIC_MASTER_IMR,
- .flags = IORESOURCE_BUSY
-};
-
-static struct resource pic2_io_resource = {
- .name = "pic2",
- .start = PIC_SLAVE_CMD,
- .end = PIC_SLAVE_IMR,
- .flags = IORESOURCE_BUSY
-};
-
-static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- irq_set_chip_and_handler(virq, &i8259A_chip, handle_level_irq);
- irq_set_probe(virq);
- return 0;
-}
-
-static struct irq_domain_ops i8259A_ops = {
- .map = i8259A_irq_domain_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
-/*
- * On systems with i8259-style interrupt controllers we assume for
- * driver compatibility reasons interrupts 0 - 15 to be the i8259
- * interrupts even if the hardware uses a different interrupt numbering.
- */
-void __init init_i8259_irqs(void)
-{
- struct irq_domain *domain;
-
- insert_resource(&ioport_resource, &pic1_io_resource);
- insert_resource(&ioport_resource, &pic2_io_resource);
-
- init_8259A(0);
-
- domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0,
- &i8259A_ops, NULL);
- if (!domain)
- panic("Failed to add i8259 IRQ domain");
-
- setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
-}
diff --git a/kernel/arch/mips/kernel/idle.c b/kernel/arch/mips/kernel/idle.c
index e4f62b787..46794d64c 100644
--- a/kernel/arch/mips/kernel/idle.c
+++ b/kernel/arch/mips/kernel/idle.c
@@ -134,6 +134,16 @@ void __init check_wait(void)
return;
}
+ /*
+ * MIPSr6 specifies that masked interrupts should unblock an executing
+ * wait instruction, and thus that it is safe for us to use
+ * r4k_wait_irqoff. Yippee!
+ */
+ if (cpu_has_mips_r6) {
+ cpu_wait = r4k_wait_irqoff;
+ return;
+ }
+
switch (current_cpu_type()) {
case CPU_R3081:
case CPU_R3081E:
@@ -155,12 +165,12 @@ void __init check_wait(void)
case CPU_4KEC:
case CPU_4KSC:
case CPU_5KC:
+ case CPU_5KE:
case CPU_25KF:
case CPU_PR4450:
case CPU_BMIPS3300:
case CPU_BMIPS4350:
case CPU_BMIPS4380:
- case CPU_BMIPS5000:
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
@@ -171,7 +181,9 @@ void __init check_wait(void)
case CPU_XLP:
cpu_wait = r4k_wait;
break;
-
+ case CPU_BMIPS5000:
+ cpu_wait = r4k_wait_irqoff;
+ break;
case CPU_RM7000:
cpu_wait = rm7k_wait_irqoff;
break;
diff --git a/kernel/arch/mips/kernel/irq.c b/kernel/arch/mips/kernel/irq.c
index 3c8a18a00..8eb5af805 100644
--- a/kernel/arch/mips/kernel/irq.c
+++ b/kernel/arch/mips/kernel/irq.c
@@ -25,48 +25,6 @@
#include <linux/atomic.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_KGDB
-int kgdb_early_setup;
-#endif
-
-static DECLARE_BITMAP(irq_map, NR_IRQS);
-
-int allocate_irqno(void)
-{
- int irq;
-
-again:
- irq = find_first_zero_bit(irq_map, NR_IRQS);
-
- if (irq >= NR_IRQS)
- return -ENOSPC;
-
- if (test_and_set_bit(irq, irq_map))
- goto again;
-
- return irq;
-}
-
-/*
- * Allocate the 16 legacy interrupts for i8259 devices. This happens early
- * in the kernel initialization so treating allocation failure as BUG() is
- * ok.
- */
-void __init alloc_legacy_irqno(void)
-{
- int i;
-
- for (i = 0; i <= 16; i++)
- BUG_ON(test_and_set_bit(i, irq_map));
-}
-
-void free_irqno(unsigned int irq)
-{
- smp_mb__before_atomic();
- clear_bit(irq, irq_map);
- smp_mb__after_atomic();
-}
-
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -93,20 +51,10 @@ void __init init_IRQ(void)
{
int i;
-#ifdef CONFIG_KGDB
- if (kgdb_early_setup)
- return;
-#endif
-
for (i = 0; i < NR_IRQS; i++)
irq_set_noprobe(i);
arch_init_irq();
-
-#ifdef CONFIG_KGDB
- if (!kgdb_early_setup)
- kgdb_early_setup = 1;
-#endif
}
#ifdef CONFIG_DEBUG_STACKOVERFLOW
diff --git a/kernel/arch/mips/kernel/irq_cpu.c b/kernel/arch/mips/kernel/irq_cpu.c
deleted file mode 100644
index 6eb7a3f51..000000000
--- a/kernel/arch/mips/kernel/irq_cpu.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2001 Ralf Baechle
- * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
- * Author: Maciej W. Rozycki <macro@mips.com>
- *
- * This file define the irq handler for MIPS CPU interrupts.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-/*
- * Almost all MIPS CPUs define 8 interrupt sources. They are typically
- * level triggered (i.e., cannot be cleared from CPU; must be cleared from
- * device). The first two are software interrupts which we don't really
- * use or support. The last one is usually the CPU timer interrupt if
- * counter register is present or, for CPUs with an external FPU, by
- * convention it's the FPU exception interrupt.
- *
- * Don't even think about using this on SMP. You have been warned.
- *
- * This file exports one global function:
- * void mips_cpu_irq_init(void);
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsmtregs.h>
-#include <asm/setup.h>
-
-static inline void unmask_mips_irq(struct irq_data *d)
-{
- set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
- irq_enable_hazard();
-}
-
-static inline void mask_mips_irq(struct irq_data *d)
-{
- clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
- irq_disable_hazard();
-}
-
-static struct irq_chip mips_cpu_irq_controller = {
- .name = "MIPS",
- .irq_ack = mask_mips_irq,
- .irq_mask = mask_mips_irq,
- .irq_mask_ack = mask_mips_irq,
- .irq_unmask = unmask_mips_irq,
- .irq_eoi = unmask_mips_irq,
- .irq_disable = mask_mips_irq,
- .irq_enable = unmask_mips_irq,
-};
-
-/*
- * Basically the same as above but taking care of all the MT stuff
- */
-
-static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
-{
- unsigned int vpflags = dvpe();
-
- clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
- evpe(vpflags);
- unmask_mips_irq(d);
- return 0;
-}
-
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues. Same for mips_cpu_irq_end.
- */
-static void mips_mt_cpu_irq_ack(struct irq_data *d)
-{
- unsigned int vpflags = dvpe();
- clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
- evpe(vpflags);
- mask_mips_irq(d);
-}
-
-static struct irq_chip mips_mt_cpu_irq_controller = {
- .name = "MIPS",
- .irq_startup = mips_mt_cpu_irq_startup,
- .irq_ack = mips_mt_cpu_irq_ack,
- .irq_mask = mask_mips_irq,
- .irq_mask_ack = mips_mt_cpu_irq_ack,
- .irq_unmask = unmask_mips_irq,
- .irq_eoi = unmask_mips_irq,
- .irq_disable = mask_mips_irq,
- .irq_enable = unmask_mips_irq,
-};
-
-asmlinkage void __weak plat_irq_dispatch(void)
-{
- unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
- int irq;
-
- if (!pending) {
- spurious_interrupt();
- return;
- }
-
- pending >>= CAUSEB_IP;
- while (pending) {
- irq = fls(pending) - 1;
- do_IRQ(MIPS_CPU_IRQ_BASE + irq);
- pending &= ~BIT(irq);
- }
-}
-
-static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- static struct irq_chip *chip;
-
- if (hw < 2 && cpu_has_mipsmt) {
- /* Software interrupts are used for MT/CMT IPI */
- chip = &mips_mt_cpu_irq_controller;
- } else {
- chip = &mips_cpu_irq_controller;
- }
-
- if (cpu_has_vint)
- set_vi_handler(hw, plat_irq_dispatch);
-
- irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
-
- return 0;
-}
-
-static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
- .map = mips_cpu_intc_map,
- .xlate = irq_domain_xlate_onecell,
-};
-
-static void __init __mips_cpu_irq_init(struct device_node *of_node)
-{
- struct irq_domain *domain;
-
- /* Mask interrupts. */
- clear_c0_status(ST0_IM);
- clear_c0_cause(CAUSEF_IP);
-
- domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
- &mips_cpu_intc_irq_domain_ops, NULL);
- if (!domain)
- panic("Failed to add irqdomain for MIPS CPU");
-}
-
-void __init mips_cpu_irq_init(void)
-{
- __mips_cpu_irq_init(NULL);
-}
-
-int __init mips_cpu_irq_of_init(struct device_node *of_node,
- struct device_node *parent)
-{
- __mips_cpu_irq_init(of_node);
- return 0;
-}
diff --git a/kernel/arch/mips/kernel/jump_label.c b/kernel/arch/mips/kernel/jump_label.c
index dda800e9e..3e586daa3 100644
--- a/kernel/arch/mips/kernel/jump_label.c
+++ b/kernel/arch/mips/kernel/jump_label.c
@@ -51,7 +51,7 @@ void arch_jump_label_transform(struct jump_entry *e,
/* Target must have the right alignment and ISA must be preserved. */
BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
- if (type == JUMP_LABEL_ENABLE) {
+ if (type == JUMP_LABEL_JMP) {
insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
insn.j_format.target = e->target >> J_RANGE_SHIFT;
} else {
diff --git a/kernel/arch/mips/kernel/kgdb.c b/kernel/arch/mips/kernel/kgdb.c
index 7afcc2f22..de63d36af 100644
--- a/kernel/arch/mips/kernel/kgdb.c
+++ b/kernel/arch/mips/kernel/kgdb.c
@@ -378,10 +378,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
struct kgdb_arch arch_kgdb_ops;
-/*
- * We use kgdb_early_setup so that functions we need to call now don't
- * cause trouble when called again later.
- */
int kgdb_arch_init(void)
{
union mips_instruction insn = {
diff --git a/kernel/arch/mips/kernel/mips-cm.c b/kernel/arch/mips/kernel/mips-cm.c
index 85bbe9b96..1448c1f43 100644
--- a/kernel/arch/mips/kernel/mips-cm.c
+++ b/kernel/arch/mips/kernel/mips-cm.c
@@ -9,17 +9,142 @@
*/
#include <linux/errno.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
#include <asm/mips-cm.h>
#include <asm/mipsregs.h>
void __iomem *mips_cm_base;
void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
+
+static char *cm2_tr[8] = {
+ "mem", "gcr", "gic", "mmio",
+ "0x04", "cpc", "0x06", "0x07"
+};
+
+/* CM3 Tag ECC transation type */
+static char *cm3_tr[16] = {
+ [0x0] = "ReqNoData",
+ [0x1] = "0x1",
+ [0x2] = "ReqWData",
+ [0x3] = "0x3",
+ [0x4] = "IReqNoResp",
+ [0x5] = "IReqWResp",
+ [0x6] = "IReqNoRespDat",
+ [0x7] = "IReqWRespDat",
+ [0x8] = "RespNoData",
+ [0x9] = "RespDataFol",
+ [0xa] = "RespWData",
+ [0xb] = "RespDataOnly",
+ [0xc] = "IRespNoData",
+ [0xd] = "IRespDataFol",
+ [0xe] = "IRespWData",
+ [0xf] = "IRespDataOnly"
+};
+
+static char *cm2_cmd[32] = {
+ [0x00] = "0x00",
+ [0x01] = "Legacy Write",
+ [0x02] = "Legacy Read",
+ [0x03] = "0x03",
+ [0x04] = "0x04",
+ [0x05] = "0x05",
+ [0x06] = "0x06",
+ [0x07] = "0x07",
+ [0x08] = "Coherent Read Own",
+ [0x09] = "Coherent Read Share",
+ [0x0a] = "Coherent Read Discard",
+ [0x0b] = "Coherent Ready Share Always",
+ [0x0c] = "Coherent Upgrade",
+ [0x0d] = "Coherent Writeback",
+ [0x0e] = "0x0e",
+ [0x0f] = "0x0f",
+ [0x10] = "Coherent Copyback",
+ [0x11] = "Coherent Copyback Invalidate",
+ [0x12] = "Coherent Invalidate",
+ [0x13] = "Coherent Write Invalidate",
+ [0x14] = "Coherent Completion Sync",
+ [0x15] = "0x15",
+ [0x16] = "0x16",
+ [0x17] = "0x17",
+ [0x18] = "0x18",
+ [0x19] = "0x19",
+ [0x1a] = "0x1a",
+ [0x1b] = "0x1b",
+ [0x1c] = "0x1c",
+ [0x1d] = "0x1d",
+ [0x1e] = "0x1e",
+ [0x1f] = "0x1f"
+};
+
+/* CM3 Tag ECC command type */
+static char *cm3_cmd[16] = {
+ [0x0] = "Legacy Read",
+ [0x1] = "Legacy Write",
+ [0x2] = "Coherent Read Own",
+ [0x3] = "Coherent Read Share",
+ [0x4] = "Coherent Read Discard",
+ [0x5] = "Coherent Evicted",
+ [0x6] = "Coherent Upgrade",
+ [0x7] = "Coherent Upgrade for Store Conditional",
+ [0x8] = "Coherent Writeback",
+ [0x9] = "Coherent Write Invalidate",
+ [0xa] = "0xa",
+ [0xb] = "0xb",
+ [0xc] = "0xc",
+ [0xd] = "0xd",
+ [0xe] = "0xe",
+ [0xf] = "0xf"
+};
+
+/* CM3 Tag ECC command group */
+static char *cm3_cmd_group[8] = {
+ [0x0] = "Normal",
+ [0x1] = "Registers",
+ [0x2] = "TLB",
+ [0x3] = "0x3",
+ [0x4] = "L1I",
+ [0x5] = "L1D",
+ [0x6] = "L3",
+ [0x7] = "L2"
+};
+
+static char *cm2_core[8] = {
+ "Invalid/OK", "Invalid/Data",
+ "Shared/OK", "Shared/Data",
+ "Modified/OK", "Modified/Data",
+ "Exclusive/OK", "Exclusive/Data"
+};
+
+static char *cm2_causes[32] = {
+ "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
+ "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
+ "0x08", "0x09", "0x0a", "0x0b",
+ "0x0c", "0x0d", "0x0e", "0x0f",
+ "0x10", "0x11", "0x12", "0x13",
+ "0x14", "0x15", "0x16", "INTVN_WR_ERR",
+ "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
+ "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static char *cm3_causes[32] = {
+ "0x0", "MP_CORRECTABLE_ECC_ERR", "MP_REQUEST_DECODE_ERR",
+ "MP_UNCORRECTABLE_ECC_ERR", "MP_PARITY_ERR", "MP_COHERENCE_ERR",
+ "CMBIU_REQUEST_DECODE_ERR", "CMBIU_PARITY_ERR", "CMBIU_AXI_RESP_ERR",
+ "0x9", "RBI_BUS_ERR", "0xb", "0xc", "0xd", "0xe", "0xf", "0x10",
+ "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18",
+ "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock);
+static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags);
phys_addr_t __mips_cm_phys_base(void)
{
u32 config3 = read_c0_config3();
- u32 cmgcr;
+ unsigned long cmgcr;
/* Check the CMGCRBase register is implemented */
if (!(config3 & MIPS_CONF3_CMGCR))
@@ -80,6 +205,14 @@ int mips_cm_probe(void)
{
phys_addr_t addr;
u32 base_reg;
+ unsigned cpu;
+
+ /*
+ * No need to probe again if we have already been
+ * here before.
+ */
+ if (mips_cm_base)
+ return 0;
addr = mips_cm_phys_base();
BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
@@ -117,5 +250,179 @@ int mips_cm_probe(void)
/* probe for an L2-only sync region */
mips_cm_probe_l2sync();
+ /* determine register width for this CM */
+ mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+
+ for_each_possible_cpu(cpu)
+ spin_lock_init(&per_cpu(cm_core_lock, cpu));
+
return 0;
}
+
+void mips_cm_lock_other(unsigned int core, unsigned int vp)
+{
+ unsigned curr_core;
+ u32 val;
+
+ preempt_disable();
+ curr_core = current_cpu_data.core;
+ spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
+ per_cpu(cm_core_lock_flags, curr_core));
+
+ if (mips_cm_revision() >= CM_REV_CM3) {
+ val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
+ val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;
+ } else {
+ BUG_ON(vp != 0);
+ val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
+ }
+
+ write_gcr_cl_other(val);
+
+ /*
+ * Ensure the core-other region reflects the appropriate core &
+ * VP before any accesses to it occur.
+ */
+ mb();
+}
+
+void mips_cm_unlock_other(void)
+{
+ unsigned curr_core = current_cpu_data.core;
+
+ spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
+ per_cpu(cm_core_lock_flags, curr_core));
+ preempt_enable();
+}
+
+void mips_cm_error_report(void)
+{
+ u64 cm_error, cm_addr, cm_other;
+ unsigned long revision;
+ int ocause, cause;
+ char buf[256];
+
+ if (!mips_cm_present())
+ return;
+
+ revision = mips_cm_revision();
+
+ if (revision < CM_REV_CM3) { /* CM2 */
+ cm_error = read_gcr_error_cause();
+ cm_addr = read_gcr_error_addr();
+ cm_other = read_gcr_error_mult();
+ cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+ ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+ if (!cause)
+ return;
+
+ if (cause < 16) {
+ unsigned long cca_bits = (cm_error >> 15) & 7;
+ unsigned long tr_bits = (cm_error >> 12) & 7;
+ 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, cm2_tr[tr_bits],
+ cm2_cmd[cmd_bits], stag_bits, sport_bits);
+ } else {
+ /* glob state & sresp together */
+ unsigned long c3_bits = (cm_error >> 18) & 7;
+ unsigned long c2_bits = (cm_error >> 15) & 7;
+ 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 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 "
+ "MCmd=%s SPort=%lu\n",
+ cm2_core[c3_bits], cm2_core[c2_bits],
+ cm2_core[c1_bits], cm2_core[c0_bits],
+ sc_bit ? "True" : "False",
+ cm2_cmd[cmd_bits], sport_bits);
+ }
+ pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
+ cm2_causes[cause], buf);
+ pr_err("CM_ADDR =%08llx\n", cm_addr);
+ pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]);
+ } else { /* CM3 */
+ ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
+ ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
+
+ cm_error = read64_gcr_error_cause();
+ cm_addr = read64_gcr_error_addr();
+ cm_other = read64_gcr_error_mult();
+ cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+ ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+ if (!cause)
+ return;
+
+ /* Used by cause == {1,2,3} */
+ core_id_bits = (cm_error >> 22) & 0xf;
+ vp_id_bits = (cm_error >> 18) & 0xf;
+ cmd_bits = (cm_error >> 14) & 0xf;
+ cmd_group_bits = (cm_error >> 11) & 0xf;
+ cm3_cca_bits = (cm_error >> 8) & 7;
+ mcp_bits = (cm_error >> 5) & 0xf;
+ cm3_tr_bits = (cm_error >> 1) & 0xf;
+ sched_bit = cm_error & 0x1;
+
+ if (cause == 1 || cause == 3) { /* Tag ECC */
+ unsigned long tag_ecc = (cm_error >> 57) & 0x1;
+ unsigned long tag_way_bits = (cm_error >> 29) & 0xffff;
+ unsigned long dword_bits = (cm_error >> 49) & 0xff;
+ unsigned long data_way_bits = (cm_error >> 45) & 0xf;
+ unsigned long data_sets_bits = (cm_error >> 29) & 0xfff;
+ unsigned long bank_bit = (cm_error >> 28) & 0x1;
+ snprintf(buf, sizeof(buf),
+ "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)"
+ "Bank=%lu CoreID=%lu VPID=%lu Command=%s"
+ "Command Group=%s CCA=%lu MCP=%d"
+ "Transaction type=%s Scheduler=%lu\n",
+ tag_ecc ? "TAG" : "DATA",
+ tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 :
+ data_way_bits, bank_bit, dword_bits,
+ data_sets_bits,
+ core_id_bits, vp_id_bits,
+ cm3_cmd[cmd_bits],
+ cm3_cmd_group[cmd_group_bits],
+ cm3_cca_bits, 1 << mcp_bits,
+ cm3_tr[cm3_tr_bits], sched_bit);
+ } else if (cause == 2) {
+ unsigned long data_error_type = (cm_error >> 41) & 0xfff;
+ unsigned long data_decode_cmd = (cm_error >> 37) & 0xf;
+ unsigned long data_decode_group = (cm_error >> 34) & 0x7;
+ unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f;
+
+ snprintf(buf, sizeof(buf),
+ "Decode Request Error: Type=%lu, Command=%lu"
+ "Command Group=%lu Destination ID=%lu"
+ "CoreID=%lu VPID=%lu Command=%s"
+ "Command Group=%s CCA=%lu MCP=%d"
+ "Transaction type=%s Scheduler=%lu\n",
+ data_error_type, data_decode_cmd,
+ data_decode_group, data_decode_destination_id,
+ core_id_bits, vp_id_bits,
+ cm3_cmd[cmd_bits],
+ cm3_cmd_group[cmd_group_bits],
+ cm3_cca_bits, 1 << mcp_bits,
+ cm3_tr[cm3_tr_bits], sched_bit);
+ } else {
+ buf[0] = 0;
+ }
+
+ pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
+ cm3_causes[cause], buf);
+ pr_err("CM_ADDR =%llx\n", cm_addr);
+ pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]);
+ }
+
+ /* reprime cause register */
+ write_gcr_error_cause(0);
+}
diff --git a/kernel/arch/mips/kernel/mips-cpc.c b/kernel/arch/mips/kernel/mips-cpc.c
index 11964501c..566b8d2c0 100644
--- a/kernel/arch/mips/kernel/mips-cpc.c
+++ b/kernel/arch/mips/kernel/mips-cpc.c
@@ -21,9 +21,16 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock);
static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
-phys_addr_t __weak mips_cpc_phys_base(void)
+/**
+ * mips_cpc_phys_base - retrieve the physical base address of the CPC
+ *
+ * This function returns the physical base address of the Cluster Power
+ * Controller memory mapped registers, or 0 if no Cluster Power Controller
+ * is present.
+ */
+static phys_addr_t mips_cpc_phys_base(void)
{
- u32 cpc_base;
+ unsigned long cpc_base;
if (!mips_cm_present())
return 0;
@@ -69,6 +76,12 @@ void mips_cpc_lock_other(unsigned int core)
spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core),
per_cpu(cpc_core_lock_flags, curr_core));
write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF);
+
+ /*
+ * Ensure the core-other region reflects the appropriate core &
+ * VP before any accesses to it occur.
+ */
+ mb();
}
void mips_cpc_unlock_other(void)
diff --git a/kernel/arch/mips/kernel/mips-r2-to-r6-emul.c b/kernel/arch/mips/kernel/mips-r2-to-r6-emul.c
index f2977f009..1f5aac7f9 100644
--- a/kernel/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/kernel/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -22,6 +22,7 @@
#include <asm/asm.h>
#include <asm/branch.h>
#include <asm/break.h>
+#include <asm/debug.h>
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#include <asm/inst.h>
@@ -2363,7 +2364,6 @@ static const struct file_operations mipsr2_clear_fops = {
static int __init mipsr2_init_debugfs(void)
{
- extern struct dentry *mips_debugfs_dir;
struct dentry *mipsr2_emul;
if (!mips_debugfs_dir)
diff --git a/kernel/arch/mips/kernel/mips_ksyms.c b/kernel/arch/mips/kernel/mips_ksyms.c
index 291af0b5c..e2b6ab746 100644
--- a/kernel/arch/mips/kernel/mips_ksyms.c
+++ b/kernel/arch/mips/kernel/mips_ksyms.c
@@ -17,6 +17,7 @@
#include <asm/fpu.h>
#include <asm/msa.h>
+extern void *__bzero_kernel(void *__s, size_t __count);
extern void *__bzero(void *__s, size_t __count);
extern long __strncpy_from_kernel_nocheck_asm(char *__to,
const char *__from, long __len);
@@ -64,6 +65,7 @@ EXPORT_SYMBOL(__copy_from_user_eva);
EXPORT_SYMBOL(__copy_in_user_eva);
EXPORT_SYMBOL(__copy_to_user_eva);
EXPORT_SYMBOL(__copy_user_inatomic_eva);
+EXPORT_SYMBOL(__bzero_kernel);
#endif
EXPORT_SYMBOL(__bzero);
EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
diff --git a/kernel/arch/mips/kernel/octeon_switch.S b/kernel/arch/mips/kernel/octeon_switch.S
index 423ae83af..3375745b9 100644
--- a/kernel/arch/mips/kernel/octeon_switch.S
+++ b/kernel/arch/mips/kernel/octeon_switch.S
@@ -18,7 +18,7 @@
.set pop
/*
* task_struct *resume(task_struct *prev, task_struct *next,
- * struct thread_info *next_ti, int usedfpu)
+ * struct thread_info *next_ti)
*/
.align 7
LEAF(resume)
@@ -28,30 +28,6 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)
- /*
- * check if we need to save FPU registers
- */
- .set push
- .set noreorder
- beqz a3, 1f
- PTR_L t3, TASK_THREAD_INFO(a0)
- .set pop
-
- /*
- * clear saved user stack CU1 bit
- */
- LONG_L t0, ST_OFF(t3)
- li t1, ~ST0_CU1
- and t0, t0, t1
- LONG_S t0, ST_OFF(t3)
-
- .set push
- .set arch=mips64r2
- fpu_save_double a0 t0 t1 # c0_status passed in t0
- # clobbers t1
- .set pop
-1:
-
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
/* Check if we need to store CVMSEG state */
dmfc0 t0, $11,7 /* CvmMemCtl */
diff --git a/kernel/arch/mips/kernel/perf_event_mipsxx.c b/kernel/arch/mips/kernel/perf_event_mipsxx.c
index cc1b6fadf..d7b8dd431 100644
--- a/kernel/arch/mips/kernel/perf_event_mipsxx.c
+++ b/kernel/arch/mips/kernel/perf_event_mipsxx.c
@@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
#endif
break;
case CPU_P5600:
+ case CPU_I6400:
/* 8-bit event numbers */
raw_id = config & 0x1ff;
base_id = raw_id & 0xff;
@@ -1717,6 +1718,11 @@ init_hw_perf_events(void)
mipspmu.general_event_map = &mipsxxcore_event_map2;
mipspmu.cache_event_map = &mipsxxcore_cache_map2;
break;
+ case CPU_I6400:
+ mipspmu.name = "mips/I6400";
+ mipspmu.general_event_map = &mipsxxcore_event_map2;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+ break;
case CPU_1004K:
mipspmu.name = "mips/1004K";
mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/kernel/arch/mips/kernel/pm-cps.c b/kernel/arch/mips/kernel/pm-cps.c
index 06147179a..f63a28997 100644
--- a/kernel/arch/mips/kernel/pm-cps.c
+++ b/kernel/arch/mips/kernel/pm-cps.c
@@ -267,6 +267,7 @@ static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
/* CPUs which do not require the workaround */
case CPU_P5600:
+ case CPU_I6400:
return 0;
default:
@@ -671,6 +672,7 @@ static int __init cps_pm_init(void)
case CPU_PROAPTIV:
case CPU_M5150:
case CPU_P5600:
+ case CPU_I6400:
stype_intervention = 0x2;
stype_memory = 0x3;
stype_ordering = 0x10;
diff --git a/kernel/arch/mips/kernel/prom.c b/kernel/arch/mips/kernel/prom.c
index e303cb1ef..5fcec3032 100644
--- a/kernel/arch/mips/kernel/prom.c
+++ b/kernel/arch/mips/kernel/prom.c
@@ -18,6 +18,7 @@
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
+#include <asm/bootinfo.h>
#include <asm/page.h>
#include <asm/prom.h>
@@ -37,7 +38,7 @@ char *mips_get_machine_name(void)
return mips_machine_name;
}
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
return add_memory_region(base, size, BOOT_MEM_RAM);
diff --git a/kernel/arch/mips/kernel/ptrace.c b/kernel/arch/mips/kernel/ptrace.c
index e933a309f..4f0ac78d1 100644
--- a/kernel/arch/mips/kernel/ptrace.c
+++ b/kernel/arch/mips/kernel/ptrace.c
@@ -25,6 +25,7 @@
#include <linux/regset.h>
#include <linux/smp.h>
#include <linux/security.h>
+#include <linux/stddef.h>
#include <linux/tracehook.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
@@ -490,6 +491,93 @@ enum mips_regset {
REGSET_FPR,
};
+struct pt_regs_offset {
+ const char *name;
+ int offset;
+};
+
+#define REG_OFFSET_NAME(reg, r) { \
+ .name = #reg, \
+ .offset = offsetof(struct pt_regs, r) \
+}
+
+#define REG_OFFSET_END { \
+ .name = NULL, \
+ .offset = 0 \
+}
+
+static const struct pt_regs_offset regoffset_table[] = {
+ REG_OFFSET_NAME(r0, regs[0]),
+ REG_OFFSET_NAME(r1, regs[1]),
+ REG_OFFSET_NAME(r2, regs[2]),
+ REG_OFFSET_NAME(r3, regs[3]),
+ REG_OFFSET_NAME(r4, regs[4]),
+ REG_OFFSET_NAME(r5, regs[5]),
+ REG_OFFSET_NAME(r6, regs[6]),
+ REG_OFFSET_NAME(r7, regs[7]),
+ REG_OFFSET_NAME(r8, regs[8]),
+ REG_OFFSET_NAME(r9, regs[9]),
+ REG_OFFSET_NAME(r10, regs[10]),
+ REG_OFFSET_NAME(r11, regs[11]),
+ REG_OFFSET_NAME(r12, regs[12]),
+ REG_OFFSET_NAME(r13, regs[13]),
+ REG_OFFSET_NAME(r14, regs[14]),
+ REG_OFFSET_NAME(r15, regs[15]),
+ REG_OFFSET_NAME(r16, regs[16]),
+ REG_OFFSET_NAME(r17, regs[17]),
+ REG_OFFSET_NAME(r18, regs[18]),
+ REG_OFFSET_NAME(r19, regs[19]),
+ REG_OFFSET_NAME(r20, regs[20]),
+ REG_OFFSET_NAME(r21, regs[21]),
+ REG_OFFSET_NAME(r22, regs[22]),
+ REG_OFFSET_NAME(r23, regs[23]),
+ REG_OFFSET_NAME(r24, regs[24]),
+ REG_OFFSET_NAME(r25, regs[25]),
+ REG_OFFSET_NAME(r26, regs[26]),
+ REG_OFFSET_NAME(r27, regs[27]),
+ REG_OFFSET_NAME(r28, regs[28]),
+ REG_OFFSET_NAME(r29, regs[29]),
+ REG_OFFSET_NAME(r30, regs[30]),
+ REG_OFFSET_NAME(r31, regs[31]),
+ REG_OFFSET_NAME(c0_status, cp0_status),
+ REG_OFFSET_NAME(hi, hi),
+ REG_OFFSET_NAME(lo, lo),
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+ REG_OFFSET_NAME(acx, acx),
+#endif
+ REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr),
+ REG_OFFSET_NAME(c0_cause, cp0_cause),
+ REG_OFFSET_NAME(c0_epc, cp0_epc),
+#ifdef CONFIG_MIPS_MT_SMTC
+ REG_OFFSET_NAME(c0_tcstatus, cp0_tcstatus),
+#endif
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ REG_OFFSET_NAME(mpl0, mpl[0]),
+ REG_OFFSET_NAME(mpl1, mpl[1]),
+ REG_OFFSET_NAME(mpl2, mpl[2]),
+ REG_OFFSET_NAME(mtp0, mtp[0]),
+ REG_OFFSET_NAME(mtp1, mtp[1]),
+ REG_OFFSET_NAME(mtp2, mtp[2]),
+#endif
+ REG_OFFSET_END,
+};
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name: the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+ const struct pt_regs_offset *roff;
+ for (roff = regoffset_table; roff->name != NULL; roff++)
+ if (!strcmp(roff->name, name))
+ return roff->offset;
+ return -EINVAL;
+}
+
#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
static const struct user_regset mips_regsets[] = {
diff --git a/kernel/arch/mips/kernel/r2300_switch.S b/kernel/arch/mips/kernel/r2300_switch.S
index 5087a4b72..ac27ef7d4 100644
--- a/kernel/arch/mips/kernel/r2300_switch.S
+++ b/kernel/arch/mips/kernel/r2300_switch.S
@@ -31,18 +31,8 @@
#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
/*
- * FPU context is saved iff the process has used it's FPU in the current
- * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
- * userland with FPU disabled after each context switch.
- *
- * FPU will be enabled as soon as the process accesses FPU again, through
- * do_cpu() trap.
- */
-
-/*
* task_struct *resume(task_struct *prev, task_struct *next,
- * struct thread_info *next_ti, int usedfpu)
+ * struct thread_info *next_ti)
*/
LEAF(resume)
mfc0 t1, CP0_STATUS
@@ -50,22 +40,6 @@ LEAF(resume)
cpu_save_nonscratch a0
sw ra, THREAD_REG31(a0)
- beqz a3, 1f
-
- PTR_L t3, TASK_THREAD_INFO(a0)
-
- /*
- * clear saved user stack CU1 bit
- */
- lw t0, ST_OFF(t3)
- li t1, ~ST0_CU1
- and t0, t0, t1
- sw t0, ST_OFF(t3)
-
- fpu_save_single a0, t0 # clobbers t0
-
-1:
-
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
diff --git a/kernel/arch/mips/kernel/r4k_fpu.S b/kernel/arch/mips/kernel/r4k_fpu.S
index 1d88af26b..f09546ee2 100644
--- a/kernel/arch/mips/kernel/r4k_fpu.S
+++ b/kernel/arch/mips/kernel/r4k_fpu.S
@@ -13,6 +13,7 @@
* Copyright (C) 1999, 2001 Silicon Graphics, Inc.
*/
#include <asm/asm.h>
+#include <asm/asmmacro.h>
#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
@@ -35,6 +36,14 @@
.set noreorder
+/**
+ * _save_fp_context() - save FP context from the FPU
+ * @a0 - pointer to fpregs field of sigcontext
+ * @a1 - pointer to fpc_csr field of sigcontext
+ *
+ * Save FP context, including the 32 FP data registers and the FP
+ * control & status register, from the FPU to signal context.
+ */
LEAF(_save_fp_context)
.set push
SET_HARDFLOAT
@@ -54,117 +63,60 @@ LEAF(_save_fp_context)
nop
#endif
/* Store the 16 odd double precision registers */
- EX sdc1 $f1, SC_FPREGS+8(a0)
- EX sdc1 $f3, SC_FPREGS+24(a0)
- EX sdc1 $f5, SC_FPREGS+40(a0)
- EX sdc1 $f7, SC_FPREGS+56(a0)
- EX sdc1 $f9, SC_FPREGS+72(a0)
- EX sdc1 $f11, SC_FPREGS+88(a0)
- EX sdc1 $f13, SC_FPREGS+104(a0)
- EX sdc1 $f15, SC_FPREGS+120(a0)
- EX sdc1 $f17, SC_FPREGS+136(a0)
- EX sdc1 $f19, SC_FPREGS+152(a0)
- EX sdc1 $f21, SC_FPREGS+168(a0)
- EX sdc1 $f23, SC_FPREGS+184(a0)
- EX sdc1 $f25, SC_FPREGS+200(a0)
- EX sdc1 $f27, SC_FPREGS+216(a0)
- EX sdc1 $f29, SC_FPREGS+232(a0)
- EX sdc1 $f31, SC_FPREGS+248(a0)
+ EX sdc1 $f1, 8(a0)
+ EX sdc1 $f3, 24(a0)
+ EX sdc1 $f5, 40(a0)
+ EX sdc1 $f7, 56(a0)
+ EX sdc1 $f9, 72(a0)
+ EX sdc1 $f11, 88(a0)
+ EX sdc1 $f13, 104(a0)
+ EX sdc1 $f15, 120(a0)
+ EX sdc1 $f17, 136(a0)
+ EX sdc1 $f19, 152(a0)
+ EX sdc1 $f21, 168(a0)
+ EX sdc1 $f23, 184(a0)
+ EX sdc1 $f25, 200(a0)
+ EX sdc1 $f27, 216(a0)
+ EX sdc1 $f29, 232(a0)
+ EX sdc1 $f31, 248(a0)
1: .set pop
#endif
.set push
SET_HARDFLOAT
/* Store the 16 even double precision registers */
- EX sdc1 $f0, SC_FPREGS+0(a0)
- EX sdc1 $f2, SC_FPREGS+16(a0)
- EX sdc1 $f4, SC_FPREGS+32(a0)
- EX sdc1 $f6, SC_FPREGS+48(a0)
- EX sdc1 $f8, SC_FPREGS+64(a0)
- EX sdc1 $f10, SC_FPREGS+80(a0)
- EX sdc1 $f12, SC_FPREGS+96(a0)
- EX sdc1 $f14, SC_FPREGS+112(a0)
- EX sdc1 $f16, SC_FPREGS+128(a0)
- EX sdc1 $f18, SC_FPREGS+144(a0)
- EX sdc1 $f20, SC_FPREGS+160(a0)
- EX sdc1 $f22, SC_FPREGS+176(a0)
- EX sdc1 $f24, SC_FPREGS+192(a0)
- EX sdc1 $f26, SC_FPREGS+208(a0)
- EX sdc1 $f28, SC_FPREGS+224(a0)
- EX sdc1 $f30, SC_FPREGS+240(a0)
- EX sw t1, SC_FPC_CSR(a0)
+ EX sdc1 $f0, 0(a0)
+ EX sdc1 $f2, 16(a0)
+ EX sdc1 $f4, 32(a0)
+ EX sdc1 $f6, 48(a0)
+ EX sdc1 $f8, 64(a0)
+ EX sdc1 $f10, 80(a0)
+ EX sdc1 $f12, 96(a0)
+ EX sdc1 $f14, 112(a0)
+ EX sdc1 $f16, 128(a0)
+ EX sdc1 $f18, 144(a0)
+ EX sdc1 $f20, 160(a0)
+ EX sdc1 $f22, 176(a0)
+ EX sdc1 $f24, 192(a0)
+ EX sdc1 $f26, 208(a0)
+ EX sdc1 $f28, 224(a0)
+ EX sdc1 $f30, 240(a0)
+ EX sw t1, 0(a1)
jr ra
li v0, 0 # success
.set pop
END(_save_fp_context)
-#ifdef CONFIG_MIPS32_COMPAT
- /* Save 32-bit process floating point context */
-LEAF(_save_fp_context32)
- .set push
- .set MIPS_ISA_ARCH_LEVEL_RAW
- SET_HARDFLOAT
- cfc1 t1, fcr31
-
-#ifndef CONFIG_CPU_MIPS64_R6
- 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, 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)
- EX sdc1 $f8, SC32_FPREGS+64(a0)
- EX sdc1 $f10, SC32_FPREGS+80(a0)
- EX sdc1 $f12, SC32_FPREGS+96(a0)
- EX sdc1 $f14, SC32_FPREGS+112(a0)
- EX sdc1 $f16, SC32_FPREGS+128(a0)
- EX sdc1 $f18, SC32_FPREGS+144(a0)
- EX sdc1 $f20, SC32_FPREGS+160(a0)
- EX sdc1 $f22, SC32_FPREGS+176(a0)
- EX sdc1 $f24, SC32_FPREGS+192(a0)
- EX sdc1 $f26, SC32_FPREGS+208(a0)
- EX sdc1 $f28, SC32_FPREGS+224(a0)
- EX sdc1 $f30, SC32_FPREGS+240(a0)
- EX sw t1, SC32_FPC_CSR(a0)
- cfc1 t0, $0 # implementation/version
- EX sw t0, SC32_FPC_EIR(a0)
- .set pop
-
- jr ra
- li v0, 0 # success
- END(_save_fp_context32)
-#endif
-
-/*
- * Restore FPU state:
- * - fp gp registers
- * - cp1 status/control register
+/**
+ * _restore_fp_context() - restore FP context to the FPU
+ * @a0 - pointer to fpregs field of sigcontext
+ * @a1 - pointer to fpc_csr field of sigcontext
+ *
+ * Restore FP context, including the 32 FP data registers and the FP
+ * control & status register, from signal context to the FPU.
*/
LEAF(_restore_fp_context)
- EX lw t1, SC_FPC_CSR(a0)
+ EX lw t1, 0(a1)
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
defined(CONFIG_CPU_MIPS32_R6)
@@ -178,101 +130,231 @@ LEAF(_restore_fp_context)
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)
- EX ldc1 $f7, SC_FPREGS+56(a0)
- EX ldc1 $f9, SC_FPREGS+72(a0)
- EX ldc1 $f11, SC_FPREGS+88(a0)
- EX ldc1 $f13, SC_FPREGS+104(a0)
- EX ldc1 $f15, SC_FPREGS+120(a0)
- EX ldc1 $f17, SC_FPREGS+136(a0)
- EX ldc1 $f19, SC_FPREGS+152(a0)
- EX ldc1 $f21, SC_FPREGS+168(a0)
- EX ldc1 $f23, SC_FPREGS+184(a0)
- EX ldc1 $f25, SC_FPREGS+200(a0)
- EX ldc1 $f27, SC_FPREGS+216(a0)
- EX ldc1 $f29, SC_FPREGS+232(a0)
- EX ldc1 $f31, SC_FPREGS+248(a0)
+ EX ldc1 $f1, 8(a0)
+ EX ldc1 $f3, 24(a0)
+ EX ldc1 $f5, 40(a0)
+ EX ldc1 $f7, 56(a0)
+ EX ldc1 $f9, 72(a0)
+ EX ldc1 $f11, 88(a0)
+ EX ldc1 $f13, 104(a0)
+ EX ldc1 $f15, 120(a0)
+ EX ldc1 $f17, 136(a0)
+ EX ldc1 $f19, 152(a0)
+ EX ldc1 $f21, 168(a0)
+ EX ldc1 $f23, 184(a0)
+ EX ldc1 $f25, 200(a0)
+ EX ldc1 $f27, 216(a0)
+ EX ldc1 $f29, 232(a0)
+ EX ldc1 $f31, 248(a0)
1: .set pop
#endif
.set push
SET_HARDFLOAT
- EX ldc1 $f0, SC_FPREGS+0(a0)
- EX ldc1 $f2, SC_FPREGS+16(a0)
- EX ldc1 $f4, SC_FPREGS+32(a0)
- EX ldc1 $f6, SC_FPREGS+48(a0)
- EX ldc1 $f8, SC_FPREGS+64(a0)
- EX ldc1 $f10, SC_FPREGS+80(a0)
- EX ldc1 $f12, SC_FPREGS+96(a0)
- EX ldc1 $f14, SC_FPREGS+112(a0)
- EX ldc1 $f16, SC_FPREGS+128(a0)
- EX ldc1 $f18, SC_FPREGS+144(a0)
- EX ldc1 $f20, SC_FPREGS+160(a0)
- EX ldc1 $f22, SC_FPREGS+176(a0)
- EX ldc1 $f24, SC_FPREGS+192(a0)
- EX ldc1 $f26, SC_FPREGS+208(a0)
- EX ldc1 $f28, SC_FPREGS+224(a0)
- EX ldc1 $f30, SC_FPREGS+240(a0)
+ EX ldc1 $f0, 0(a0)
+ EX ldc1 $f2, 16(a0)
+ EX ldc1 $f4, 32(a0)
+ EX ldc1 $f6, 48(a0)
+ EX ldc1 $f8, 64(a0)
+ EX ldc1 $f10, 80(a0)
+ EX ldc1 $f12, 96(a0)
+ EX ldc1 $f14, 112(a0)
+ EX ldc1 $f16, 128(a0)
+ EX ldc1 $f18, 144(a0)
+ EX ldc1 $f20, 160(a0)
+ EX ldc1 $f22, 176(a0)
+ EX ldc1 $f24, 192(a0)
+ EX ldc1 $f26, 208(a0)
+ EX ldc1 $f28, 224(a0)
+ EX ldc1 $f30, 240(a0)
ctc1 t1, fcr31
.set pop
jr ra
li v0, 0 # success
END(_restore_fp_context)
-#ifdef CONFIG_MIPS32_COMPAT
-LEAF(_restore_fp_context32)
- /* Restore an o32 sigcontext. */
- .set push
- SET_HARDFLOAT
- EX lw t1, SC32_FPC_CSR(a0)
+#ifdef CONFIG_CPU_HAS_MSA
-#ifndef CONFIG_CPU_MIPS64_R6
- mfc0 t0, CP0_STATUS
- sll t0, t0, 5
- bgez t0, 1f # skip loading odd if FR=0
+ .macro op_one_wr op, idx, base
+ .align 4
+\idx: \op \idx, 0, \base
+ jr ra
nop
-#endif
+ .endm
- 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)
+ .macro op_msa_wr name, op
+LEAF(\name)
+ .set push
+ .set noreorder
+ sll t0, a0, 4
+ PTR_LA t1, 0f
+ PTR_ADDU t0, t0, t1
+ jr t0
+ nop
+ op_one_wr \op, 0, a1
+ op_one_wr \op, 1, a1
+ op_one_wr \op, 2, a1
+ op_one_wr \op, 3, a1
+ op_one_wr \op, 4, a1
+ op_one_wr \op, 5, a1
+ op_one_wr \op, 6, a1
+ op_one_wr \op, 7, a1
+ op_one_wr \op, 8, a1
+ op_one_wr \op, 9, a1
+ op_one_wr \op, 10, a1
+ op_one_wr \op, 11, a1
+ op_one_wr \op, 12, a1
+ op_one_wr \op, 13, a1
+ op_one_wr \op, 14, a1
+ op_one_wr \op, 15, a1
+ op_one_wr \op, 16, a1
+ op_one_wr \op, 17, a1
+ op_one_wr \op, 18, a1
+ op_one_wr \op, 19, a1
+ op_one_wr \op, 20, a1
+ op_one_wr \op, 21, a1
+ op_one_wr \op, 22, a1
+ op_one_wr \op, 23, a1
+ op_one_wr \op, 24, a1
+ op_one_wr \op, 25, a1
+ op_one_wr \op, 26, a1
+ op_one_wr \op, 27, a1
+ op_one_wr \op, 28, a1
+ op_one_wr \op, 29, a1
+ op_one_wr \op, 30, a1
+ op_one_wr \op, 31, a1
+ .set pop
+ END(\name)
+ .endm
-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)
- EX ldc1 $f8, SC32_FPREGS+64(a0)
- EX ldc1 $f10, SC32_FPREGS+80(a0)
- EX ldc1 $f12, SC32_FPREGS+96(a0)
- EX ldc1 $f14, SC32_FPREGS+112(a0)
- EX ldc1 $f16, SC32_FPREGS+128(a0)
- EX ldc1 $f18, SC32_FPREGS+144(a0)
- EX ldc1 $f20, SC32_FPREGS+160(a0)
- EX ldc1 $f22, SC32_FPREGS+176(a0)
- EX ldc1 $f24, SC32_FPREGS+192(a0)
- EX ldc1 $f26, SC32_FPREGS+208(a0)
- EX ldc1 $f28, SC32_FPREGS+224(a0)
- EX ldc1 $f30, SC32_FPREGS+240(a0)
- ctc1 t1, fcr31
+ op_msa_wr read_msa_wr_b, st_b
+ op_msa_wr read_msa_wr_h, st_h
+ op_msa_wr read_msa_wr_w, st_w
+ op_msa_wr read_msa_wr_d, st_d
+
+ op_msa_wr write_msa_wr_b, ld_b
+ op_msa_wr write_msa_wr_h, ld_h
+ op_msa_wr write_msa_wr_w, ld_w
+ op_msa_wr write_msa_wr_d, ld_d
+
+#endif /* CONFIG_CPU_HAS_MSA */
+
+#ifdef CONFIG_CPU_HAS_MSA
+
+ .macro save_msa_upper wr, off, base
+ .set push
+ .set noat
+#ifdef CONFIG_64BIT
+ copy_u_d \wr, 1
+ EX sd $1, \off(\base)
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+ copy_u_w \wr, 2
+ EX sw $1, \off(\base)
+ copy_u_w \wr, 3
+ EX sw $1, (\off+4)(\base)
+#else /* CONFIG_CPU_BIG_ENDIAN */
+ copy_u_w \wr, 2
+ EX sw $1, (\off+4)(\base)
+ copy_u_w \wr, 3
+ EX sw $1, \off(\base)
+#endif
+ .set pop
+ .endm
+
+LEAF(_save_msa_all_upper)
+ save_msa_upper 0, 0x00, a0
+ save_msa_upper 1, 0x08, a0
+ save_msa_upper 2, 0x10, a0
+ save_msa_upper 3, 0x18, a0
+ save_msa_upper 4, 0x20, a0
+ save_msa_upper 5, 0x28, a0
+ save_msa_upper 6, 0x30, a0
+ save_msa_upper 7, 0x38, a0
+ save_msa_upper 8, 0x40, a0
+ save_msa_upper 9, 0x48, a0
+ save_msa_upper 10, 0x50, a0
+ save_msa_upper 11, 0x58, a0
+ save_msa_upper 12, 0x60, a0
+ save_msa_upper 13, 0x68, a0
+ save_msa_upper 14, 0x70, a0
+ save_msa_upper 15, 0x78, a0
+ save_msa_upper 16, 0x80, a0
+ save_msa_upper 17, 0x88, a0
+ save_msa_upper 18, 0x90, a0
+ save_msa_upper 19, 0x98, a0
+ save_msa_upper 20, 0xa0, a0
+ save_msa_upper 21, 0xa8, a0
+ save_msa_upper 22, 0xb0, a0
+ save_msa_upper 23, 0xb8, a0
+ save_msa_upper 24, 0xc0, a0
+ save_msa_upper 25, 0xc8, a0
+ save_msa_upper 26, 0xd0, a0
+ save_msa_upper 27, 0xd8, a0
+ save_msa_upper 28, 0xe0, a0
+ save_msa_upper 29, 0xe8, a0
+ save_msa_upper 30, 0xf0, a0
+ save_msa_upper 31, 0xf8, a0
jr ra
- li v0, 0 # success
- .set pop
- END(_restore_fp_context32)
+ li v0, 0
+ END(_save_msa_all_upper)
+
+ .macro restore_msa_upper wr, off, base
+ .set push
+ .set noat
+#ifdef CONFIG_64BIT
+ EX ld $1, \off(\base)
+ insert_d \wr, 1
+#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
+ EX lw $1, \off(\base)
+ insert_w \wr, 2
+ EX lw $1, (\off+4)(\base)
+ insert_w \wr, 3
+#else /* CONFIG_CPU_BIG_ENDIAN */
+ EX lw $1, (\off+4)(\base)
+ insert_w \wr, 2
+ EX lw $1, \off(\base)
+ insert_w \wr, 3
#endif
+ .set pop
+ .endm
+
+LEAF(_restore_msa_all_upper)
+ restore_msa_upper 0, 0x00, a0
+ restore_msa_upper 1, 0x08, a0
+ restore_msa_upper 2, 0x10, a0
+ restore_msa_upper 3, 0x18, a0
+ restore_msa_upper 4, 0x20, a0
+ restore_msa_upper 5, 0x28, a0
+ restore_msa_upper 6, 0x30, a0
+ restore_msa_upper 7, 0x38, a0
+ restore_msa_upper 8, 0x40, a0
+ restore_msa_upper 9, 0x48, a0
+ restore_msa_upper 10, 0x50, a0
+ restore_msa_upper 11, 0x58, a0
+ restore_msa_upper 12, 0x60, a0
+ restore_msa_upper 13, 0x68, a0
+ restore_msa_upper 14, 0x70, a0
+ restore_msa_upper 15, 0x78, a0
+ restore_msa_upper 16, 0x80, a0
+ restore_msa_upper 17, 0x88, a0
+ restore_msa_upper 18, 0x90, a0
+ restore_msa_upper 19, 0x98, a0
+ restore_msa_upper 20, 0xa0, a0
+ restore_msa_upper 21, 0xa8, a0
+ restore_msa_upper 22, 0xb0, a0
+ restore_msa_upper 23, 0xb8, a0
+ restore_msa_upper 24, 0xc0, a0
+ restore_msa_upper 25, 0xc8, a0
+ restore_msa_upper 26, 0xd0, a0
+ restore_msa_upper 27, 0xd8, a0
+ restore_msa_upper 28, 0xe0, a0
+ restore_msa_upper 29, 0xe8, a0
+ restore_msa_upper 30, 0xf0, a0
+ restore_msa_upper 31, 0xf8, a0
+ jr ra
+ li v0, 0
+ END(_restore_msa_all_upper)
+
+#endif /* CONFIG_CPU_HAS_MSA */
.set reorder
diff --git a/kernel/arch/mips/kernel/r4k_switch.S b/kernel/arch/mips/kernel/r4k_switch.S
index 04cbbde35..92cd0516e 100644
--- a/kernel/arch/mips/kernel/r4k_switch.S
+++ b/kernel/arch/mips/kernel/r4k_switch.S
@@ -34,7 +34,7 @@
#ifndef USE_ALTERNATE_RESUME_IMPL
/*
* task_struct *resume(task_struct *prev, task_struct *next,
- * struct thread_info *next_ti, s32 fp_save)
+ * struct thread_info *next_ti)
*/
.align 5
LEAF(resume)
@@ -43,45 +43,6 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)
- /*
- * Check whether we need to save any FP context. FP context is saved
- * iff the process has used the context with the scalar FPU or the MSA
- * ASE in the current time slice, as indicated by _TIF_USEDFPU and
- * _TIF_USEDMSA respectively. switch_to will have set fp_save
- * accordingly to an FP_SAVE_ enum value.
- */
- beqz a3, 2f
-
- /*
- * We do. Clear the saved CU1 bit for prev, such that next time it is
- * scheduled it will start in userland with the FPU disabled. If the
- * task uses the FPU then it will be enabled again via the do_cpu trap.
- * This allows us to lazily restore the FP context.
- */
- PTR_L t3, TASK_THREAD_INFO(a0)
- LONG_L t0, ST_OFF(t3)
- li t1, ~ST0_CU1
- and t0, t0, t1
- LONG_S t0, ST_OFF(t3)
-
- /* Check whether we're saving scalar or vector context. */
- bgtz a3, 1f
-
- /* Save 128b MSA vector context + scalar FP control & status. */
- .set push
- SET_HARDFLOAT
- cfc1 t1, fcr31
- msa_save_all a0
- .set pop /* SET_HARDFLOAT */
-
- sw t1, THREAD_FCR31(a0)
- b 2f
-
-1: /* Save 32b/64b scalar FP context. */
- fpu_save_double a0 t0 t1 # c0_status passed in t0
- # clobbers t1
-2:
-
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
diff --git a/kernel/arch/mips/kernel/scall32-o32.S b/kernel/arch/mips/kernel/scall32-o32.S
index 6e8de80bb..2d23c834b 100644
--- a/kernel/arch/mips/kernel/scall32-o32.S
+++ b/kernel/arch/mips/kernel/scall32-o32.S
@@ -36,16 +36,8 @@ NESTED(handle_sys, PT_SIZE, sp)
lw t1, PT_EPC(sp) # skip syscall on return
subu v0, v0, __NR_O32_Linux # check syscall number
- sltiu t0, v0, __NR_O32_Linux_syscalls + 1
addiu t1, 4 # skip to next instruction
sw t1, PT_EPC(sp)
- beqz t0, illegal_syscall
-
- sll t0, v0, 2
- la t1, sys_call_table
- addu t1, t0
- lw t2, (t1) # syscall routine
- beqz t2, illegal_syscall
sw a3, PT_R26(sp) # save a3 for syscall restarting
@@ -73,10 +65,11 @@ NESTED(handle_sys, PT_SIZE, sp)
.set noreorder
.set nomacro
-1: user_lw(t5, 16(t0)) # argument #5 from usp
-4: user_lw(t6, 20(t0)) # argument #6 from usp
-3: user_lw(t7, 24(t0)) # argument #7 from usp
-2: user_lw(t8, 28(t0)) # argument #8 from usp
+load_a4: user_lw(t5, 16(t0)) # argument #5 from usp
+load_a5: user_lw(t6, 20(t0)) # argument #6 from usp
+load_a6: user_lw(t7, 24(t0)) # argument #7 from usp
+load_a7: user_lw(t8, 28(t0)) # argument #8 from usp
+loads_done:
sw t5, 16(sp) # argument #5 to ksp
sw t6, 20(sp) # argument #6 to ksp
@@ -85,16 +78,26 @@ NESTED(handle_sys, PT_SIZE, sp)
.set pop
.section __ex_table,"a"
- PTR 1b,bad_stack
- PTR 2b,bad_stack
- PTR 3b,bad_stack
- PTR 4b,bad_stack
+ PTR load_a4, bad_stack_a4
+ PTR load_a5, bad_stack_a5
+ PTR load_a6, bad_stack_a6
+ PTR load_a7, bad_stack_a7
.previous
lw t0, TI_FLAGS($28) # syscall tracing enabled?
li t1, _TIF_WORK_SYSCALL_ENTRY
and t0, t1
bnez t0, syscall_trace_entry # -> yes
+syscall_common:
+ sltiu t0, v0, __NR_O32_Linux_syscalls + 1
+ beqz t0, illegal_syscall
+
+ sll t0, v0, 2
+ la t1, sys_call_table
+ addu t1, t0
+ lw t2, (t1) # syscall routine
+
+ beqz t2, illegal_syscall
jalr t2 # Do The Real Thing (TM)
@@ -115,7 +118,7 @@ o32_syscall_exit:
syscall_trace_entry:
SAVE_STATIC
- move s0, t2
+ move s0, v0
move a0, sp
/*
@@ -128,33 +131,24 @@ syscall_trace_entry:
1: jal syscall_trace_enter
- bltz v0, 2f # seccomp failed? Skip syscall
+ bltz v0, 1f # seccomp failed? Skip syscall
+
+ move v0, s0 # restore syscall
- move t0, s0
RESTORE_STATIC
lw a0, PT_R4(sp) # Restore argument registers
lw a1, PT_R5(sp)
lw a2, PT_R6(sp)
lw a3, PT_R7(sp)
- jalr t0
-
- li t0, -EMAXERRNO - 1 # error?
- sltu t0, t0, v0
- sw t0, PT_R7(sp) # set error flag
- beqz t0, 1f
-
- lw t1, PT_R2(sp) # syscall number
- negu v0 # error
- sw t1, PT_R0(sp) # save it for syscall restarting
-1: sw v0, PT_R2(sp) # result
+ j syscall_common
-2: j syscall_exit
+1: j syscall_exit
/* ------------------------------------------------------------------------ */
/*
- * The stackpointer for a call with more than 4 arguments is bad.
- * We probably should handle this case a bit more drastic.
+ * Our open-coded access area sanity test for the stack pointer
+ * failed. We probably should handle this case a bit more drastic.
*/
bad_stack:
li v0, EFAULT
@@ -163,6 +157,22 @@ bad_stack:
sw t0, PT_R7(sp)
j o32_syscall_exit
+bad_stack_a4:
+ li t5, 0
+ b load_a5
+
+bad_stack_a5:
+ li t6, 0
+ b load_a6
+
+bad_stack_a6:
+ li t7, 0
+ b load_a7
+
+bad_stack_a7:
+ li t8, 0
+ b loads_done
+
/*
* The system call does not exist in this kernel
*/
@@ -582,3 +592,6 @@ EXPORT(sys_call_table)
PTR sys_memfd_create
PTR sys_bpf /* 4355 */
PTR sys_execveat
+ PTR sys_userfaultfd
+ PTR sys_membarrier
+ PTR sys_mlock2
diff --git a/kernel/arch/mips/kernel/scall64-64.S b/kernel/arch/mips/kernel/scall64-64.S
index a6f6b762c..deac63315 100644
--- a/kernel/arch/mips/kernel/scall64-64.S
+++ b/kernel/arch/mips/kernel/scall64-64.S
@@ -39,18 +39,11 @@ NESTED(handle_sys64, PT_SIZE, sp)
.set at
#endif
- dsubu t0, v0, __NR_64_Linux # check syscall number
- sltiu t0, t0, __NR_64_Linux_syscalls + 1
#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
ld t1, PT_EPC(sp) # skip syscall on return
daddiu t1, 4 # skip to next instruction
sd t1, PT_EPC(sp)
#endif
- beqz t0, illegal_syscall
-
- dsll t0, v0, 3 # offset into table
- ld t2, (sys_call_table - (__NR_64_Linux * 8))(t0)
- # syscall routine
sd a3, PT_R26(sp) # save a3 for syscall restarting
@@ -59,6 +52,17 @@ NESTED(handle_sys64, PT_SIZE, sp)
and t0, t1, t0
bnez t0, syscall_trace_entry
+syscall_common:
+ dsubu t2, v0, __NR_64_Linux
+ sltiu t0, t2, __NR_64_Linux_syscalls + 1
+ beqz t0, illegal_syscall
+
+ dsll t0, t2, 3 # offset into table
+ dla t2, sys_call_table
+ daddu t0, t2, t0
+ ld t2, (t0) # syscall routine
+ beqz t2, illegal_syscall
+
jalr t2 # Do The Real Thing (TM)
li t0, -EMAXERRNO - 1 # error?
@@ -78,14 +82,14 @@ n64_syscall_exit:
syscall_trace_entry:
SAVE_STATIC
- move s0, t2
+ move s0, v0
move a0, sp
move a1, v0
jal syscall_trace_enter
- bltz v0, 2f # seccomp failed? Skip syscall
+ bltz v0, 1f # seccomp failed? Skip syscall
- move t0, s0
+ move v0, s0
RESTORE_STATIC
ld a0, PT_R4(sp) # Restore argument registers
ld a1, PT_R5(sp)
@@ -93,19 +97,9 @@ syscall_trace_entry:
ld a3, PT_R7(sp)
ld a4, PT_R8(sp)
ld a5, PT_R9(sp)
- jalr t0
-
- li t0, -EMAXERRNO - 1 # error?
- sltu t0, t0, v0
- sd t0, PT_R7(sp) # set error flag
- beqz t0, 1f
-
- ld t1, PT_R2(sp) # syscall number
- dnegu v0 # error
- sd t1, PT_R0(sp) # save it for syscall restarting
-1: sd v0, PT_R2(sp) # result
+ j syscall_common
-2: j syscall_exit
+1: j syscall_exit
illegal_syscall:
/* This also isn't a 64-bit syscall, throw an error. */
@@ -436,4 +430,7 @@ EXPORT(sys_call_table)
PTR sys_memfd_create
PTR sys_bpf /* 5315 */
PTR sys_execveat
+ PTR sys_userfaultfd
+ PTR sys_membarrier
+ PTR sys_mlock2
.size sys_call_table,.-sys_call_table
diff --git a/kernel/arch/mips/kernel/scall64-n32.S b/kernel/arch/mips/kernel/scall64-n32.S
index 4b2010654..5a69eb48d 100644
--- a/kernel/arch/mips/kernel/scall64-n32.S
+++ b/kernel/arch/mips/kernel/scall64-n32.S
@@ -52,6 +52,7 @@ NESTED(handle_sysn32, PT_SIZE, sp)
and t0, t1, t0
bnez t0, n32_syscall_trace_entry
+syscall_common:
jalr t2 # Do The Real Thing (TM)
li t0, -EMAXERRNO - 1 # error?
@@ -75,9 +76,9 @@ n32_syscall_trace_entry:
move a1, v0
jal syscall_trace_enter
- bltz v0, 2f # seccomp failed? Skip syscall
+ bltz v0, 1f # seccomp failed? Skip syscall
- move t0, s0
+ move t2, s0
RESTORE_STATIC
ld a0, PT_R4(sp) # Restore argument registers
ld a1, PT_R5(sp)
@@ -85,19 +86,9 @@ n32_syscall_trace_entry:
ld a3, PT_R7(sp)
ld a4, PT_R8(sp)
ld a5, PT_R9(sp)
- jalr t0
+ j syscall_common
- li t0, -EMAXERRNO - 1 # error?
- sltu t0, t0, v0
- sd t0, PT_R7(sp) # set error flag
- beqz t0, 1f
-
- ld t1, PT_R2(sp) # syscall number
- dnegu v0 # error
- sd t1, PT_R0(sp) # save it for syscall restarting
-1: sd v0, PT_R2(sp) # result
-
-2: j syscall_exit
+1: j syscall_exit
not_n32_scall:
/* This is not an n32 compatibility syscall, pass it on to
@@ -429,4 +420,7 @@ EXPORT(sysn32_call_table)
PTR sys_memfd_create
PTR sys_bpf
PTR compat_sys_execveat /* 6320 */
+ PTR sys_userfaultfd
+ PTR sys_membarrier
+ PTR sys_mlock2
.size sysn32_call_table,.-sysn32_call_table
diff --git a/kernel/arch/mips/kernel/scall64-o32.S b/kernel/arch/mips/kernel/scall64-o32.S
index d07b210fb..e4b6d7c97 100644
--- a/kernel/arch/mips/kernel/scall64-o32.S
+++ b/kernel/arch/mips/kernel/scall64-o32.S
@@ -69,16 +69,17 @@ NESTED(handle_sys, PT_SIZE, sp)
daddu t1, t0, 32
bltz t1, bad_stack
-1: lw a4, 16(t0) # argument #5 from usp
-2: lw a5, 20(t0) # argument #6 from usp
-3: lw a6, 24(t0) # argument #7 from usp
-4: lw a7, 28(t0) # argument #8 from usp (for indirect syscalls)
+load_a4: lw a4, 16(t0) # argument #5 from usp
+load_a5: lw a5, 20(t0) # argument #6 from usp
+load_a6: lw a6, 24(t0) # argument #7 from usp
+load_a7: lw a7, 28(t0) # argument #8 from usp
+loads_done:
.section __ex_table,"a"
- PTR 1b, bad_stack
- PTR 2b, bad_stack
- PTR 3b, bad_stack
- PTR 4b, bad_stack
+ PTR load_a4, bad_stack_a4
+ PTR load_a5, bad_stack_a5
+ PTR load_a6, bad_stack_a6
+ PTR load_a7, bad_stack_a7
.previous
li t1, _TIF_WORK_SYSCALL_ENTRY
@@ -86,6 +87,7 @@ NESTED(handle_sys, PT_SIZE, sp)
and t0, t1, t0
bnez t0, trace_a_syscall
+syscall_common:
jalr t2 # Do The Real Thing (TM)
li t0, -EMAXERRNO - 1 # error?
@@ -129,9 +131,9 @@ trace_a_syscall:
1: jal syscall_trace_enter
- bltz v0, 2f # seccomp failed? Skip syscall
+ bltz v0, 1f # seccomp failed? Skip syscall
- move t0, s0
+ move t2, s0
RESTORE_STATIC
ld a0, PT_R4(sp) # Restore argument registers
ld a1, PT_R5(sp)
@@ -141,19 +143,9 @@ trace_a_syscall:
ld a5, PT_R9(sp)
ld a6, PT_R10(sp)
ld a7, PT_R11(sp) # For indirect syscalls
- jalr t0
+ j syscall_common
- li t0, -EMAXERRNO - 1 # error?
- sltu t0, t0, v0
- sd t0, PT_R7(sp) # set error flag
- beqz t0, 1f
-
- ld t1, PT_R2(sp) # syscall number
- dnegu v0 # error
- sd t1, PT_R0(sp) # save it for syscall restarting
-1: sd v0, PT_R2(sp) # result
-
-2: j syscall_exit
+1: j syscall_exit
/* ------------------------------------------------------------------------ */
@@ -167,6 +159,22 @@ bad_stack:
sd t0, PT_R7(sp)
j o32_syscall_exit
+bad_stack_a4:
+ li a4, 0
+ b load_a5
+
+bad_stack_a5:
+ li a5, 0
+ b load_a6
+
+bad_stack_a6:
+ li a6, 0
+ b load_a7
+
+bad_stack_a7:
+ li a7, 0
+ b loads_done
+
not_o32_scall:
/*
* This is not an o32 compatibility syscall, pass it on
@@ -383,7 +391,7 @@ EXPORT(sys32_call_table)
PTR sys_connect /* 4170 */
PTR sys_getpeername
PTR sys_getsockname
- PTR sys_getsockopt
+ PTR compat_sys_getsockopt
PTR sys_listen
PTR compat_sys_recv /* 4175 */
PTR compat_sys_recvfrom
@@ -567,4 +575,7 @@ EXPORT(sys32_call_table)
PTR sys_memfd_create
PTR sys_bpf /* 4355 */
PTR compat_sys_execveat
+ PTR sys_userfaultfd
+ PTR sys_membarrier
+ PTR sys_mlock2
.size sys32_call_table,.-sys32_call_table
diff --git a/kernel/arch/mips/kernel/segment.c b/kernel/arch/mips/kernel/segment.c
index 076ead2a9..87bc74a5a 100644
--- a/kernel/arch/mips/kernel/segment.c
+++ b/kernel/arch/mips/kernel/segment.c
@@ -10,6 +10,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <asm/cpu.h>
+#include <asm/debug.h>
#include <asm/mipsregs.h>
static void build_segment_config(char *str, unsigned int cfg)
@@ -91,7 +92,6 @@ static const struct file_operations segments_fops = {
static int __init segments_info(void)
{
- extern struct dentry *mips_debugfs_dir;
struct dentry *segments;
if (cpu_has_segments) {
diff --git a/kernel/arch/mips/kernel/setup.c b/kernel/arch/mips/kernel/setup.c
index be73c4911..66aac55df 100644
--- a/kernel/arch/mips/kernel/setup.c
+++ b/kernel/arch/mips/kernel/setup.c
@@ -33,11 +33,16 @@
#include <asm/cache.h>
#include <asm/cdmm.h>
#include <asm/cpu.h>
+#include <asm/debug.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/smp-ops.h>
#include <asm/prom.h>
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+const char __section(.appended_dtb) __appended_dtb[0x100000];
+#endif /* CONFIG_MIPS_ELF_APPENDED_DTB */
+
struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_data);
@@ -337,6 +342,11 @@ static void __init bootmem_init(void)
min_low_pfn = start;
if (end <= reserved_end)
continue;
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Skip zones before initrd and initrd itself */
+ if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end)))
+ continue;
+#endif
if (start >= mapstart)
continue;
mapstart = max(reserved_end, start);
@@ -479,7 +489,7 @@ static void __init bootmem_init(void)
* o bootmem_init()
* o sparse_init()
* o paging_init()
- * o dma_continguous_reserve()
+ * o dma_contiguous_reserve()
*
* At this stage the bootmem allocator is ready to use.
*
@@ -611,6 +621,10 @@ static void __init request_crashkernel(struct resource *res)
}
#endif /* !defined(CONFIG_KEXEC) */
+#define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
+#define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
+#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND)
+
static void __init arch_mem_init(char **cmdline_p)
{
struct memblock_region *reg;
@@ -635,18 +649,24 @@ static void __init arch_mem_init(char **cmdline_p)
pr_info("Determined physical RAM map:\n");
print_memory_map();
-#ifdef CONFIG_CMDLINE_BOOL
-#ifdef CONFIG_CMDLINE_OVERRIDE
+#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
+ if ((USE_PROM_CMDLINE && arcs_cmdline[0]) ||
+ (USE_DTB_CMDLINE && !boot_command_line[0]))
+ strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+
+ if (EXTEND_WITH_PROM && arcs_cmdline[0]) {
+ strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+ strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+ }
+
+#if defined(CONFIG_CMDLINE_BOOL)
if (builtin_cmdline[0]) {
- strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
- strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+ strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+ strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
}
- strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
#endif
-#else
- strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
#endif
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
diff --git a/kernel/arch/mips/kernel/signal-common.h b/kernel/arch/mips/kernel/signal-common.h
index 0b85f827c..f50d48435 100644
--- a/kernel/arch/mips/kernel/signal-common.h
+++ b/kernel/arch/mips/kernel/signal-common.h
@@ -31,4 +31,13 @@ extern int fpcsr_pending(unsigned int __user *fpcsr);
#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); })
#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); })
+/* Assembly functions to move context to/from the FPU */
+extern asmlinkage int
+_save_fp_context(void __user *fpregs, void __user *csr);
+extern asmlinkage int
+_restore_fp_context(void __user *fpregs, void __user *csr);
+
+extern asmlinkage int _save_msa_all_upper(void __user *buf);
+extern asmlinkage int _restore_msa_all_upper(void __user *buf);
+
#endif /* __SIGNAL_COMMON_H */
diff --git a/kernel/arch/mips/kernel/signal.c b/kernel/arch/mips/kernel/signal.c
index 6a28c792d..bf792e283 100644
--- a/kernel/arch/mips/kernel/signal.c
+++ b/kernel/arch/mips/kernel/signal.c
@@ -21,6 +21,7 @@
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
+#include <linux/uprobes.h>
#include <linux/compiler.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
@@ -35,23 +36,23 @@
#include <asm/ucontext.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
-#include <asm/vdso.h>
#include <asm/dsp.h>
#include <asm/inst.h>
+#include <asm/msa.h>
#include "signal-common.h"
-static int (*save_fp_context)(struct sigcontext __user *sc);
-static int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
-extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
+static int (*save_fp_context)(void __user *sc);
+static int (*restore_fp_context)(void __user *sc);
struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_pad[2]; /* Was: signal trampoline */
+
+ /* Matches struct ucontext from its uc_mcontext field onwards */
struct sigcontext sf_sc;
sigset_t sf_mask;
+ unsigned long long sf_extcontext[0];
};
struct rt_sigframe {
@@ -65,43 +66,255 @@ struct rt_sigframe {
* Thread saved context copy to/from a signal context presumed to be on the
* user stack, and therefore accessed with appropriate macros from uaccess.h.
*/
-static int copy_fp_to_sigcontext(struct sigcontext __user *sc)
+static int copy_fp_to_sigcontext(void __user *sc)
{
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
int i;
int err = 0;
+ int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
- for (i = 0; i < NUM_FPU_REGS; i++) {
+ for (i = 0; i < NUM_FPU_REGS; i += inc) {
err |=
__put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
- &sc->sc_fpregs[i]);
+ &fpregs[i]);
}
- err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+ err |= __put_user(current->thread.fpu.fcr31, csr);
return err;
}
-static int copy_fp_from_sigcontext(struct sigcontext __user *sc)
+static int copy_fp_from_sigcontext(void __user *sc)
{
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
int i;
int err = 0;
+ int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
u64 fpr_val;
- for (i = 0; i < NUM_FPU_REGS; i++) {
- err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
+ for (i = 0; i < NUM_FPU_REGS; i += inc) {
+ err |= __get_user(fpr_val, &fpregs[i]);
set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
}
- err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
+ err |= __get_user(current->thread.fpu.fcr31, csr);
+
+ return err;
+}
+
+/*
+ * Wrappers for the assembly _{save,restore}_fp_context functions.
+ */
+static int save_hw_fp_context(void __user *sc)
+{
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+
+ return _save_fp_context(fpregs, csr);
+}
+
+static int restore_hw_fp_context(void __user *sc)
+{
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+
+ return _restore_fp_context(fpregs, csr);
+}
+
+/*
+ * Extended context handling.
+ */
+
+static inline void __user *sc_to_extcontext(void __user *sc)
+{
+ struct ucontext __user *uc;
+
+ /*
+ * We can just pretend the sigcontext is always embedded in a struct
+ * ucontext here, because the offset from sigcontext to extended
+ * context is the same in the struct sigframe case.
+ */
+ uc = container_of(sc, struct ucontext, uc_mcontext);
+ return &uc->uc_extcontext;
+}
+
+static int save_msa_extcontext(void __user *buf)
+{
+ struct msa_extcontext __user *msa = buf;
+ uint64_t val;
+ int i, err;
+
+ if (!thread_msa_context_live())
+ return 0;
+
+ /*
+ * Ensure that we can't lose the live MSA context between checking
+ * for it & writing it to memory.
+ */
+ preempt_disable();
+
+ if (is_msa_enabled()) {
+ /*
+ * There are no EVA versions of the vector register load/store
+ * instructions, so MSA context has to be saved to kernel memory
+ * and then copied to user memory. The save to kernel memory
+ * should already have been done when handling scalar FP
+ * context.
+ */
+ BUG_ON(config_enabled(CONFIG_EVA));
+
+ err = __put_user(read_msa_csr(), &msa->csr);
+ err |= _save_msa_all_upper(&msa->wr);
+
+ preempt_enable();
+ } else {
+ preempt_enable();
+
+ err = __put_user(current->thread.fpu.msacsr, &msa->csr);
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ val = get_fpr64(&current->thread.fpu.fpr[i], 1);
+ err |= __put_user(val, &msa->wr[i]);
+ }
+ }
+
+ err |= __put_user(MSA_EXTCONTEXT_MAGIC, &msa->ext.magic);
+ err |= __put_user(sizeof(*msa), &msa->ext.size);
+
+ return err ? -EFAULT : sizeof(*msa);
+}
+
+static int restore_msa_extcontext(void __user *buf, unsigned int size)
+{
+ struct msa_extcontext __user *msa = buf;
+ unsigned long long val;
+ unsigned int csr;
+ int i, err;
+
+ if (size != sizeof(*msa))
+ return -EINVAL;
+
+ err = get_user(csr, &msa->csr);
+ if (err)
+ return err;
+
+ preempt_disable();
+
+ if (is_msa_enabled()) {
+ /*
+ * There are no EVA versions of the vector register load/store
+ * instructions, so MSA context has to be copied to kernel
+ * memory and later loaded to registers. The same is true of
+ * scalar FP context, so FPU & MSA should have already been
+ * disabled whilst handling scalar FP context.
+ */
+ BUG_ON(config_enabled(CONFIG_EVA));
+
+ write_msa_csr(csr);
+ err |= _restore_msa_all_upper(&msa->wr);
+ preempt_enable();
+ } else {
+ preempt_enable();
+
+ current->thread.fpu.msacsr = csr;
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ err |= __get_user(val, &msa->wr[i]);
+ set_fpr64(&current->thread.fpu.fpr[i], 1, val);
+ }
+ }
return err;
}
+static int save_extcontext(void __user *buf)
+{
+ int sz;
+
+ sz = save_msa_extcontext(buf);
+ if (sz < 0)
+ return sz;
+ buf += sz;
+
+ /* If no context was saved then trivially return */
+ if (!sz)
+ return 0;
+
+ /* Write the end marker */
+ if (__put_user(END_EXTCONTEXT_MAGIC, (u32 *)buf))
+ return -EFAULT;
+
+ sz += sizeof(((struct extcontext *)NULL)->magic);
+ return sz;
+}
+
+static int restore_extcontext(void __user *buf)
+{
+ struct extcontext ext;
+ int err;
+
+ while (1) {
+ err = __get_user(ext.magic, (unsigned int *)buf);
+ if (err)
+ return err;
+
+ if (ext.magic == END_EXTCONTEXT_MAGIC)
+ return 0;
+
+ err = __get_user(ext.size, (unsigned int *)(buf
+ + offsetof(struct extcontext, size)));
+ if (err)
+ return err;
+
+ switch (ext.magic) {
+ case MSA_EXTCONTEXT_MAGIC:
+ err = restore_msa_extcontext(buf, ext.size);
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ if (err)
+ return err;
+
+ buf += ext.size;
+ }
+}
+
/*
* Helper routines
*/
-static int protected_save_fp_context(struct sigcontext __user *sc)
+int protected_save_fp_context(void __user *sc)
{
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+ uint32_t __user *used_math = sc + abi->off_sc_used_math;
+ unsigned int used, ext_sz;
int err;
-#ifndef CONFIG_EVA
+
+ used = used_math() ? USED_FP : 0;
+ if (!used)
+ goto fp_done;
+
+ if (!test_thread_flag(TIF_32BIT_FPREGS))
+ used |= USED_FR1;
+ if (test_thread_flag(TIF_HYBRID_FPREGS))
+ used |= USED_HYBRID_FPRS;
+
+ /*
+ * EVA does not have userland equivalents of ldc1 or sdc1, so
+ * save to the kernel FP context & copy that to userland below.
+ */
+ if (config_enabled(CONFIG_EVA))
+ lose_fpu(1);
+
while (1) {
lock_fpu_owner();
if (is_fpu_owner()) {
@@ -114,27 +327,57 @@ static int protected_save_fp_context(struct sigcontext __user *sc)
if (likely(!err))
break;
/* touch the sigcontext and try again */
- err = __put_user(0, &sc->sc_fpregs[0]) |
- __put_user(0, &sc->sc_fpregs[31]) |
- __put_user(0, &sc->sc_fpc_csr);
+ err = __put_user(0, &fpregs[0]) |
+ __put_user(0, &fpregs[31]) |
+ __put_user(0, csr);
if (err)
- break; /* really bad sigcontext */
+ return err; /* really bad sigcontext */
}
-#else
- /*
- * EVA does not have FPU EVA instructions so saving fpu context directly
- * does not work.
- */
- lose_fpu(1);
- err = save_fp_context(sc); /* this might fail */
-#endif
- return err;
+
+fp_done:
+ ext_sz = err = save_extcontext(sc_to_extcontext(sc));
+ if (err < 0)
+ return err;
+ used |= ext_sz ? USED_EXTCONTEXT : 0;
+
+ return __put_user(used, used_math);
}
-static int protected_restore_fp_context(struct sigcontext __user *sc)
+int protected_restore_fp_context(void __user *sc)
{
- int err, tmp __maybe_unused;
-#ifndef CONFIG_EVA
+ struct mips_abi *abi = current->thread.abi;
+ uint64_t __user *fpregs = sc + abi->off_sc_fpregs;
+ uint32_t __user *csr = sc + abi->off_sc_fpc_csr;
+ uint32_t __user *used_math = sc + abi->off_sc_used_math;
+ unsigned int used;
+ int err, sig = 0, tmp __maybe_unused;
+
+ err = __get_user(used, used_math);
+ conditional_used_math(used & USED_FP);
+
+ /*
+ * The signal handler may have used FPU; give it up if the program
+ * doesn't want it following sigreturn.
+ */
+ if (err || !(used & USED_FP))
+ lose_fpu(0);
+ if (err)
+ return err;
+ if (!(used & USED_FP))
+ goto fp_done;
+
+ err = sig = fpcsr_pending(csr);
+ if (err < 0)
+ return err;
+
+ /*
+ * EVA does not have userland equivalents of ldc1 or sdc1, so we
+ * disable the FPU here such that the code below simply copies to
+ * the kernel FP context.
+ */
+ if (config_enabled(CONFIG_EVA))
+ lose_fpu(0);
+
while (1) {
lock_fpu_owner();
if (is_fpu_owner()) {
@@ -147,28 +390,24 @@ static int protected_restore_fp_context(struct sigcontext __user *sc)
if (likely(!err))
break;
/* touch the sigcontext and try again */
- err = __get_user(tmp, &sc->sc_fpregs[0]) |
- __get_user(tmp, &sc->sc_fpregs[31]) |
- __get_user(tmp, &sc->sc_fpc_csr);
+ err = __get_user(tmp, &fpregs[0]) |
+ __get_user(tmp, &fpregs[31]) |
+ __get_user(tmp, csr);
if (err)
break; /* really bad sigcontext */
}
-#else
- /*
- * EVA does not have FPU EVA instructions so restoring fpu context
- * directly does not work.
- */
- lose_fpu(0);
- err = restore_fp_context(sc); /* this might fail */
-#endif
- return err;
+
+fp_done:
+ if (used & USED_EXTCONTEXT)
+ err |= restore_extcontext(sc_to_extcontext(sc));
+
+ return err ?: sig;
}
int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
int err = 0;
int i;
- unsigned int used_math;
err |= __put_user(regs->cp0_epc, &sc->sc_pc);
@@ -191,19 +430,38 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
}
- used_math = !!used_math();
- err |= __put_user(used_math, &sc->sc_used_math);
- if (used_math) {
- /*
- * Save FPU state to signal context. Signal handler
- * will "inherit" current FPU state.
- */
- err |= protected_save_fp_context(sc);
- }
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ err |= protected_save_fp_context(sc);
+
return err;
}
+static size_t extcontext_max_size(void)
+{
+ size_t sz = 0;
+
+ /*
+ * The assumption here is that between this point & the point at which
+ * the extended context is saved the size of the context should only
+ * ever be able to shrink (if the task is preempted), but never grow.
+ * That is, what this function returns is an upper bound on the size of
+ * the extended context for the current task at the current time.
+ */
+
+ if (thread_msa_context_live())
+ sz += sizeof(struct msa_extcontext);
+
+ /* If any context is saved then we'll append the end marker */
+ if (sz)
+ sz += sizeof(((struct extcontext *)NULL)->magic);
+
+ return sz;
+}
+
int fpcsr_pending(unsigned int __user *fpcsr)
{
int err, sig = 0;
@@ -223,21 +481,8 @@ int fpcsr_pending(unsigned int __user *fpcsr)
return err ?: sig;
}
-static int
-check_and_restore_fp_context(struct sigcontext __user *sc)
-{
- int err, sig;
-
- err = sig = fpcsr_pending(&sc->sc_fpc_csr);
- if (err > 0)
- err = 0;
- err |= protected_restore_fp_context(sc);
- return err ?: sig;
-}
-
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
- unsigned int used_math;
unsigned long treg;
int err = 0;
int i;
@@ -265,19 +510,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
for (i = 1; i < 32; i++)
err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
- err |= __get_user(used_math, &sc->sc_used_math);
- conditional_used_math(used_math);
-
- if (used_math) {
- /* restore fpu context if we have used it before */
- if (!err)
- err = check_and_restore_fp_context(sc);
- } else {
- /* signal handler may have used FPU. Give it up. */
- lose_fpu(0);
- }
-
- return err;
+ return err ?: protected_restore_fp_context(sc);
}
void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
@@ -285,6 +518,9 @@ void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
{
unsigned long sp;
+ /* Leave space for potential extended context */
+ frame_size += extcontext_max_size();
+
/* Default to using normal stack */
sp = regs->regs[29];
@@ -515,12 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
struct mips_abi mips_abi = {
#ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame,
- .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
#endif
.setup_rt_frame = setup_rt_frame,
- .rt_signal_return_offset =
- offsetof(struct mips_vdso, rt_signal_trampoline),
- .restart = __NR_restart_syscall
+ .restart = __NR_restart_syscall,
+
+ .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
+ .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
+ .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+ .vdso = &vdso_image,
};
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
@@ -560,11 +799,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
}
if (sig_uses_siginfo(&ksig->ka))
- ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
+ ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
ksig, regs, oldset);
else
- ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
- regs, oldset);
+ ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn,
+ ksig, regs, oldset);
signal_setup_done(ret, ksig, 0);
}
@@ -616,6 +855,9 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
user_exit();
+ if (thread_info_flags & _TIF_UPROBE)
+ uprobe_notify_resume(regs);
+
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
@@ -629,43 +871,46 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
}
#ifdef CONFIG_SMP
-#ifndef CONFIG_EVA
-static int smp_save_fp_context(struct sigcontext __user *sc)
+static int smp_save_fp_context(void __user *sc)
{
return raw_cpu_has_fpu
- ? _save_fp_context(sc)
+ ? save_hw_fp_context(sc)
: copy_fp_to_sigcontext(sc);
}
-static int smp_restore_fp_context(struct sigcontext __user *sc)
+static int smp_restore_fp_context(void __user *sc)
{
return raw_cpu_has_fpu
- ? _restore_fp_context(sc)
+ ? restore_hw_fp_context(sc)
: copy_fp_from_sigcontext(sc);
}
-#endif /* CONFIG_EVA */
#endif
static int signal_setup(void)
{
-#ifndef CONFIG_EVA
+ /*
+ * The offset from sigcontext to extended context should be the same
+ * regardless of the type of signal, such that userland can always know
+ * where to look if it wishes to find the extended context structures.
+ */
+ BUILD_BUG_ON((offsetof(struct sigframe, sf_extcontext) -
+ offsetof(struct sigframe, sf_sc)) !=
+ (offsetof(struct rt_sigframe, rs_uc.uc_extcontext) -
+ offsetof(struct rt_sigframe, rs_uc.uc_mcontext)));
+
#ifdef CONFIG_SMP
/* For now just do the cpu_has_fpu check when the functions are invoked */
save_fp_context = smp_save_fp_context;
restore_fp_context = smp_restore_fp_context;
#else
if (cpu_has_fpu) {
- save_fp_context = _save_fp_context;
- restore_fp_context = _restore_fp_context;
+ save_fp_context = save_hw_fp_context;
+ restore_fp_context = restore_hw_fp_context;
} else {
save_fp_context = copy_fp_to_sigcontext;
restore_fp_context = copy_fp_from_sigcontext;
}
#endif /* CONFIG_SMP */
-#else
- save_fp_context = copy_fp_to_sigcontext;
- restore_fp_context = copy_fp_from_sigcontext;
-#endif
return 0;
}
diff --git a/kernel/arch/mips/kernel/signal32.c b/kernel/arch/mips/kernel/signal32.c
index 5d7f26349..4909639aa 100644
--- a/kernel/arch/mips/kernel/signal32.c
+++ b/kernel/arch/mips/kernel/signal32.c
@@ -31,17 +31,10 @@
#include <asm/ucontext.h>
#include <asm/fpu.h>
#include <asm/war.h>
-#include <asm/vdso.h>
#include <asm/dsp.h>
#include "signal-common.h"
-static int (*save_fp_context32)(struct sigcontext32 __user *sc);
-static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
-extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
-
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
@@ -74,99 +67,11 @@ struct rt_sigframe32 {
struct ucontext32 rs_uc;
};
-/*
- * Thread saved context copy to/from a signal context presumed to be on the
- * user stack, and therefore accessed with appropriate macros from uaccess.h.
- */
-static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc)
-{
- int i;
- int err = 0;
- int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
-
- for (i = 0; i < NUM_FPU_REGS; i += inc) {
- err |=
- __put_user(get_fpr64(&current->thread.fpu.fpr[i], 0),
- &sc->sc_fpregs[i]);
- }
- err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-
-static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc)
-{
- int i;
- int err = 0;
- int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
- u64 fpr_val;
-
- for (i = 0; i < NUM_FPU_REGS; i += inc) {
- err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
- set_fpr64(&current->thread.fpu.fpr[i], 0, fpr_val);
- }
- err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
-
- return err;
-}
-
-/*
- * sigcontext handlers
- */
-static int protected_save_fp_context32(struct sigcontext32 __user *sc)
-{
- int err;
- while (1) {
- lock_fpu_owner();
- if (is_fpu_owner()) {
- err = save_fp_context32(sc);
- unlock_fpu_owner();
- } else {
- unlock_fpu_owner();
- err = copy_fp_to_sigcontext32(sc);
- }
- if (likely(!err))
- break;
- /* touch the sigcontext and try again */
- err = __put_user(0, &sc->sc_fpregs[0]) |
- __put_user(0, &sc->sc_fpregs[31]) |
- __put_user(0, &sc->sc_fpc_csr);
- if (err)
- break; /* really bad sigcontext */
- }
- return err;
-}
-
-static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
-{
- int err, tmp __maybe_unused;
- while (1) {
- lock_fpu_owner();
- if (is_fpu_owner()) {
- err = restore_fp_context32(sc);
- unlock_fpu_owner();
- } else {
- unlock_fpu_owner();
- err = copy_fp_from_sigcontext32(sc);
- }
- if (likely(!err))
- break;
- /* touch the sigcontext and try again */
- err = __get_user(tmp, &sc->sc_fpregs[0]) |
- __get_user(tmp, &sc->sc_fpregs[31]) |
- __get_user(tmp, &sc->sc_fpc_csr);
- if (err)
- break; /* really bad sigcontext */
- }
- return err;
-}
-
static int setup_sigcontext32(struct pt_regs *regs,
struct sigcontext32 __user *sc)
{
int err = 0;
int i;
- u32 used_math;
err |= __put_user(regs->cp0_epc, &sc->sc_pc);
@@ -186,35 +91,18 @@ static int setup_sigcontext32(struct pt_regs *regs,
err |= __put_user(mflo3(), &sc->sc_lo3);
}
- used_math = !!used_math();
- err |= __put_user(used_math, &sc->sc_used_math);
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ err |= protected_save_fp_context(sc);
- if (used_math) {
- /*
- * Save FPU state to signal context. Signal handler
- * will "inherit" current FPU state.
- */
- err |= protected_save_fp_context32(sc);
- }
return err;
}
-static int
-check_and_restore_fp_context32(struct sigcontext32 __user *sc)
-{
- int err, sig;
-
- err = sig = fpcsr_pending(&sc->sc_fpc_csr);
- if (err > 0)
- err = 0;
- err |= protected_restore_fp_context32(sc);
- return err ?: sig;
-}
-
static int restore_sigcontext32(struct pt_regs *regs,
struct sigcontext32 __user *sc)
{
- u32 used_math;
int err = 0;
s32 treg;
int i;
@@ -238,70 +126,7 @@ static int restore_sigcontext32(struct pt_regs *regs,
for (i = 1; i < 32; i++)
err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
- err |= __get_user(used_math, &sc->sc_used_math);
- conditional_used_math(used_math);
-
- if (used_math) {
- /* restore fpu context if we have used it before */
- if (!err)
- err = check_and_restore_fp_context32(sc);
- } else {
- /* signal handler may have used FPU. Give it up. */
- lose_fpu(0);
- }
-
- return err;
-}
-
-/*
- *
- */
-extern void __put_sigset_unknown_nsig(void);
-extern void __get_sigset_unknown_nsig(void);
-
-static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
-{
- int err = 0;
-
- if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
- return -EFAULT;
-
- switch (_NSIG_WORDS) {
- default:
- __put_sigset_unknown_nsig();
- case 2:
- err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
- err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
- case 1:
- err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
- err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
- }
-
- return err;
-}
-
-static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
-{
- int err = 0;
- unsigned long sig[4];
-
- if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
- return -EFAULT;
-
- switch (_NSIG_WORDS) {
- default:
- __get_sigset_unknown_nsig();
- case 2:
- err |= __get_user(sig[3], &ubuf->sig[3]);
- err |= __get_user(sig[2], &ubuf->sig[2]);
- kbuf->sig[1] = sig[2] | (sig[3] << 32);
- case 1:
- err |= __get_user(sig[1], &ubuf->sig[1]);
- err |= __get_user(sig[0], &ubuf->sig[0]);
- kbuf->sig[0] = sig[0] | (sig[1] << 32);
- }
-
- return err;
+ return err ?: protected_restore_fp_context(sc);
}
/*
@@ -580,25 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
*/
struct mips_abi mips_abi_32 = {
.setup_frame = setup_frame_32,
- .signal_return_offset =
- offsetof(struct mips_vdso, o32_signal_trampoline),
.setup_rt_frame = setup_rt_frame_32,
- .rt_signal_return_offset =
- offsetof(struct mips_vdso, o32_rt_signal_trampoline),
- .restart = __NR_O32_restart_syscall
-};
-
-static int signal32_init(void)
-{
- if (cpu_has_fpu) {
- save_fp_context32 = _save_fp_context32;
- restore_fp_context32 = _restore_fp_context32;
- } else {
- save_fp_context32 = copy_fp_to_sigcontext32;
- restore_fp_context32 = copy_fp_from_sigcontext32;
- }
+ .restart = __NR_O32_restart_syscall,
- return 0;
-}
+ .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
+ .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
+ .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
-arch_initcall(signal32_init);
+ .vdso = &vdso_image_o32,
+};
diff --git a/kernel/arch/mips/kernel/signal_n32.c b/kernel/arch/mips/kernel/signal_n32.c
index f1d4751ee..a7bc38430 100644
--- a/kernel/arch/mips/kernel/signal_n32.c
+++ b/kernel/arch/mips/kernel/signal_n32.c
@@ -38,7 +38,6 @@
#include <asm/fpu.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
-#include <asm/vdso.h>
#include "signal-common.h"
@@ -151,7 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
struct mips_abi mips_abi_n32 = {
.setup_rt_frame = setup_rt_frame_n32,
- .rt_signal_return_offset =
- offsetof(struct mips_vdso, n32_rt_signal_trampoline),
- .restart = __NR_N32_restart_syscall
+ .restart = __NR_N32_restart_syscall,
+
+ .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
+ .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
+ .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+ .vdso = &vdso_image_n32,
};
diff --git a/kernel/arch/mips/kernel/smp-bmips.c b/kernel/arch/mips/kernel/smp-bmips.c
index 336708ae5..78cf8c2f1 100644
--- a/kernel/arch/mips/kernel/smp-bmips.c
+++ b/kernel/arch/mips/kernel/smp-bmips.c
@@ -284,7 +284,7 @@ static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
if (action == 0)
scheduler_ipi();
else
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
@@ -336,7 +336,7 @@ static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/kernel/arch/mips/kernel/smp-cps.c b/kernel/arch/mips/kernel/smp-cps.c
index 4251d390b..e04c8057b 100644
--- a/kernel/arch/mips/kernel/smp-cps.c
+++ b/kernel/arch/mips/kernel/smp-cps.c
@@ -8,6 +8,7 @@
* option) any later version.
*/
+#include <linux/delay.h>
#include <linux/io.h>
#include <linux/irqchip/mips-gic.h>
#include <linux/sched.h>
@@ -37,8 +38,9 @@ static unsigned core_vpe_count(unsigned core)
if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
return 1;
- write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+ mips_cm_lock_other(core, 0);
cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
+ mips_cm_unlock_other();
return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
}
@@ -133,11 +135,9 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
/*
* Patch the start of mips_cps_core_entry to provide:
*
- * v0 = CM base address
* s0 = kseg0 CCA
*/
entry_code = (u32 *)&mips_cps_core_entry;
- UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
uasm_i_addiu(&entry_code, 16, 0, cca);
blast_dcache_range((unsigned long)&mips_cps_core_entry,
(unsigned long)entry_code);
@@ -190,10 +190,11 @@ err_out:
static void boot_core(unsigned core)
{
- u32 access;
+ u32 access, stat, seq_state;
+ unsigned timeout;
/* Select the appropriate core */
- write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+ mips_cm_lock_other(core, 0);
/* Set its reset vector */
write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
@@ -210,12 +211,36 @@ static void boot_core(unsigned core)
/* Reset the core */
mips_cpc_lock_other(core);
write_cpc_co_cmd(CPC_Cx_CMD_RESET);
+
+ timeout = 100;
+ while (true) {
+ stat = read_cpc_co_stat_conf();
+ seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+
+ /* U6 == coherent execution, ie. the core is up */
+ if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U6)
+ break;
+
+ /* Delay a little while before we start warning */
+ if (timeout) {
+ timeout--;
+ mdelay(10);
+ continue;
+ }
+
+ pr_warn("Waiting for core %u to start... STAT_CONF=0x%x\n",
+ core, stat);
+ mdelay(1000);
+ }
+
mips_cpc_unlock_other();
} else {
/* Take the core out of reset */
write_gcr_co_reset_release(0);
}
+ mips_cm_unlock_other();
+
/* The core is now powered up */
bitmap_set(core_power, core, 1);
}
@@ -369,7 +394,7 @@ void play_dead(void)
static void wait_for_sibling_halt(void *ptr_cpu)
{
- unsigned cpu = (unsigned)ptr_cpu;
+ unsigned cpu = (unsigned long)ptr_cpu;
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
unsigned halted;
unsigned long flags;
@@ -430,7 +455,7 @@ static void cps_cpu_die(unsigned int cpu)
*/
err = smp_call_function_single(cpu_death_sibling,
wait_for_sibling_halt,
- (void *)cpu, 1);
+ (void *)(unsigned long)cpu, 1);
if (err)
panic("Failed to call remote sibling CPU\n");
}
diff --git a/kernel/arch/mips/kernel/smp-gic.c b/kernel/arch/mips/kernel/smp-gic.c
index 5f0ab5bcd..9b63829cf 100644
--- a/kernel/arch/mips/kernel/smp-gic.c
+++ b/kernel/arch/mips/kernel/smp-gic.c
@@ -46,9 +46,11 @@ void gic_send_ipi_single(int cpu, unsigned int action)
if (mips_cpc_present() && (core != current_cpu_data.core)) {
while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+ mips_cm_lock_other(core, 0);
mips_cpc_lock_other(core);
write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
mips_cpc_unlock_other();
+ mips_cm_unlock_other();
}
}
diff --git a/kernel/arch/mips/kernel/smp.c b/kernel/arch/mips/kernel/smp.c
index d0744cc77..2b521e07b 100644
--- a/kernel/arch/mips/kernel/smp.c
+++ b/kernel/arch/mips/kernel/smp.c
@@ -42,6 +42,7 @@
#include <asm/mmu_context.h>
#include <asm/time.h>
#include <asm/setup.h>
+#include <asm/maar.h>
cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
@@ -120,6 +121,7 @@ static inline void calculate_cpu_foreign_map(void)
cpumask_t temp_foreign_map;
/* Re-calculate the mask */
+ cpumask_clear(&temp_foreign_map);
for_each_online_cpu(i) {
core_present = 0;
for_each_cpu(k, &temp_foreign_map)
@@ -157,6 +159,7 @@ asmlinkage void start_secondary(void)
mips_clockevent_init();
mp_ops->init_secondary();
cpu_report();
+ maar_init();
/*
* XXX parity protection should be folded in here when it's converted
@@ -192,16 +195,6 @@ asmlinkage void start_secondary(void)
cpu_startup_entry(CPUHP_ONLINE);
}
-/*
- * Call into both interrupt handlers, as we share the IPI for them
- */
-void __irq_entry smp_call_function_interrupt(void)
-{
- irq_enter();
- generic_smp_call_function_interrupt();
- irq_exit();
-}
-
static void stop_this_cpu(void *dummy)
{
/*
diff --git a/kernel/arch/mips/kernel/spinlock_test.c b/kernel/arch/mips/kernel/spinlock_test.c
index 39f7ab7b0..f7d86955d 100644
--- a/kernel/arch/mips/kernel/spinlock_test.c
+++ b/kernel/arch/mips/kernel/spinlock_test.c
@@ -5,7 +5,7 @@
#include <linux/debugfs.h>
#include <linux/export.h>
#include <linux/spinlock.h>
-
+#include <asm/debug.h>
static int ss_get(void *data, u64 *val)
{
@@ -115,8 +115,6 @@ static int multi_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
-
-extern struct dentry *mips_debugfs_dir;
static int __init spinlock_test(void)
{
struct dentry *d;
diff --git a/kernel/arch/mips/kernel/spram.c b/kernel/arch/mips/kernel/spram.c
index d1168d7c3..8489c88f9 100644
--- a/kernel/arch/mips/kernel/spram.c
+++ b/kernel/arch/mips/kernel/spram.c
@@ -209,6 +209,7 @@ void spram_config(void)
case CPU_PROAPTIV:
case CPU_P5600:
case CPU_QEMU_GENERIC:
+ case CPU_I6400:
config0 = read_c0_config();
/* FIXME: addresses are Malta specific */
if (config0 & (1<<24)) {
diff --git a/kernel/arch/mips/kernel/stacktrace.c b/kernel/arch/mips/kernel/stacktrace.c
index 1ba775d24..506021f62 100644
--- a/kernel/arch/mips/kernel/stacktrace.c
+++ b/kernel/arch/mips/kernel/stacktrace.c
@@ -12,14 +12,15 @@
* Save stack-backtrace addresses into a stack_trace buffer:
*/
static void save_raw_context_stack(struct stack_trace *trace,
- unsigned long reg29)
+ unsigned long reg29, int savesched)
{
unsigned long *sp = (unsigned long *)reg29;
unsigned long addr;
while (!kstack_end(sp)) {
addr = *sp++;
- if (__kernel_text_address(addr)) {
+ if (__kernel_text_address(addr) &&
+ (savesched || !in_sched_functions(addr))) {
if (trace->skip > 0)
trace->skip--;
else
@@ -31,7 +32,7 @@ static void save_raw_context_stack(struct stack_trace *trace,
}
static void save_context_stack(struct stack_trace *trace,
- struct task_struct *tsk, struct pt_regs *regs)
+ struct task_struct *tsk, struct pt_regs *regs, int savesched)
{
unsigned long sp = regs->regs[29];
#ifdef CONFIG_KALLSYMS
@@ -43,20 +44,22 @@ static void save_context_stack(struct stack_trace *trace,
(unsigned long)task_stack_page(tsk);
if (stack_page && sp >= stack_page &&
sp <= stack_page + THREAD_SIZE - 32)
- save_raw_context_stack(trace, sp);
+ save_raw_context_stack(trace, sp, savesched);
return;
}
do {
- if (trace->skip > 0)
- trace->skip--;
- else
- trace->entries[trace->nr_entries++] = pc;
- if (trace->nr_entries >= trace->max_entries)
- break;
+ if (savesched || !in_sched_functions(pc)) {
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+ trace->entries[trace->nr_entries++] = pc;
+ if (trace->nr_entries >= trace->max_entries)
+ break;
+ }
pc = unwind_stack(tsk, &sp, pc, &ra);
} while (pc);
#else
- save_raw_context_stack(trace, sp);
+ save_raw_context_stack(trace, sp, savesched);
#endif
}
@@ -82,6 +85,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
regs->cp0_epc = tsk->thread.reg31;
} else
prepare_frametrace(regs);
- save_context_stack(trace, tsk, regs);
+ save_context_stack(trace, tsk, regs, tsk == current);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/kernel/arch/mips/kernel/sysrq.c b/kernel/arch/mips/kernel/sysrq.c
new file mode 100644
index 000000000..5f0553930
--- /dev/null
+++ b/kernel/arch/mips/kernel/sysrq.c
@@ -0,0 +1,65 @@
+/*
+ * MIPS specific sysrq operations.
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/workqueue.h>
+
+#include <asm/cpu-features.h>
+#include <asm/mipsregs.h>
+#include <asm/tlbdebug.h>
+
+/*
+ * Dump TLB entries on all CPUs.
+ */
+
+static DEFINE_SPINLOCK(show_lock);
+
+static void sysrq_tlbdump_single(void *dummy)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&show_lock, flags);
+
+ pr_info("CPU%d:\n", smp_processor_id());
+ dump_tlb_regs();
+ pr_info("\n");
+ dump_tlb_all();
+ pr_info("\n");
+
+ spin_unlock_irqrestore(&show_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void sysrq_tlbdump_othercpus(struct work_struct *dummy)
+{
+ smp_call_function(sysrq_tlbdump_single, NULL, 0);
+}
+
+static DECLARE_WORK(sysrq_tlbdump, sysrq_tlbdump_othercpus);
+#endif
+
+static void sysrq_handle_tlbdump(int key)
+{
+ sysrq_tlbdump_single(NULL);
+#ifdef CONFIG_SMP
+ schedule_work(&sysrq_tlbdump);
+#endif
+}
+
+static struct sysrq_key_op sysrq_tlbdump_op = {
+ .handler = sysrq_handle_tlbdump,
+ .help_msg = "show-tlbs(x)",
+ .action_msg = "Show TLB entries",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
+
+static int __init mips_sysrq_init(void)
+{
+ return register_sysrq_key('x', &sysrq_tlbdump_op);
+}
+arch_initcall(mips_sysrq_init);
diff --git a/kernel/arch/mips/kernel/traps.c b/kernel/arch/mips/kernel/traps.c
index 5f5f44edc..ca9a81007 100644
--- a/kernel/arch/mips/kernel/traps.c
+++ b/kernel/arch/mips/kernel/traps.c
@@ -37,6 +37,7 @@
#include <linux/irq.h>
#include <linux/perf_event.h>
+#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/branch.h>
#include <asm/break.h>
@@ -243,6 +244,7 @@ static void __show_regs(const struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
unsigned int cause = regs->cp0_cause;
+ unsigned int exccode;
int i;
show_regs_print_info(KERN_DEFAULT);
@@ -324,10 +326,10 @@ static void __show_regs(const struct pt_regs *regs)
}
printk("\n");
- printk("Cause : %08x\n", cause);
+ exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
+ printk("Cause : %08x (ExcCode %02x)\n", cause, exccode);
- cause = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
- if (1 <= cause && cause <= 5)
+ if (1 <= exccode && exccode <= 5)
printk("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
printk("PrId : %08x (%s)\n", read_c0_prid(),
@@ -369,11 +371,6 @@ void show_registers(struct pt_regs *regs)
set_fs(old_fs);
}
-static int regs_to_trapnr(struct pt_regs *regs)
-{
- return (regs->cp0_cause >> 2) & 0x1f;
-}
-
static DEFINE_RAW_SPINLOCK(die_lock);
void __noreturn die(const char *str, struct pt_regs *regs)
@@ -383,7 +380,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
oops_enter();
- if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs),
+ if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_nr,
SIGSEGV) == NOTIFY_STOP)
sig = 0;
@@ -469,7 +466,7 @@ asmlinkage void do_be(struct pt_regs *regs)
printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
data ? "Data" : "Instruction",
field, regs->cp0_epc, field, regs->regs[31]);
- if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs),
+ if (notify_die(DIE_OOPS, "bus error", regs, 0, current->thread.trap_nr,
SIGBUS) == NOTIFY_STOP)
goto out;
@@ -693,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
asmlinkage void do_ov(struct pt_regs *regs)
{
enum ctx_state prev_state;
- siginfo_t info;
+ siginfo_t info = {
+ .si_signo = SIGFPE,
+ .si_code = FPE_INTOVF,
+ .si_addr = (void __user *)regs->cp0_epc,
+ };
prev_state = exception_enter();
die_if_kernel("Integer overflow", regs);
- info.si_code = FPE_INTOVF;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
exception_exit(prev_state);
}
@@ -825,7 +822,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
int sig;
prev_state = exception_enter();
- if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
+ if (notify_die(DIE_FP, "FP exception", regs, 0, current->thread.trap_nr,
SIGFPE) == NOTIFY_STOP)
goto out;
@@ -877,15 +874,16 @@ out:
void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
const char *str)
{
- siginfo_t info;
+ siginfo_t info = { 0 };
char b[40];
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
- if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
+ SIGTRAP) == NOTIFY_STOP)
return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
- if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs),
+ if (notify_die(DIE_TRAP, str, regs, code, current->thread.trap_nr,
SIGTRAP) == NOTIFY_STOP)
return;
@@ -905,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
else
info.si_code = FPE_INTOVF;
info.si_signo = SIGFPE;
- info.si_errno = 0;
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;
@@ -947,6 +944,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
set_fs(KERNEL_DS);
prev_state = exception_enter();
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (get_isa16_mode(regs->cp0_epc)) {
u16 instr[2];
@@ -986,15 +984,27 @@ asmlinkage void do_bp(struct pt_regs *regs)
* pertain to them.
*/
switch (bcode) {
+ case BRK_UPROBE:
+ if (notify_die(DIE_UPROBE, "uprobe", regs, bcode,
+ current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
+ goto out;
+ else
+ break;
+ case BRK_UPROBE_XOL:
+ if (notify_die(DIE_UPROBE_XOL, "uprobe_xol", regs, bcode,
+ current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
+ goto out;
+ else
+ break;
case BRK_KPROBE_BP:
if (notify_die(DIE_BREAK, "debug", regs, bcode,
- regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
goto out;
else
break;
case BRK_KPROBE_SSTEPBP:
if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode,
- regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
goto out;
else
break;
@@ -1027,6 +1037,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
set_fs(get_ds());
prev_state = exception_enter();
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (get_isa16_mode(regs->cp0_epc)) {
if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
__get_user(instr[1], (u16 __user *)(epc + 2)))
@@ -1093,8 +1104,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
no_r2_instr:
prev_state = exception_enter();
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
- if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
+ if (notify_die(DIE_RI, "RI Fault", regs, 0, current->thread.trap_nr,
SIGILL) == NOTIFY_STOP)
goto out;
@@ -1443,8 +1455,9 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
enum ctx_state prev_state;
prev_state = exception_enter();
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0,
- regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP)
+ current->thread.trap_nr, SIGFPE) == NOTIFY_STOP)
goto out;
/* Clear MSACSR.Cause before enabling interrupts */
@@ -1522,7 +1535,6 @@ asmlinkage void do_watch(struct pt_regs *regs)
asmlinkage void do_mcheck(struct pt_regs *regs)
{
- const int field = 2 * sizeof(unsigned long);
int multi_match = regs->cp0_status & ST0_TS;
enum ctx_state prev_state;
mm_segment_t old_fs = get_fs();
@@ -1531,19 +1543,8 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
show_regs(regs);
if (multi_match) {
- pr_err("Index : %0x\n", read_c0_index());
- pr_err("Pagemask: %0x\n", read_c0_pagemask());
- pr_err("EntryHi : %0*lx\n", field, read_c0_entryhi());
- pr_err("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
- pr_err("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
- pr_err("Wired : %0x\n", read_c0_wired());
- pr_err("Pagegrain: %0x\n", read_c0_pagegrain());
- if (cpu_has_htw) {
- pr_err("PWField : %0*lx\n", field, read_c0_pwfield());
- pr_err("PWSize : %0*lx\n", field, read_c0_pwsize());
- pr_err("PWCtl : %0x\n", read_c0_pwctl());
- }
- pr_err("\n");
+ dump_tlb_regs();
+ pr_info("\n");
dump_tlb_all();
}
@@ -1650,6 +1651,7 @@ static inline void parity_protection_init(void)
case CPU_PROAPTIV:
case CPU_P5600:
case CPU_QEMU_GENERIC:
+ case CPU_I6400:
{
#define ERRCTL_PE 0x80000000
#define ERRCTL_L2P 0x00800000
@@ -1854,12 +1856,14 @@ void __noreturn nmi_exception_handler(struct pt_regs *regs)
{
char str[100];
+ nmi_enter();
raw_notifier_call_chain(&nmi_chain, 0, regs);
bust_spinlocks(1);
snprintf(str, 100, "CPU%d NMI taken, CP0_EPC=%lx\n",
smp_processor_id(), regs->cp0_epc);
regs->cp0_epc = read_c0_errorepc();
die(str, regs);
+ nmi_exit();
}
#define VECTORSPACING 0x100 /* for EI/VI mode */
@@ -2142,10 +2146,10 @@ void per_cpu_trap_init(bool is_boot_cpu)
BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
- /* Boot CPU's cache setup in setup_arch(). */
- if (!is_boot_cpu)
- cpu_cache_init();
- tlb_init();
+ /* Boot CPU's cache setup in setup_arch(). */
+ if (!is_boot_cpu)
+ cpu_cache_init();
+ tlb_init();
TLBMISS_HANDLER_SETUP();
}
@@ -2197,22 +2201,13 @@ void __init trap_init(void)
check_wait();
-#if defined(CONFIG_KGDB)
- if (kgdb_early_setup)
- return; /* Already done */
-#endif
-
if (cpu_has_veic || cpu_has_vint) {
unsigned long size = 0x200 + VECTORSPACING*64;
ebase = (unsigned long)
__alloc_bootmem(size, 1 << fls(size), 0);
} else {
-#ifdef CONFIG_KVM_GUEST
-#define KVM_GUEST_KSEG0 0x40000000
- ebase = KVM_GUEST_KSEG0;
-#else
- ebase = CKSEG0;
-#endif
+ ebase = CAC_BASE;
+
if (cpu_has_mips_r2_r6)
ebase += (read_c0_ebase() & 0x3ffff000);
}
diff --git a/kernel/arch/mips/kernel/unaligned.c b/kernel/arch/mips/kernel/unaligned.c
index eb3efd137..490cea569 100644
--- a/kernel/arch/mips/kernel/unaligned.c
+++ b/kernel/arch/mips/kernel/unaligned.c
@@ -85,6 +85,7 @@
#include <asm/branch.h>
#include <asm/byteorder.h>
#include <asm/cop2.h>
+#include <asm/debug.h>
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#include <asm/inst.h>
@@ -891,6 +892,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
#ifdef CONFIG_EVA
mm_segment_t seg;
#endif
+ union fpureg *fpr;
+ enum msa_2b_fmt df;
+ unsigned int wd;
origpc = (unsigned long)pc;
orig31 = regs->regs[31];
@@ -1202,6 +1206,75 @@ static void emulate_load_store_insn(struct pt_regs *regs,
break;
return;
+ case msa_op:
+ if (!cpu_has_msa)
+ goto sigill;
+
+ /*
+ * If we've reached this point then userland should have taken
+ * the MSA disabled exception & initialised vector context at
+ * some point in the past.
+ */
+ BUG_ON(!thread_msa_context_live());
+
+ df = insn.msa_mi10_format.df;
+ wd = insn.msa_mi10_format.wd;
+ fpr = &current->thread.fpu.fpr[wd];
+
+ switch (insn.msa_mi10_format.func) {
+ case msa_ld_op:
+ if (!access_ok(VERIFY_READ, addr, sizeof(*fpr)))
+ goto sigbus;
+
+ /*
+ * Disable preemption to avoid a race between copying
+ * state from userland, migrating to another CPU and
+ * updating the hardware vector register below.
+ */
+ preempt_disable();
+
+ res = __copy_from_user_inatomic(fpr, addr,
+ sizeof(*fpr));
+ if (res)
+ goto fault;
+
+ /*
+ * Update the hardware register if it is in use by the
+ * task in this quantum, in order to avoid having to
+ * save & restore the whole vector context.
+ */
+ if (test_thread_flag(TIF_USEDMSA))
+ write_msa_wr(wd, fpr, df);
+
+ preempt_enable();
+ break;
+
+ case msa_st_op:
+ if (!access_ok(VERIFY_WRITE, addr, sizeof(*fpr)))
+ goto sigbus;
+
+ /*
+ * Update from the hardware register if it is in use by
+ * the task in this quantum, in order to avoid having to
+ * save & restore the whole vector context.
+ */
+ preempt_disable();
+ if (test_thread_flag(TIF_USEDMSA))
+ read_msa_wr(wd, fpr, df);
+ preempt_enable();
+
+ res = __copy_to_user_inatomic(addr, fpr, sizeof(*fpr));
+ if (res)
+ goto fault;
+ break;
+
+ default:
+ goto sigbus;
+ }
+
+ compute_return_epc(regs);
+ break;
+
#ifndef CONFIG_CPU_MIPSR6
/*
* COP2 is available to implementor for application specific use.
@@ -2223,7 +2296,6 @@ sigbus:
}
#ifdef CONFIG_DEBUG_FS
-extern struct dentry *mips_debugfs_dir;
static int __init debugfs_unaligned(void)
{
struct dentry *d;
@@ -2240,5 +2312,5 @@ static int __init debugfs_unaligned(void)
return -ENOMEM;
return 0;
}
-__initcall(debugfs_unaligned);
+arch_initcall(debugfs_unaligned);
#endif
diff --git a/kernel/arch/mips/kernel/uprobes.c b/kernel/arch/mips/kernel/uprobes.c
new file mode 100644
index 000000000..8452d933a
--- /dev/null
+++ b/kernel/arch/mips/kernel/uprobes.c
@@ -0,0 +1,341 @@
+#include <linux/highmem.h>
+#include <linux/kdebug.h>
+#include <linux/types.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/uprobes.h>
+
+#include <asm/branch.h>
+#include <asm/cpu-features.h>
+#include <asm/ptrace.h>
+#include <asm/inst.h>
+
+static inline int insn_has_delay_slot(const union mips_instruction insn)
+{
+ switch (insn.i_format.opcode) {
+ /*
+ * jr and jalr are in r_format format.
+ */
+ case spec_op:
+ switch (insn.r_format.func) {
+ case jalr_op:
+ case jr_op:
+ return 1;
+ }
+ break;
+
+ /*
+ * This group contains:
+ * bltz_op, bgez_op, bltzl_op, bgezl_op,
+ * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+ */
+ case bcond_op:
+ switch (insn.i_format.rt) {
+ case bltz_op:
+ case bltzl_op:
+ case bgez_op:
+ case bgezl_op:
+ case bltzal_op:
+ case bltzall_op:
+ case bgezal_op:
+ case bgezall_op:
+ case bposge32_op:
+ return 1;
+ }
+ break;
+
+ /*
+ * These are unconditional and in j_format.
+ */
+ case jal_op:
+ case j_op:
+ case beq_op:
+ case beql_op:
+ case bne_op:
+ case bnel_op:
+ case blez_op: /* not really i_format */
+ case blezl_op:
+ case bgtz_op:
+ case bgtzl_op:
+ return 1;
+
+ /*
+ * And now the FPA/cp1 branch instructions.
+ */
+ case cop1_op:
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ case lwc2_op: /* This is bbit0 on Octeon */
+ case ldc2_op: /* This is bbit032 on Octeon */
+ case swc2_op: /* This is bbit1 on Octeon */
+ case sdc2_op: /* This is bbit132 on Octeon */
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: virtual address at which to install the probepoint
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
+ struct mm_struct *mm, unsigned long addr)
+{
+ union mips_instruction inst;
+
+ /*
+ * For the time being this also blocks attempts to use uprobes with
+ * MIPS16 and microMIPS.
+ */
+ if (addr & 0x03)
+ return -EINVAL;
+
+ inst.word = aup->insn[0];
+ aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)];
+ aup->ixol[1] = UPROBE_BRK_UPROBE_XOL; /* NOP */
+
+ return 0;
+}
+
+/**
+ * is_trap_insn - check if the instruction is a trap variant
+ * @insn: instruction to be checked.
+ * Returns true if @insn is a trap variant.
+ *
+ * This definition overrides the weak definition in kernel/events/uprobes.c.
+ * and is needed for the case where an architecture has multiple trap
+ * instructions (like PowerPC or MIPS). We treat BREAK just like the more
+ * modern conditional trap instructions.
+ */
+bool is_trap_insn(uprobe_opcode_t *insn)
+{
+ union mips_instruction inst;
+
+ inst.word = *insn;
+
+ switch (inst.i_format.opcode) {
+ case spec_op:
+ switch (inst.r_format.func) {
+ case break_op:
+ case teq_op:
+ case tge_op:
+ case tgeu_op:
+ case tlt_op:
+ case tltu_op:
+ case tne_op:
+ return 1;
+ }
+ break;
+
+ case bcond_op: /* Yes, really ... */
+ switch (inst.u_format.rt) {
+ case teqi_op:
+ case tgei_op:
+ case tgeiu_op:
+ case tlti_op:
+ case tltiu_op:
+ case tnei_op:
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#define UPROBE_TRAP_NR ULONG_MAX
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+ union mips_instruction insn;
+
+ /*
+ * Now find the EPC where to resume after the breakpoint has been
+ * dealt with. This may require emulation of a branch.
+ */
+ aup->resume_epc = regs->cp0_epc + 4;
+ if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) {
+ unsigned long epc;
+
+ epc = regs->cp0_epc;
+ __compute_return_epc_for_insn(regs, insn);
+ aup->resume_epc = regs->cp0_epc;
+ }
+
+ utask->autask.saved_trap_nr = current->thread.trap_nr;
+ current->thread.trap_nr = UPROBE_TRAP_NR;
+ regs->cp0_epc = current->utask->xol_vaddr;
+
+ return 0;
+}
+
+int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ current->thread.trap_nr = utask->autask.saved_trap_nr;
+ regs->cp0_epc = aup->resume_epc;
+
+ return 0;
+}
+
+/*
+ * If xol insn itself traps and generates a signal(Say,
+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
+ * instruction jumps back to its own address. It is assumed that anything
+ * like do_page_fault/do_trap/etc sets thread.trap_nr != -1.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *tsk)
+{
+ if (tsk->thread.trap_nr != UPROBE_TRAP_NR)
+ return true;
+
+ return false;
+}
+
+int arch_uprobe_exception_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = data;
+ struct pt_regs *regs = args->regs;
+
+ /* regs == NULL is a kernel bug */
+ if (WARN_ON(!regs))
+ return NOTIFY_DONE;
+
+ /* We are only interested in userspace traps */
+ if (!user_mode(regs))
+ return NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BREAK:
+ if (uprobe_pre_sstep_notifier(regs))
+ return NOTIFY_STOP;
+ break;
+ case DIE_UPROBE_XOL:
+ if (uprobe_post_sstep_notifier(regs))
+ return NOTIFY_STOP;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal. Reset the instruction pointer to its
+ * probed address for the potential restart or for post mortem analysis.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *aup,
+ struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ instruction_pointer_set(regs, utask->vaddr);
+}
+
+unsigned long arch_uretprobe_hijack_return_addr(
+ unsigned long trampoline_vaddr, struct pt_regs *regs)
+{
+ unsigned long ra;
+
+ ra = regs->regs[31];
+
+ /* Replace the return address with the trampoline address */
+ regs->regs[31] = ra;
+
+ return ra;
+}
+
+/**
+ * set_swbp - store breakpoint at a given address.
+ * @auprobe: arch specific probepoint information.
+ * @mm: the probed process address space.
+ * @vaddr: the virtual address to insert the opcode.
+ *
+ * For mm @mm, store the breakpoint instruction at @vaddr.
+ * Return 0 (success) or a negative errno.
+ *
+ * This version overrides the weak version in kernel/events/uprobes.c.
+ * It is required to handle MIPS16 and microMIPS.
+ */
+int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+ unsigned long vaddr)
+{
+ return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
+}
+
+/**
+ * set_orig_insn - Restore the original instruction.
+ * @mm: the probed process address space.
+ * @auprobe: arch specific probepoint information.
+ * @vaddr: the virtual address to insert the opcode.
+ *
+ * For mm @mm, restore the original opcode (opcode) at @vaddr.
+ * Return 0 (success) or a negative errno.
+ *
+ * This overrides the weak version in kernel/events/uprobes.c.
+ */
+int set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
+ unsigned long vaddr)
+{
+ return uprobe_write_opcode(mm, vaddr,
+ *(uprobe_opcode_t *)&auprobe->orig_inst[0].word);
+}
+
+void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+ void *src, unsigned long len)
+{
+ void *kaddr;
+
+ /* Initialize the slot */
+ kaddr = kmap_atomic(page);
+ memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
+ kunmap_atomic(kaddr);
+
+ /*
+ * The MIPS version of flush_icache_range will operate safely on
+ * user space addresses and more importantly, it doesn't require a
+ * VMA argument.
+ */
+ flush_icache_range(vaddr, vaddr + len);
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ *
+ * This overrides the weak version in kernel/events/uprobes.c.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+ return instruction_pointer(regs);
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ *
+ * For now we always emulate so this function just returns 0.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ return 0;
+}
diff --git a/kernel/arch/mips/kernel/vdso.c b/kernel/arch/mips/kernel/vdso.c
index ed2a27872..975e99759 100644
--- a/kernel/arch/mips/kernel/vdso.c
+++ b/kernel/arch/mips/kernel/vdso.c
@@ -1,122 +1,175 @@
/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
*
- * Copyright (C) 2009, 2010 Cavium Networks, Inc.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/unistd.h>
-#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
+#include <asm/abi.h>
#include <asm/vdso.h>
-#include <asm/uasm.h>
-#include <asm/processor.h>
+
+/* Kernel-provided data used by the VDSO. */
+static union mips_vdso_data vdso_data __page_aligned_data;
/*
- * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
+ * what we map and where within the area they are mapped is determined at
+ * runtime.
*/
-#define __NR_O32_sigreturn 4119
-#define __NR_O32_rt_sigreturn 4193
-#define __NR_N32_rt_sigreturn 6211
+static struct page *no_pages[] = { NULL };
+static struct vm_special_mapping vdso_vvar_mapping = {
+ .name = "[vvar]",
+ .pages = no_pages,
+};
-static struct page *vdso_page;
-
-static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
+static void __init init_vdso_image(struct mips_vdso_image *image)
{
- uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */
- uasm_i_syscall(&tramp, 0);
+ unsigned long num_pages, i;
+
+ BUG_ON(!PAGE_ALIGNED(image->data));
+ BUG_ON(!PAGE_ALIGNED(image->size));
+
+ num_pages = image->size / PAGE_SIZE;
+
+ for (i = 0; i < num_pages; i++) {
+ image->mapping.pages[i] =
+ virt_to_page(image->data + (i * PAGE_SIZE));
+ }
}
static int __init init_vdso(void)
{
- struct mips_vdso *vdso;
-
- vdso_page = alloc_page(GFP_KERNEL);
- if (!vdso_page)
- panic("Cannot allocate vdso");
-
- vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
- if (!vdso)
- panic("Cannot map vdso");
- clear_page(vdso);
-
- install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
-#ifdef CONFIG_32BIT
- install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
-#else
- install_trampoline(vdso->n32_rt_signal_trampoline,
- __NR_N32_rt_sigreturn);
- install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
- install_trampoline(vdso->o32_rt_signal_trampoline,
- __NR_O32_rt_sigreturn);
+ init_vdso_image(&vdso_image);
+
+#ifdef CONFIG_MIPS32_O32
+ init_vdso_image(&vdso_image_o32);
#endif
- vunmap(vdso);
+#ifdef CONFIG_MIPS32_N32
+ init_vdso_image(&vdso_image_n32);
+#endif
return 0;
}
subsys_initcall(init_vdso);
-static unsigned long vdso_addr(unsigned long start)
+void update_vsyscall(struct timekeeper *tk)
{
- unsigned long offset = 0UL;
-
- if (current->flags & PF_RANDOMIZE) {
- offset = get_random_int();
- offset <<= PAGE_SHIFT;
- if (TASK_IS_32BIT_ADDR)
- offset &= 0xfffffful;
- else
- offset &= 0xffffffful;
+ vdso_data_write_begin(&vdso_data);
+
+ vdso_data.xtime_sec = tk->xtime_sec;
+ vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec;
+ vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec;
+ vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec;
+ vdso_data.cs_shift = tk->tkr_mono.shift;
+
+ vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode;
+ if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+ vdso_data.cs_mult = tk->tkr_mono.mult;
+ vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last;
+ vdso_data.cs_mask = tk->tkr_mono.mask;
}
- return STACK_TOP + offset;
+ vdso_data_write_end(&vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+ if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+ vdso_data.tz_minuteswest = sys_tz.tz_minuteswest;
+ vdso_data.tz_dsttime = sys_tz.tz_dsttime;
+ }
}
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
- int ret;
- unsigned long addr;
+ struct mips_vdso_image *image = current->thread.abi->vdso;
struct mm_struct *mm = current->mm;
+ unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
+ struct vm_area_struct *vma;
+ struct resource gic_res;
+ int ret;
down_write(&mm->mmap_sem);
- addr = vdso_addr(mm->start_stack);
+ /*
+ * Determine total area size. This includes the VDSO data itself, the
+ * data page, and the GIC user page if present. Always create a mapping
+ * for the GIC user area if the GIC is present regardless of whether it
+ * is the current clocksource, in case it comes into use later on. We
+ * only map a page even though the total area is 64K, as we only need
+ * the counter registers at the start.
+ */
+ gic_size = gic_present ? PAGE_SIZE : 0;
+ vvar_size = gic_size + PAGE_SIZE;
+ size = vvar_size + image->size;
+
+ base = get_unmapped_area(NULL, 0, size, 0, 0);
+ if (IS_ERR_VALUE(base)) {
+ ret = base;
+ goto out;
+ }
+
+ data_addr = base + gic_size;
+ vdso_addr = data_addr + PAGE_SIZE;
- addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
- if (IS_ERR_VALUE(addr)) {
- ret = addr;
- goto up_fail;
+ vma = _install_special_mapping(mm, base, vvar_size,
+ VM_READ | VM_MAYREAD,
+ &vdso_vvar_mapping);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ goto out;
}
- ret = install_special_mapping(mm, addr, PAGE_SIZE,
- VM_READ|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
- &vdso_page);
+ /* Map GIC user page. */
+ if (gic_size) {
+ ret = gic_get_usm_range(&gic_res);
+ if (ret)
+ goto out;
+
+ ret = io_remap_pfn_range(vma, base,
+ gic_res.start >> PAGE_SHIFT,
+ gic_size,
+ pgprot_noncached(PAGE_READONLY));
+ if (ret)
+ goto out;
+ }
+ /* Map data page. */
+ ret = remap_pfn_range(vma, data_addr,
+ virt_to_phys(&vdso_data) >> PAGE_SHIFT,
+ PAGE_SIZE, PAGE_READONLY);
if (ret)
- goto up_fail;
+ goto out;
+
+ /* Map VDSO image. */
+ vma = _install_special_mapping(mm, vdso_addr, image->size,
+ VM_READ | VM_EXEC |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+ &image->mapping);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ goto out;
+ }
- mm->context.vdso = (void *)addr;
+ mm->context.vdso = (void *)vdso_addr;
+ ret = 0;
-up_fail:
+out:
up_write(&mm->mmap_sem);
return ret;
}
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
- return "[vdso]";
- return NULL;
-}
diff --git a/kernel/arch/mips/kernel/vmlinux.lds.S b/kernel/arch/mips/kernel/vmlinux.lds.S
index 3b46f7ce9..0a93e83cd 100644
--- a/kernel/arch/mips/kernel/vmlinux.lds.S
+++ b/kernel/arch/mips/kernel/vmlinux.lds.S
@@ -17,7 +17,9 @@ OUTPUT_ARCH(mips)
ENTRY(kernel_entry)
PHDRS {
text PT_LOAD FLAGS(7); /* RWX */
+#ifndef CONFIG_CAVIUM_OCTEON_SOC
note PT_NOTE FLAGS(4); /* R__ */
+#endif /* CAVIUM_OCTEON_SOC */
}
#ifdef CONFIG_32BIT
@@ -71,7 +73,12 @@ SECTIONS
__stop___dbe_table = .;
}
- NOTES :text :note
+#ifdef CONFIG_CAVIUM_OCTEON_SOC
+#define NOTES_HEADER
+#else /* CONFIG_CAVIUM_OCTEON_SOC */
+#define NOTES_HEADER :note
+#endif /* CONFIG_CAVIUM_OCTEON_SOC */
+ NOTES :text NOTES_HEADER
.dummy : { *(.dummy) } :text
_sdata = .; /* Start of data section */
@@ -125,8 +132,19 @@ SECTIONS
.exit.data : {
EXIT_DATA
}
-
+#ifdef CONFIG_SMP
PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
+#endif
+#ifdef CONFIG_MIPS_RAW_APPENDED_DTB
+ __appended_dtb = .;
+ /* leave space for appended DTB */
+ . += 0x100000;
+#elif defined(CONFIG_MIPS_ELF_APPENDED_DTB)
+ .appended_dtb : AT(ADDR(.appended_dtb) - LOAD_OFFSET) {
+ *(.appended_dtb)
+ KEEP(*(.appended_dtb))
+ }
+#endif
/*
* Align to 64K in attempt to eliminate holes before the
* .bss..swapper_pg_dir section at the start of .bss. This
@@ -175,6 +193,7 @@ SECTIONS
DISCARDS
/DISCARD/ : {
/* ABI crap starts here */
+ *(.MIPS.abiflags)
*(.MIPS.options)
*(.options)
*(.pdr)
diff --git a/kernel/arch/mips/kernel/vpe.c b/kernel/arch/mips/kernel/vpe.c
index 11da31456..9067b651c 100644
--- a/kernel/arch/mips/kernel/vpe.c
+++ b/kernel/arch/mips/kernel/vpe.c
@@ -817,6 +817,7 @@ static int vpe_open(struct inode *inode, struct file *filp)
static int vpe_release(struct inode *inode, struct file *filp)
{
+#if defined(CONFIG_MIPS_VPE_LOADER_MT) || defined(CONFIG_MIPS_VPE_LOADER_CMP)
struct vpe *v;
Elf_Ehdr *hdr;
int ret = 0;
@@ -827,7 +828,7 @@ static int vpe_release(struct inode *inode, struct file *filp)
hdr = (Elf_Ehdr *) v->pbuffer;
if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) == 0) {
- if ((vpe_elfload(v) >= 0) && vpe_run) {
+ if (vpe_elfload(v) >= 0) {
vpe_run(v);
} else {
pr_warn("VPE loader: ELF load failed.\n");
@@ -850,6 +851,10 @@ static int vpe_release(struct inode *inode, struct file *filp)
v->plen = 0;
return ret;
+#else
+ pr_warn("VPE loader: ELF load failed.\n");
+ return -ENOEXEC;
+#endif
}
static ssize_t vpe_write(struct file *file, const char __user *buffer,
diff --git a/kernel/arch/mips/kvm/emulate.c b/kernel/arch/mips/kvm/emulate.c
index d5fa3eaf3..41b1b090f 100644
--- a/kernel/arch/mips/kvm/emulate.c
+++ b/kernel/arch/mips/kvm/emulate.c
@@ -1581,7 +1581,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
base = (inst >> 21) & 0x1f;
op_inst = (inst >> 16) & 0x1f;
- offset = inst & 0xffff;
+ offset = (int16_t)inst;
cache = (inst >> 16) & 0x3;
op = (inst >> 18) & 0x7;
diff --git a/kernel/arch/mips/kvm/locore.S b/kernel/arch/mips/kvm/locore.S
index c56724038..7e2210846 100644
--- a/kernel/arch/mips/kvm/locore.S
+++ b/kernel/arch/mips/kvm/locore.S
@@ -36,14 +36,6 @@
#define PT_HOST_USERLOCAL PT_EPC
#define CP0_DDATA_LO $28,3
-#define CP0_CONFIG3 $16,3
-#define CP0_CONFIG5 $16,5
-#define CP0_EBASE $15,1
-
-#define CP0_INTCTL $12,1
-#define CP0_SRSCTL $12,2
-#define CP0_SRSMAP $12,3
-#define CP0_HWRENA $7,0
/* Resume Flags */
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
@@ -165,9 +157,11 @@ FEXPORT(__kvm_mips_vcpu_run)
FEXPORT(__kvm_mips_load_asid)
/* Set the ASID for the Guest Kernel */
- INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
- /* addresses shift to 0x80000000 */
- bltz t0, 1f /* If kernel */
+ PTR_L t0, VCPU_COP0(k1)
+ LONG_L t0, COP0_STATUS(t0)
+ andi t0, KSU_USER | ST0_ERL | ST0_EXL
+ xori t0, KSU_USER
+ bnez t0, 1f /* If kernel */
INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
1:
@@ -482,9 +476,11 @@ __kvm_mips_return_to_guest:
mtc0 t0, CP0_EPC
/* Set the ASID for the Guest Kernel */
- INT_SLL t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */
- /* addresses shift to 0x80000000 */
- bltz t0, 1f /* If kernel */
+ PTR_L t0, VCPU_COP0(k1)
+ LONG_L t0, COP0_STATUS(t0)
+ andi t0, KSU_USER | ST0_ERL | ST0_EXL
+ xori t0, KSU_USER
+ bnez t0, 1f /* If kernel */
INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
1:
diff --git a/kernel/arch/mips/kvm/mips.c b/kernel/arch/mips/kvm/mips.c
index 52f205ae1..8a113298b 100644
--- a/kernel/arch/mips/kvm/mips.c
+++ b/kernel/arch/mips/kvm/mips.c
@@ -55,6 +55,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "msa_disabled", VCPU_STAT(msa_disabled_exits), KVM_STAT_VCPU },
{ "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
{ "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU },
+ { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll), KVM_STAT_VCPU },
{ "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU },
{NULL}
};
@@ -198,15 +199,16 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
int kvm_arch_prepare_memory_region(struct kvm *kvm,
struct kvm_memory_slot *memslot,
- struct kvm_userspace_memory_region *mem,
+ const struct kvm_userspace_memory_region *mem,
enum kvm_mr_change change)
{
return 0;
}
void kvm_arch_commit_memory_region(struct kvm *kvm,
- struct kvm_userspace_memory_region *mem,
+ const struct kvm_userspace_memory_region *mem,
const struct kvm_memory_slot *old,
+ const struct kvm_memory_slot *new,
enum kvm_mr_change change)
{
unsigned long npages = 0;
@@ -277,7 +279,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
if (!gebase) {
err = -ENOMEM;
- goto out_free_cpu;
+ goto out_uninit_cpu;
}
kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n",
ALIGN(size, PAGE_SIZE), gebase);
@@ -341,6 +343,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
out_free_gebase:
kfree(gebase);
+out_uninit_cpu:
+ kvm_vcpu_uninit(vcpu);
+
out_free_cpu:
kfree(vcpu);
@@ -393,7 +398,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
kvm_mips_deliver_interrupts(vcpu,
kvm_read_c0_guest_cause(vcpu->arch.cop0));
- kvm_guest_enter();
+ __kvm_guest_enter();
/* Disable hardware page table walking while in guest */
htw_stop();
@@ -403,7 +408,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
/* Re-enable HTW before enabling interrupts */
htw_start();
- kvm_guest_exit();
+ __kvm_guest_exit();
local_irq_enable();
if (vcpu->sigset_active)
@@ -440,8 +445,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
dvcpu->arch.wait = 0;
- if (waitqueue_active(&dvcpu->wq))
- wake_up_interruptible(&dvcpu->wq);
+ if (swait_active(&dvcpu->wq))
+ swake_up(&dvcpu->wq);
return 0;
}
@@ -697,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
void __user *uaddr = (void __user *)(long)reg->addr;
- return copy_to_user(uaddr, vs, 16);
+ return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
} else {
return -EINVAL;
}
@@ -727,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
void __user *uaddr = (void __user *)(long)reg->addr;
- return copy_from_user(vs, uaddr, 16);
+ return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
} else {
return -EINVAL;
}
@@ -968,6 +973,7 @@ out:
/* Get (and clear) the dirty memory log for a memory slot. */
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
{
+ struct kvm_memslots *slots;
struct kvm_memory_slot *memslot;
unsigned long ga, ga_end;
int is_dirty = 0;
@@ -982,7 +988,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
/* If nothing is dirty, don't bother messing with page tables. */
if (is_dirty) {
- memslot = id_to_memslot(kvm->memslots, log->slot);
+ slots = kvm_memslots(kvm);
+ memslot = id_to_memslot(slots, log->slot);
ga = memslot->base_gfn << PAGE_SHIFT;
ga_end = ga + (memslot->npages << PAGE_SHIFT);
@@ -1167,8 +1174,8 @@ static void kvm_mips_comparecount_func(unsigned long data)
kvm_mips_callbacks->queue_timer_int(vcpu);
vcpu->arch.wait = 0;
- if (waitqueue_active(&vcpu->wq))
- wake_up_interruptible(&vcpu->wq);
+ if (swait_active(&vcpu->wq))
+ swake_up(&vcpu->wq);
}
/* low level hrtimer wake routine */
diff --git a/kernel/arch/mips/lantiq/clk.c b/kernel/arch/mips/lantiq/clk.c
index 3fc2e6d70..a0706fd4c 100644
--- a/kernel/arch/mips/lantiq/clk.c
+++ b/kernel/arch/mips/lantiq/clk.c
@@ -99,6 +99,23 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
}
EXPORT_SYMBOL(clk_set_rate);
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (unlikely(!clk_good(clk)))
+ return 0;
+ if (clk->rates && *clk->rates) {
+ unsigned long *r = clk->rates;
+
+ while (*r && (*r != rate))
+ r++;
+ if (!*r) {
+ return clk->rate;
+ }
+ }
+ return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
int clk_enable(struct clk *clk)
{
if (unlikely(!clk_good(clk)))
diff --git a/kernel/arch/mips/lantiq/clk.h b/kernel/arch/mips/lantiq/clk.h
index 77e4bdb1f..7376ce817 100644
--- a/kernel/arch/mips/lantiq/clk.h
+++ b/kernel/arch/mips/lantiq/clk.h
@@ -31,13 +31,18 @@
#define CLOCK_240M 240000000
#define CLOCK_250M 250000000
#define CLOCK_266M 266666666
+#define CLOCK_288M 288888888
#define CLOCK_300M 300000000
#define CLOCK_333M 333333333
+#define CLOCK_360M 360000000
#define CLOCK_393M 393215332
#define CLOCK_400M 400000000
+#define CLOCK_432M 432000000
#define CLOCK_450M 450000000
#define CLOCK_500M 500000000
#define CLOCK_600M 600000000
+#define CLOCK_666M 666666666
+#define CLOCK_720M 720000000
/* clock out speeds */
#define CLOCK_32_768K 32768
@@ -80,4 +85,12 @@ extern unsigned long ltq_vr9_cpu_hz(void);
extern unsigned long ltq_vr9_fpi_hz(void);
extern unsigned long ltq_vr9_pp32_hz(void);
+extern unsigned long ltq_ar10_cpu_hz(void);
+extern unsigned long ltq_ar10_fpi_hz(void);
+extern unsigned long ltq_ar10_pp32_hz(void);
+
+extern unsigned long ltq_grx390_cpu_hz(void);
+extern unsigned long ltq_grx390_fpi_hz(void);
+extern unsigned long ltq_grx390_pp32_hz(void);
+
#endif
diff --git a/kernel/arch/mips/lantiq/irq.c b/kernel/arch/mips/lantiq/irq.c
index d01ade634..2e7f60c9f 100644
--- a/kernel/arch/mips/lantiq/irq.c
+++ b/kernel/arch/mips/lantiq/irq.c
@@ -293,7 +293,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
@@ -369,8 +369,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
if (of_address_to_resource(node, i, &res))
panic("Failed to get icu memory range");
- if (request_mem_region(res.start, resource_size(&res),
- res.name) < 0)
+ if (!request_mem_region(res.start, resource_size(&res),
+ res.name))
pr_err("Failed to request icu memory");
ltq_icu_membase[i] = ioremap_nocache(res.start,
@@ -449,8 +449,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
if (ret != exin_avail)
panic("failed to load external irq resources");
- if (request_mem_region(res.start, resource_size(&res),
- res.name) < 0)
+ if (!request_mem_region(res.start, resource_size(&res),
+ res.name))
pr_err("Failed to request eiu memory");
ltq_eiu_membase = ioremap_nocache(res.start,
diff --git a/kernel/arch/mips/lantiq/prom.c b/kernel/arch/mips/lantiq/prom.c
index 0db099ecc..297bcaa6b 100644
--- a/kernel/arch/mips/lantiq/prom.c
+++ b/kernel/arch/mips/lantiq/prom.c
@@ -77,8 +77,6 @@ void __init plat_mem_setup(void)
* parsed resulting in our memory appearing
*/
__dt_setup_arch(__dtb_start);
-
- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
}
void __init device_tree_init(void)
diff --git a/kernel/arch/mips/lantiq/xway/clk.c b/kernel/arch/mips/lantiq/xway/clk.c
index 8750dc0a1..07f6d5b0b 100644
--- a/kernel/arch/mips/lantiq/xway/clk.c
+++ b/kernel/arch/mips/lantiq/xway/clk.c
@@ -4,6 +4,7 @@
* by the Free Software Foundation.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
*/
#include <linux/io.h>
@@ -25,9 +26,9 @@ static unsigned int ram_clocks[] = {
/* legacy xway clock */
#define CGU_SYS 0x10
-/* vr9 clock */
-#define CGU_SYS_VR9 0x0c
-#define CGU_IF_CLK_VR9 0x24
+/* vr9, ar10/grx390 clock */
+#define CGU_SYS_XRX 0x0c
+#define CGU_IF_CLK_AR10 0x24
unsigned long ltq_danube_fpi_hz(void)
{
@@ -87,8 +88,9 @@ unsigned long ltq_ar9_fpi_hz(void)
unsigned long sys = ltq_ar9_sys_hz();
if (ltq_cgu_r32(CGU_SYS) & BIT(0))
- return sys;
- return sys >> 1;
+ return sys / 3;
+ else
+ return sys / 2;
}
unsigned long ltq_ar9_cpu_hz(void)
@@ -104,7 +106,7 @@ unsigned long ltq_vr9_cpu_hz(void)
unsigned int cpu_sel;
unsigned long clk;
- cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
+ cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf;
switch (cpu_sel) {
case 0:
@@ -145,7 +147,7 @@ unsigned long ltq_vr9_fpi_hz(void)
unsigned long clk;
cpu_clk = ltq_vr9_cpu_hz();
- ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
+ ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3;
switch (ocp_sel) {
case 0:
@@ -174,15 +176,18 @@ unsigned long ltq_vr9_fpi_hz(void)
unsigned long ltq_vr9_pp32_hz(void)
{
- unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3;
+ unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
unsigned long clk;
switch (clksys) {
+ case 0:
+ clk = CLOCK_500M;
+ break;
case 1:
- clk = CLOCK_450M;
+ clk = CLOCK_432M;
break;
case 2:
- clk = CLOCK_300M;
+ clk = CLOCK_288M;
break;
default:
clk = CLOCK_500M;
@@ -191,3 +196,158 @@ unsigned long ltq_vr9_pp32_hz(void)
return clk;
}
+
+unsigned long ltq_ar10_cpu_hz(void)
+{
+ unsigned int clksys;
+ int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1;
+ int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7;
+
+ switch (cpu_fs) {
+ case 0:
+ clksys = CLOCK_500M;
+ break;
+ case 1:
+ clksys = CLOCK_600M;
+ break;
+ default:
+ clksys = CLOCK_500M;
+ break;
+ }
+
+ switch (freq_div) {
+ case 0:
+ return clksys;
+ case 1:
+ return clksys >> 1;
+ case 2:
+ return clksys >> 2;
+ default:
+ return clksys;
+ }
+}
+
+unsigned long ltq_ar10_fpi_hz(void)
+{
+ int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf;
+
+ switch (freq_fpi) {
+ case 1:
+ return CLOCK_300M;
+ case 5:
+ return CLOCK_250M;
+ case 2:
+ return CLOCK_150M;
+ case 6:
+ return CLOCK_125M;
+
+ default:
+ return CLOCK_125M;
+ }
+}
+
+unsigned long ltq_ar10_pp32_hz(void)
+{
+ unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+ unsigned long clk;
+
+ switch (clksys) {
+ case 1:
+ clk = CLOCK_250M;
+ break;
+ case 4:
+ clk = CLOCK_400M;
+ break;
+ default:
+ clk = CLOCK_250M;
+ break;
+ }
+
+ return clk;
+}
+
+unsigned long ltq_grx390_cpu_hz(void)
+{
+ unsigned int clksys;
+ int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+ int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7);
+
+ switch (cpu_fs) {
+ case 0:
+ clksys = CLOCK_600M;
+ break;
+ case 1:
+ clksys = CLOCK_666M;
+ break;
+ case 2:
+ clksys = CLOCK_720M;
+ break;
+ default:
+ clksys = CLOCK_600M;
+ break;
+ }
+
+ switch (freq_div) {
+ case 0:
+ return clksys;
+ case 1:
+ return clksys >> 1;
+ case 2:
+ return clksys >> 2;
+ default:
+ return clksys;
+ }
+}
+
+unsigned long ltq_grx390_fpi_hz(void)
+{
+ /* fpi clock is derived from ddr_clk */
+ unsigned int clksys;
+ int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+ int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7);
+ switch (cpu_fs) {
+ case 0:
+ clksys = CLOCK_600M;
+ break;
+ case 1:
+ clksys = CLOCK_666M;
+ break;
+ case 2:
+ clksys = CLOCK_720M;
+ break;
+ default:
+ clksys = CLOCK_600M;
+ break;
+ }
+
+ switch (freq_div) {
+ case 1:
+ return clksys >> 1;
+ case 2:
+ return clksys >> 2;
+ default:
+ return clksys >> 1;
+ }
+}
+
+unsigned long ltq_grx390_pp32_hz(void)
+{
+ unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+ unsigned long clk;
+
+ switch (clksys) {
+ case 1:
+ clk = CLOCK_250M;
+ break;
+ case 2:
+ clk = CLOCK_432M;
+ break;
+ case 4:
+ clk = CLOCK_400M;
+ break;
+ default:
+ clk = CLOCK_250M;
+ break;
+ }
+ return clk;
+}
diff --git a/kernel/arch/mips/lantiq/xway/prom.c b/kernel/arch/mips/lantiq/xway/prom.c
index 248429ab2..8f6e02f1e 100644
--- a/kernel/arch/mips/lantiq/xway/prom.c
+++ b/kernel/arch/mips/lantiq/xway/prom.c
@@ -4,6 +4,7 @@
* by the Free Software Foundation.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
*/
#include <linux/export.h>
@@ -19,8 +20,11 @@
#define SOC_TWINPASS "Twinpass"
#define SOC_AMAZON_SE "Amazon_SE"
#define SOC_AR9 "AR9"
-#define SOC_GR9 "GR9"
-#define SOC_VR9 "VR9"
+#define SOC_GR9 "GRX200"
+#define SOC_VR9 "xRX200"
+#define SOC_VRX220 "xRX220"
+#define SOC_AR10 "xRX300"
+#define SOC_GRX390 "xRX330"
#define COMP_DANUBE "lantiq,danube"
#define COMP_TWINPASS "lantiq,twinpass"
@@ -28,6 +32,8 @@
#define COMP_AR9 "lantiq,ar9"
#define COMP_GR9 "lantiq,gr9"
#define COMP_VR9 "lantiq,vr9"
+#define COMP_AR10 "lantiq,ar10"
+#define COMP_GRX390 "lantiq,grx390"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
@@ -101,6 +107,12 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
i->compatible = COMP_VR9;
break;
+ case SOC_ID_VRX220:
+ i->name = SOC_VRX220;
+ i->type = SOC_TYPE_VRX220;
+ i->compatible = COMP_VR9;
+ break;
+
case SOC_ID_GRX282_2:
case SOC_ID_GRX288_2:
i->name = SOC_GR9;
@@ -108,6 +120,25 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
i->compatible = COMP_GR9;
break;
+ case SOC_ID_ARX362:
+ case SOC_ID_ARX368:
+ case SOC_ID_ARX382:
+ case SOC_ID_ARX388:
+ case SOC_ID_URX388:
+ i->name = SOC_AR10;
+ i->type = SOC_TYPE_AR10;
+ i->compatible = COMP_AR10;
+ break;
+
+ case SOC_ID_GRX383:
+ case SOC_ID_GRX369:
+ case SOC_ID_GRX387:
+ case SOC_ID_GRX389:
+ i->name = SOC_GRX390;
+ i->type = SOC_TYPE_GRX390;
+ i->compatible = COMP_GRX390;
+ break;
+
default:
unreachable();
break;
diff --git a/kernel/arch/mips/lantiq/xway/reset.c b/kernel/arch/mips/lantiq/xway/reset.c
index fe68f9ae4..bc29bb349 100644
--- a/kernel/arch/mips/lantiq/xway/reset.c
+++ b/kernel/arch/mips/lantiq/xway/reset.c
@@ -4,6 +4,7 @@
* by the Free Software Foundation.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
*/
#include <linux/init.h>
@@ -22,9 +23,6 @@
#include "../prom.h"
-#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y))
-#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x))
-
/* reset request register */
#define RCU_RST_REQ 0x0010
/* reset status register */
@@ -32,11 +30,33 @@
/* vr9 gphy registers */
#define RCU_GFS_ADD0_XRX200 0x0020
#define RCU_GFS_ADD1_XRX200 0x0068
+/* xRX300 gphy registers */
+#define RCU_GFS_ADD0_XRX300 0x0020
+#define RCU_GFS_ADD1_XRX300 0x0058
+#define RCU_GFS_ADD2_XRX300 0x00AC
+/* xRX330 gphy registers */
+#define RCU_GFS_ADD0_XRX330 0x0020
+#define RCU_GFS_ADD1_XRX330 0x0058
+#define RCU_GFS_ADD2_XRX330 0x00AC
+#define RCU_GFS_ADD3_XRX330 0x0264
+
+/* xbar BE flag */
+#define RCU_AHB_ENDIAN 0x004C
+#define RCU_VR9_BE_AHB1S 0x00000008
/* reboot bit */
#define RCU_RD_GPHY0_XRX200 BIT(31)
#define RCU_RD_SRST BIT(30)
#define RCU_RD_GPHY1_XRX200 BIT(29)
+/* xRX300 bits */
+#define RCU_RD_GPHY0_XRX300 BIT(31)
+#define RCU_RD_GPHY1_XRX300 BIT(29)
+#define RCU_RD_GPHY2_XRX300 BIT(28)
+/* xRX330 bits */
+#define RCU_RD_GPHY0_XRX330 BIT(31)
+#define RCU_RD_GPHY1_XRX330 BIT(29)
+#define RCU_RD_GPHY2_XRX330 BIT(28)
+#define RCU_RD_GPHY3_XRX330 BIT(10)
/* reset cause */
#define RCU_STAT_SHIFT 26
@@ -44,9 +64,60 @@
#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
+/* dwc2 USB configuration registers */
+#define RCU_USB1CFG 0x0018
+#define RCU_USB2CFG 0x0034
+
+/* USB DMA endianness bits */
+#define RCU_USBCFG_HDSEL_BIT BIT(11)
+#define RCU_USBCFG_HOST_END_BIT BIT(10)
+#define RCU_USBCFG_SLV_END_BIT BIT(9)
+
+/* USB reset bits */
+#define RCU_USBRESET 0x0010
+
+#define USBRESET_BIT BIT(4)
+
+#define RCU_USBRESET2 0x0048
+
+#define USB1RESET_BIT BIT(4)
+#define USB2RESET_BIT BIT(5)
+
+#define RCU_CFG1A 0x0038
+#define RCU_CFG1B 0x003C
+
+/* USB PMU devices */
+#define PMU_AHBM BIT(15)
+#define PMU_USB0 BIT(6)
+#define PMU_USB1 BIT(27)
+
+/* USB PHY PMU devices */
+#define PMU_USB0_P BIT(0)
+#define PMU_USB1_P BIT(26)
+
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
static struct device_node *ltq_rcu_np;
+static DEFINE_SPINLOCK(ltq_rcu_lock);
+
+static void ltq_rcu_w32(uint32_t val, uint32_t reg_off)
+{
+ ltq_w32(val, ltq_rcu_membase + reg_off);
+}
+
+static uint32_t ltq_rcu_r32(uint32_t reg_off)
+{
+ return ltq_r32(ltq_rcu_membase + reg_off);
+}
+
+static void ltq_rcu_w32_mask(uint32_t clr, uint32_t set, uint32_t reg_off)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ltq_rcu_lock, flags);
+ ltq_rcu_w32((ltq_rcu_r32(reg_off) & ~(clr)) | (set), reg_off);
+ spin_unlock_irqrestore(&ltq_rcu_lock, flags);
+}
/* This function is used by the watchdog driver */
int ltq_reset_cause(void)
@@ -67,15 +138,40 @@ unsigned char ltq_boot_select(void)
return RCU_BOOT_SEL(val);
}
-/* reset / boot a gphy */
-static struct ltq_xrx200_gphy_reset {
+struct ltq_gphy_reset {
u32 rd;
u32 addr;
-} xrx200_gphy[] = {
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx200_gphy[] = {
{RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
{RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
};
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx300_gphy[] = {
+ {RCU_RD_GPHY0_XRX300, RCU_GFS_ADD0_XRX300},
+ {RCU_RD_GPHY1_XRX300, RCU_GFS_ADD1_XRX300},
+ {RCU_RD_GPHY2_XRX300, RCU_GFS_ADD2_XRX300},
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx330_gphy[] = {
+ {RCU_RD_GPHY0_XRX330, RCU_GFS_ADD0_XRX330},
+ {RCU_RD_GPHY1_XRX330, RCU_GFS_ADD1_XRX330},
+ {RCU_RD_GPHY2_XRX330, RCU_GFS_ADD2_XRX330},
+ {RCU_RD_GPHY3_XRX330, RCU_GFS_ADD3_XRX330},
+};
+
+static void xrx200_gphy_boot_addr(struct ltq_gphy_reset *phy_regs,
+ dma_addr_t dev_addr)
+{
+ ltq_rcu_w32_mask(0, phy_regs->rd, RCU_RST_REQ);
+ ltq_rcu_w32(dev_addr, phy_regs->addr);
+ ltq_rcu_w32_mask(phy_regs->rd, 0, RCU_RST_REQ);
+}
+
/* reset and boot a gphy. these phys only exist on xrx200 SoC */
int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
{
@@ -86,23 +182,34 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
return -EINVAL;
}
- clk = clk_get_sys("1f203000.rcu", "gphy");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- clk_enable(clk);
-
- if (id > 1) {
- dev_err(dev, "%u is an invalid gphy id\n", id);
- return -EINVAL;
+ if (of_machine_is_compatible("lantiq,vr9")) {
+ clk = clk_get_sys("1f203000.rcu", "gphy");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clk_enable(clk);
}
+
dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
- RCU_RST_REQ);
- ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
- ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
- RCU_RST_REQ);
+ if (of_machine_is_compatible("lantiq,vr9")) {
+ if (id >= ARRAY_SIZE(xrx200_gphy)) {
+ dev_err(dev, "%u is an invalid gphy id\n", id);
+ return -EINVAL;
+ }
+ xrx200_gphy_boot_addr(&xrx200_gphy[id], dev_addr);
+ } else if (of_machine_is_compatible("lantiq,ar10")) {
+ if (id >= ARRAY_SIZE(xrx300_gphy)) {
+ dev_err(dev, "%u is an invalid gphy id\n", id);
+ return -EINVAL;
+ }
+ xrx200_gphy_boot_addr(&xrx300_gphy[id], dev_addr);
+ } else if (of_machine_is_compatible("lantiq,grx390")) {
+ if (id >= ARRAY_SIZE(xrx330_gphy)) {
+ dev_err(dev, "%u is an invalid gphy id\n", id);
+ return -EINVAL;
+ }
+ xrx200_gphy_boot_addr(&xrx330_gphy[id], dev_addr);
+ }
return 0;
}
@@ -200,6 +307,45 @@ static void ltq_machine_power_off(void)
unreachable();
}
+static void ltq_usb_init(void)
+{
+ /* Power for USB cores 1 & 2 */
+ ltq_pmu_enable(PMU_AHBM);
+ ltq_pmu_enable(PMU_USB0);
+ ltq_pmu_enable(PMU_USB1);
+
+ ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B);
+
+ /* Enable USB PHY power for cores 1 & 2 */
+ ltq_pmu_enable(PMU_USB0_P);
+ ltq_pmu_enable(PMU_USB1_P);
+
+ /* Configure cores to host mode */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT,
+ RCU_USB1CFG);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT,
+ RCU_USB2CFG);
+
+ /* Select DMA endianness (Host-endian: big-endian) */
+ ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT)
+ | RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG);
+ ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT)
+ | RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG);
+
+ /* Hard reset USB state machines */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET);
+ udelay(50 * 1000);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET);
+
+ /* Soft reset USB state machines */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+ | USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2);
+ udelay(50 * 1000);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+ & ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2);
+}
+
static int __init mips_reboot_setup(void)
{
struct resource res;
@@ -216,13 +362,21 @@ static int __init mips_reboot_setup(void)
if (of_address_to_resource(ltq_rcu_np, 0, &res))
panic("Failed to get rcu memory range");
- if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
+ if (!request_mem_region(res.start, resource_size(&res), res.name))
pr_err("Failed to request rcu memory");
ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
if (!ltq_rcu_membase)
panic("Failed to remap core memory");
+ if (of_machine_is_compatible("lantiq,ar9") ||
+ of_machine_is_compatible("lantiq,vr9"))
+ ltq_usb_init();
+
+ if (of_machine_is_compatible("lantiq,vr9"))
+ ltq_rcu_w32(ltq_rcu_r32(RCU_AHB_ENDIAN) | RCU_VR9_BE_AHB1S,
+ RCU_AHB_ENDIAN);
+
_machine_restart = ltq_machine_restart;
_machine_halt = ltq_machine_halt;
pm_power_off = ltq_machine_power_off;
diff --git a/kernel/arch/mips/lantiq/xway/sysctrl.c b/kernel/arch/mips/lantiq/xway/sysctrl.c
index 2b15491de..80554e8f6 100644
--- a/kernel/arch/mips/lantiq/xway/sysctrl.c
+++ b/kernel/arch/mips/lantiq/xway/sysctrl.c
@@ -4,11 +4,13 @@
* by the Free Software Foundation.
*
* Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
*/
#include <linux/ioport.h>
#include <linux/export.h>
#include <linux/clkdev.h>
+#include <linux/spinlock.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
@@ -18,16 +20,18 @@
#include "../clk.h"
#include "../prom.h"
-/* clock control register */
+/* clock control register for legacy */
#define CGU_IFCCR 0x0018
#define CGU_IFCCR_VR9 0x0024
-/* system clock register */
+/* system clock register for legacy */
#define CGU_SYS 0x0010
/* pci control register */
#define CGU_PCICR 0x0034
#define CGU_PCICR_VR9 0x0038
/* ephy configuration register */
#define CGU_EPHY 0x10
+
+/* Legacy PMU register for ar9, ase, danube */
/* power control register */
#define PMU_PWDCR 0x1C
/* power status register */
@@ -41,13 +45,56 @@
/* power status register */
#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
+
+/* PMU register for ar10 and grx390 */
+
+/* First register set */
+#define PMU_CLK_SR 0x20 /* status */
+#define PMU_CLK_CR_A 0x24 /* Enable */
+#define PMU_CLK_CR_B 0x28 /* Disable */
+/* Second register set */
+#define PMU_CLK_SR1 0x30 /* status */
+#define PMU_CLK_CR1_A 0x34 /* Enable */
+#define PMU_CLK_CR1_B 0x38 /* Disable */
+/* Third register set */
+#define PMU_ANA_SR 0x40 /* status */
+#define PMU_ANA_CR_A 0x44 /* Enable */
+#define PMU_ANA_CR_B 0x48 /* Disable */
+
+/* Status */
+static u32 pmu_clk_sr[] = {
+ PMU_CLK_SR,
+ PMU_CLK_SR1,
+ PMU_ANA_SR,
+};
+
+/* Enable */
+static u32 pmu_clk_cr_a[] = {
+ PMU_CLK_CR_A,
+ PMU_CLK_CR1_A,
+ PMU_ANA_CR_A,
+};
+
+/* Disable */
+static u32 pmu_clk_cr_b[] = {
+ PMU_CLK_CR_B,
+ PMU_CLK_CR1_B,
+ PMU_ANA_CR_B,
+};
+
+#define PWDCR_EN_XRX(x) (pmu_clk_cr_a[(x)])
+#define PWDCR_DIS_XRX(x) (pmu_clk_cr_b[(x)])
+#define PWDSR_XRX(x) (pmu_clk_sr[(x)])
+
/* clock gates that we can en/disable */
#define PMU_USB0_P BIT(0)
+#define PMU_ASE_SDIO BIT(2) /* ASE special */
#define PMU_PCI BIT(4)
#define PMU_DMA BIT(5)
#define PMU_USB0 BIT(6)
#define PMU_ASC0 BIT(7)
#define PMU_EPHY BIT(7) /* ase */
+#define PMU_USIF BIT(7) /* from vr9 until grx390 */
#define PMU_SPI BIT(8)
#define PMU_DFE BIT(9)
#define PMU_EBU BIT(10)
@@ -56,12 +103,15 @@
#define PMU_AHBS BIT(13) /* vr9 */
#define PMU_FPI BIT(14)
#define PMU_AHBM BIT(15)
+#define PMU_SDIO BIT(16) /* danube, ar9, vr9 */
#define PMU_ASC1 BIT(17)
#define PMU_PPE_QSB BIT(18)
#define PMU_PPE_SLL01 BIT(19)
+#define PMU_DEU BIT(20)
#define PMU_PPE_TC BIT(21)
#define PMU_PPE_EMA BIT(22)
#define PMU_PPE_DPLUM BIT(23)
+#define PMU_PPE_DP BIT(23)
#define PMU_PPE_DPLUS BIT(24)
#define PMU_USB1_P BIT(26)
#define PMU_USB1 BIT(27)
@@ -70,30 +120,59 @@
#define PMU_GPHY BIT(30)
#define PMU_PCIE_CLK BIT(31)
-#define PMU1_PCIE_PHY BIT(0)
+#define PMU1_PCIE_PHY BIT(0) /* vr9-specific,moved in ar10/grx390 */
#define PMU1_PCIE_CTL BIT(1)
#define PMU1_PCIE_PDI BIT(4)
#define PMU1_PCIE_MSI BIT(5)
+#define PMU1_CKE BIT(6)
+#define PMU1_PCIE1_CTL BIT(17)
+#define PMU1_PCIE1_PDI BIT(20)
+#define PMU1_PCIE1_MSI BIT(21)
+#define PMU1_PCIE2_CTL BIT(25)
+#define PMU1_PCIE2_PDI BIT(26)
+#define PMU1_PCIE2_MSI BIT(27)
+
+#define PMU_ANALOG_USB0_P BIT(0)
+#define PMU_ANALOG_USB1_P BIT(1)
+#define PMU_ANALOG_PCIE0_P BIT(8)
+#define PMU_ANALOG_PCIE1_P BIT(9)
+#define PMU_ANALOG_PCIE2_P BIT(10)
+#define PMU_ANALOG_DSL_AFE BIT(16)
+#define PMU_ANALOG_DCDC_2V5 BIT(17)
+#define PMU_ANALOG_DCDC_1VX BIT(18)
+#define PMU_ANALOG_DCDC_1V0 BIT(19)
#define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y))
#define pmu_r32(x) ltq_r32(pmu_membase + (x))
+#define XBAR_ALWAYS_LAST 0x430
+#define XBAR_FPI_BURST_EN BIT(1)
+#define XBAR_AHB_BURST_EN BIT(2)
+
+#define xbar_w32(x, y) ltq_w32((x), ltq_xbar_membase + (y))
+#define xbar_r32(x) ltq_r32(ltq_xbar_membase + (x))
+
static void __iomem *pmu_membase;
+static void __iomem *ltq_xbar_membase;
void __iomem *ltq_cgu_membase;
void __iomem *ltq_ebu_membase;
static u32 ifccr = CGU_IFCCR;
static u32 pcicr = CGU_PCICR;
+static DEFINE_SPINLOCK(g_pmu_lock);
+
/* legacy function kept alive to ease clkdev transition */
void ltq_pmu_enable(unsigned int module)
{
- int err = 1000000;
+ int retry = 1000000;
+ spin_lock(&g_pmu_lock);
pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
- do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
+ do {} while (--retry && (pmu_r32(PMU_PWDSR) & module));
+ spin_unlock(&g_pmu_lock);
- if (!err)
+ if (!retry)
panic("activating PMU module failed!");
}
EXPORT_SYMBOL(ltq_pmu_enable);
@@ -101,7 +180,15 @@ EXPORT_SYMBOL(ltq_pmu_enable);
/* legacy function kept alive to ease clkdev transition */
void ltq_pmu_disable(unsigned int module)
{
+ int retry = 1000000;
+
+ spin_lock(&g_pmu_lock);
pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
+ do {} while (--retry && (!(pmu_r32(PMU_PWDSR) & module)));
+ spin_unlock(&g_pmu_lock);
+
+ if (!retry)
+ pr_warn("deactivating PMU module failed!");
}
EXPORT_SYMBOL(ltq_pmu_disable);
@@ -123,9 +210,20 @@ static int pmu_enable(struct clk *clk)
{
int retry = 1000000;
- pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
- PWDCR(clk->module));
- do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
+ if (of_machine_is_compatible("lantiq,ar10")
+ || of_machine_is_compatible("lantiq,grx390")) {
+ pmu_w32(clk->bits, PWDCR_EN_XRX(clk->module));
+ do {} while (--retry &&
+ (!(pmu_r32(PWDSR_XRX(clk->module)) & clk->bits)));
+
+ } else {
+ spin_lock(&g_pmu_lock);
+ pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
+ PWDCR(clk->module));
+ do {} while (--retry &&
+ (pmu_r32(PWDSR(clk->module)) & clk->bits));
+ spin_unlock(&g_pmu_lock);
+ }
if (!retry)
panic("activating PMU module failed!");
@@ -136,8 +234,24 @@ static int pmu_enable(struct clk *clk)
/* disable a clock gate */
static void pmu_disable(struct clk *clk)
{
- pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
- PWDCR(clk->module));
+ int retry = 1000000;
+
+ if (of_machine_is_compatible("lantiq,ar10")
+ || of_machine_is_compatible("lantiq,grx390")) {
+ pmu_w32(clk->bits, PWDCR_DIS_XRX(clk->module));
+ do {} while (--retry &&
+ (pmu_r32(PWDSR_XRX(clk->module)) & clk->bits));
+ } else {
+ spin_lock(&g_pmu_lock);
+ pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
+ PWDCR(clk->module));
+ do {} while (--retry &&
+ (!(pmu_r32(PWDSR(clk->module)) & clk->bits)));
+ spin_unlock(&g_pmu_lock);
+ }
+
+ if (!retry)
+ pr_warn("deactivating PMU module failed!");
}
/* the pci enable helper */
@@ -179,6 +293,16 @@ static void pci_ext_disable(struct clk *clk)
ltq_cgu_w32((1 << 31) | (1 << 30), pcicr);
}
+static void xbar_fpi_burst_disable(void)
+{
+ u32 reg;
+
+ /* bit 1 as 1 --burst; bit 1 as 0 -- single */
+ reg = xbar_r32(XBAR_ALWAYS_LAST);
+ reg &= ~XBAR_FPI_BURST_EN;
+ xbar_w32(reg, XBAR_ALWAYS_LAST);
+}
+
/* enable a clockout source */
static int clkout_enable(struct clk *clk)
{
@@ -202,8 +326,8 @@ static int clkout_enable(struct clk *clk)
}
/* manage the clock gates via PMU */
-static void clkdev_add_pmu(const char *dev, const char *con,
- unsigned int module, unsigned int bits)
+static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate,
+ unsigned int module, unsigned int bits)
{
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
@@ -214,6 +338,13 @@ static void clkdev_add_pmu(const char *dev, const char *con,
clk->disable = pmu_disable;
clk->module = module;
clk->bits = bits;
+ if (deactivate) {
+ /*
+ * Disable it during the initialization. Module should enable
+ * when used
+ */
+ pmu_disable(clk);
+ }
clkdev_add(&clk->cl);
}
@@ -312,12 +443,12 @@ void __init ltq_soc_init(void)
of_address_to_resource(np_ebu, 0, &res_ebu))
panic("Failed to get core resources");
- if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
- res_pmu.name) < 0) ||
- (request_mem_region(res_cgu.start, resource_size(&res_cgu),
- res_cgu.name) < 0) ||
- (request_mem_region(res_ebu.start, resource_size(&res_ebu),
- res_ebu.name) < 0))
+ if (!request_mem_region(res_pmu.start, resource_size(&res_pmu),
+ res_pmu.name) ||
+ !request_mem_region(res_cgu.start, resource_size(&res_cgu),
+ res_cgu.name) ||
+ !request_mem_region(res_ebu.start, resource_size(&res_ebu),
+ res_ebu.name))
pr_err("Failed to request core resources");
pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
@@ -328,17 +459,37 @@ void __init ltq_soc_init(void)
if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
panic("Failed to remap core resources");
+ if (of_machine_is_compatible("lantiq,vr9")) {
+ struct resource res_xbar;
+ struct device_node *np_xbar =
+ of_find_compatible_node(NULL, NULL,
+ "lantiq,xbar-xway");
+
+ if (!np_xbar)
+ panic("Failed to load xbar nodes from devicetree");
+ if (of_address_to_resource(np_pmu, 0, &res_xbar))
+ panic("Failed to get xbar resources");
+ if (request_mem_region(res_xbar.start, resource_size(&res_xbar),
+ res_xbar.name) < 0)
+ panic("Failed to get xbar resources");
+
+ ltq_xbar_membase = ioremap_nocache(res_xbar.start,
+ resource_size(&res_xbar));
+ if (!ltq_xbar_membase)
+ panic("Failed to remap xbar resources");
+ }
+
/* make sure to unprotect the memory region where flash is located */
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
/* add our generic xway clocks */
- clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
- clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
- clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
- clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
- clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
- clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
- clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
+ clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI);
+ clkdev_add_pmu("1e100400.serial", NULL, 0, 0, PMU_ASC0);
+ clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT);
+ clkdev_add_pmu("1e100bb0.stp", NULL, 1, 0, PMU_STP);
+ clkdev_add_pmu("1e104100.dma", NULL, 1, 0, PMU_DMA);
+ clkdev_add_pmu("1e100800.spi", NULL, 1, 0, PMU_SPI);
+ clkdev_add_pmu("1e105300.ebu", NULL, 0, 0, PMU_EBU);
clkdev_add_clkout();
/* add the soc dependent clocks */
@@ -346,14 +497,30 @@ void __init ltq_soc_init(void)
ifccr = CGU_IFCCR_VR9;
pcicr = CGU_PCICR_VR9;
} else {
- clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
+ clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE);
}
if (!of_machine_is_compatible("lantiq,ase")) {
- clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
+ clkdev_add_pmu("1e100c00.serial", NULL, 0, 0, PMU_ASC1);
clkdev_add_pci();
}
+ if (of_machine_is_compatible("lantiq,grx390") ||
+ of_machine_is_compatible("lantiq,ar10")) {
+ clkdev_add_pmu("1e101000.usb", "phy", 1, 2, PMU_ANALOG_USB0_P);
+ clkdev_add_pmu("1e106000.usb", "phy", 1, 2, PMU_ANALOG_USB1_P);
+ /* rc 0 */
+ clkdev_add_pmu("1d900000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE0_P);
+ clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+ clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+ clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+ /* rc 1 */
+ clkdev_add_pmu("19000000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE1_P);
+ clkdev_add_pmu("19000000.pcie", "msi", 1, 1, PMU1_PCIE1_MSI);
+ clkdev_add_pmu("19000000.pcie", "pdi", 1, 1, PMU1_PCIE1_PDI);
+ clkdev_add_pmu("19000000.pcie", "ctl", 1, 1, PMU1_PCIE1_CTL);
+ }
+
if (of_machine_is_compatible("lantiq,ase")) {
if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
clkdev_add_static(CLOCK_266M, CLOCK_133M,
@@ -361,28 +528,84 @@ void __init ltq_soc_init(void)
else
clkdev_add_static(CLOCK_133M, CLOCK_133M,
CLOCK_133M, CLOCK_133M);
- clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
- clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+ clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+ clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE);
+ clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY);
+ clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY);
+ clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO);
+ clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+ } else if (of_machine_is_compatible("lantiq,grx390")) {
+ clkdev_add_static(ltq_grx390_cpu_hz(), ltq_grx390_fpi_hz(),
+ ltq_grx390_fpi_hz(), ltq_grx390_pp32_hz());
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+ clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+ /* rc 2 */
+ clkdev_add_pmu("1a800000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE2_P);
+ clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
+ clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
+ clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
+ clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP);
+ clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+ clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+ } else if (of_machine_is_compatible("lantiq,ar10")) {
+ clkdev_add_static(ltq_ar10_cpu_hz(), ltq_ar10_fpi_hz(),
+ ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+ clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+ clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH |
+ PMU_PPE_DP | PMU_PPE_TC);
+ clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+ clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+ clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+ clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
+ clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
} else if (of_machine_is_compatible("lantiq,vr9")) {
clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());
- clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
- clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
- clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
- clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
- clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
- clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
- clkdev_add_pmu("1e108000.eth", NULL, 0,
+ clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0 | PMU_AHBM);
+ clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+ clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1 | PMU_AHBM);
+ clkdev_add_pmu("1d900000.pcie", "phy", 1, 1, PMU1_PCIE_PHY);
+ clkdev_add_pmu("1d900000.pcie", "bus", 1, 0, PMU_PCIE_CLK);
+ clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+ clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+ clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+ clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
+
+ clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+ clkdev_add_pmu("1e108000.eth", NULL, 1, 0,
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
PMU_PPE_QSB | PMU_PPE_TOP);
- clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
+ clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+ clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+ clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+ clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz(), CLOCK_250M);
- clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+ clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+ clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+ clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+ clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH);
+ clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+ clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+ clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+ clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
} else {
clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
+ clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+ clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+ clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+ clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+ clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+ clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
}
+
+ if (of_machine_is_compatible("lantiq,vr9"))
+ xbar_fpi_burst_disable();
}
diff --git a/kernel/arch/mips/lasat/sysctl.c b/kernel/arch/mips/lasat/sysctl.c
index a57959e64..c710d9699 100644
--- a/kernel/arch/mips/lasat/sysctl.c
+++ b/kernel/arch/mips/lasat/sysctl.c
@@ -270,4 +270,4 @@ static int __init lasat_register_sysctl(void)
return 0;
}
-__initcall(lasat_register_sysctl);
+arch_initcall(lasat_register_sysctl);
diff --git a/kernel/arch/mips/lib/Makefile b/kernel/arch/mips/lib/Makefile
index 1e9e900cd..0344e575f 100644
--- a/kernel/arch/mips/lib/Makefile
+++ b/kernel/arch/mips/lib/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
# libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
diff --git a/kernel/arch/mips/lib/bswapdi.c b/kernel/arch/mips/lib/bswapdi.c
new file mode 100644
index 000000000..77e5f9c1f
--- /dev/null
+++ b/kernel/arch/mips/lib/bswapdi.c
@@ -0,0 +1,15 @@
+#include <linux/module.h>
+
+unsigned long long __bswapdi2(unsigned long long u)
+{
+ return (((u) & 0xff00000000000000ull) >> 56) |
+ (((u) & 0x00ff000000000000ull) >> 40) |
+ (((u) & 0x0000ff0000000000ull) >> 24) |
+ (((u) & 0x000000ff00000000ull) >> 8) |
+ (((u) & 0x00000000ff000000ull) << 8) |
+ (((u) & 0x0000000000ff0000ull) << 24) |
+ (((u) & 0x000000000000ff00ull) << 40) |
+ (((u) & 0x00000000000000ffull) << 56);
+}
+
+EXPORT_SYMBOL(__bswapdi2);
diff --git a/kernel/arch/mips/lib/bswapsi.c b/kernel/arch/mips/lib/bswapsi.c
new file mode 100644
index 000000000..2b302ff12
--- /dev/null
+++ b/kernel/arch/mips/lib/bswapsi.c
@@ -0,0 +1,11 @@
+#include <linux/module.h>
+
+unsigned int __bswapsi2(unsigned int u)
+{
+ return (((u) & 0xff000000) >> 24) |
+ (((u) & 0x00ff0000) >> 8) |
+ (((u) & 0x0000ff00) << 8) |
+ (((u) & 0x000000ff) << 24);
+}
+
+EXPORT_SYMBOL(__bswapsi2);
diff --git a/kernel/arch/mips/lib/dump_tlb.c b/kernel/arch/mips/lib/dump_tlb.c
index 32b9f21bf..92a37319e 100644
--- a/kernel/arch/mips/lib/dump_tlb.c
+++ b/kernel/arch/mips/lib/dump_tlb.c
@@ -7,11 +7,39 @@
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <asm/hazards.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/tlbdebug.h>
+void dump_tlb_regs(void)
+{
+ const int field = 2 * sizeof(unsigned long);
+
+ pr_info("Index : %0x\n", read_c0_index());
+ pr_info("PageMask : %0x\n", read_c0_pagemask());
+ pr_info("EntryHi : %0*lx\n", field, read_c0_entryhi());
+ pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
+ pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
+ pr_info("Wired : %0x\n", read_c0_wired());
+ switch (current_cpu_type()) {
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_R14000:
+ case CPU_R16000:
+ pr_info("FrameMask: %0x\n", read_c0_framemask());
+ break;
+ }
+ if (cpu_has_small_pages || cpu_has_rixi || cpu_has_xpa)
+ pr_info("PageGrain: %0x\n", read_c0_pagegrain());
+ if (cpu_has_htw) {
+ pr_info("PWField : %0*lx\n", field, read_c0_pwfield());
+ pr_info("PWSize : %0*lx\n", field, read_c0_pwsize());
+ pr_info("PWCtl : %0x\n", read_c0_pwctl());
+ }
+}
+
static inline const char *msk2str(unsigned int mask)
{
switch (mask) {
@@ -40,17 +68,20 @@ static inline const char *msk2str(unsigned int mask)
return "";
}
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
static void dump_tlb(int first, int last)
{
unsigned long s_entryhi, entryhi, asid;
- unsigned long long entrylo0, entrylo1;
+ unsigned long long entrylo0, entrylo1, pa;
unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
+#ifdef CONFIG_32BIT
+ bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
+ int pwidth = xpa ? 11 : 8;
+ int vwidth = 8;
+#else
+ bool xpa = false;
+ int pwidth = 11;
+ int vwidth = 11;
+#endif
s_pagemask = read_c0_pagemask();
s_entryhi = read_c0_entryhi();
@@ -59,46 +90,74 @@ static void dump_tlb(int first, int last)
for (i = first; i <= last; i++) {
write_c0_index(i);
- BARRIER();
+ mtc0_tlbr_hazard();
tlb_read();
- BARRIER();
+ tlb_read_hazard();
pagemask = read_c0_pagemask();
entryhi = read_c0_entryhi();
entrylo0 = read_c0_entrylo0();
entrylo1 = read_c0_entrylo1();
- /* Unused entries have a virtual address of CKSEG0. */
- if ((entryhi & ~0x1ffffUL) != CKSEG0
- && (entryhi & 0xff) == asid) {
-#ifdef CONFIG_32BIT
- int width = 8;
-#else
- int width = 11;
-#endif
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+ /* EHINV bit marks entire entry as invalid */
+ if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
+ continue;
+ /*
+ * Prior to tlbinv, unused entries have a virtual address of
+ * CKSEG0.
+ */
+ if ((entryhi & ~0x1ffffUL) == CKSEG0)
+ continue;
+ /*
+ * ASID takes effect in absence of G (global) bit.
+ * We check both G bits, even though architecturally they should
+ * match one another, because some revisions of the SB1 core may
+ * leave only a single G bit set after a machine check exception
+ * due to duplicate TLB entry.
+ */
+ if (!((entrylo0 | entrylo1) & ENTRYLO_G) &&
+ (entryhi & 0xff) != asid)
+ continue;
+
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
+ c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
+ c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
- printk("va=%0*lx asid=%02lx\n",
- width, (entryhi & ~0x1fffUL),
- entryhi & 0xff);
- printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
- width,
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0,
- (entrylo0 & 1) ? 1 : 0);
- printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
- width,
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0,
- (entrylo1 & 1) ? 1 : 0);
- }
+ printk("va=%0*lx asid=%02lx\n",
+ vwidth, (entryhi & ~0x1fffUL),
+ entryhi & 0xff);
+ /* RI/XI are in awkward places, so mask them off separately */
+ pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+ if (xpa)
+ pa |= (unsigned long long)readx_c0_entrylo0() << 30;
+ pa = (pa << 6) & PAGE_MASK;
+ printk("\t[");
+ if (cpu_has_rixi)
+ printk("ri=%d xi=%d ",
+ (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0,
+ (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0);
+ printk("pa=%0*llx c=%d d=%d v=%d g=%d] [",
+ pwidth, pa, c0,
+ (entrylo0 & ENTRYLO_D) ? 1 : 0,
+ (entrylo0 & ENTRYLO_V) ? 1 : 0,
+ (entrylo0 & ENTRYLO_G) ? 1 : 0);
+ /* RI/XI are in awkward places, so mask them off separately */
+ pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+ if (xpa)
+ pa |= (unsigned long long)readx_c0_entrylo1() << 30;
+ pa = (pa << 6) & PAGE_MASK;
+ if (cpu_has_rixi)
+ printk("ri=%d xi=%d ",
+ (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0,
+ (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0);
+ printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n",
+ pwidth, pa, c1,
+ (entrylo1 & ENTRYLO_D) ? 1 : 0,
+ (entrylo1 & ENTRYLO_V) ? 1 : 0,
+ (entrylo1 & ENTRYLO_G) ? 1 : 0);
}
printk("\n");
diff --git a/kernel/arch/mips/lib/memset.S b/kernel/arch/mips/lib/memset.S
index b8e63fd00..8f0019a2e 100644
--- a/kernel/arch/mips/lib/memset.S
+++ b/kernel/arch/mips/lib/memset.S
@@ -283,6 +283,8 @@ LEAF(memset)
1:
#ifndef CONFIG_EVA
FEXPORT(__bzero)
+#else
+FEXPORT(__bzero_kernel)
#endif
__BUILD_BZERO LEGACY_MODE
diff --git a/kernel/arch/mips/lib/r3k_dump_tlb.c b/kernel/arch/mips/lib/r3k_dump_tlb.c
index 975a13855..cfcbb5218 100644
--- a/kernel/arch/mips/lib/r3k_dump_tlb.c
+++ b/kernel/arch/mips/lib/r3k_dump_tlb.c
@@ -14,7 +14,16 @@
#include <asm/pgtable.h>
#include <asm/tlbdebug.h>
-extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
+extern int r3k_have_wired_reg;
+
+void dump_tlb_regs(void)
+{
+ pr_info("Index : %0x\n", read_c0_index());
+ pr_info("EntryHi : %0lx\n", read_c0_entryhi());
+ pr_info("EntryLo : %0lx\n", read_c0_entrylo0());
+ if (r3k_have_wired_reg)
+ pr_info("Wired : %0x\n", read_c0_wired());
+}
static void dump_tlb(int first, int last)
{
@@ -35,8 +44,9 @@ static void dump_tlb(int first, int last)
entrylo0 = read_c0_entrylo0();
/* Unused entries have a virtual address of KSEG0. */
- if ((entryhi & PAGE_MASK) != KSEG0
- && (entryhi & ASID_MASK) == asid) {
+ if ((entryhi & PAGE_MASK) != KSEG0 &&
+ (entrylo0 & R3K_ENTRYLO_G ||
+ (entryhi & ASID_MASK) == asid)) {
/*
* Only print entries in use
*/
@@ -47,10 +57,10 @@ static void dump_tlb(int first, int last)
entryhi & PAGE_MASK,
entryhi & ASID_MASK,
entrylo0 & PAGE_MASK,
- (entrylo0 & (1 << 11)) ? 1 : 0,
- (entrylo0 & (1 << 10)) ? 1 : 0,
- (entrylo0 & (1 << 9)) ? 1 : 0,
- (entrylo0 & (1 << 8)) ? 1 : 0);
+ (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0,
+ (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0,
+ (entrylo0 & R3K_ENTRYLO_V) ? 1 : 0,
+ (entrylo0 & R3K_ENTRYLO_G) ? 1 : 0);
}
}
printk("\n");
diff --git a/kernel/arch/mips/loongson1/Kconfig b/kernel/arch/mips/loongson32/Kconfig
index a2b796eaf..7704f2052 100644
--- a/kernel/arch/mips/loongson1/Kconfig
+++ b/kernel/arch/mips/loongson32/Kconfig
@@ -1,4 +1,4 @@
-if MACH_LOONGSON1
+if MACH_LOONGSON32
choice
prompt "Machine Type"
@@ -10,7 +10,7 @@ config LOONGSON1_LS1B
select SYS_HAS_CPU_LOONGSON1B
select DMA_NONCOHERENT
select BOOT_ELF32
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
@@ -58,4 +58,4 @@ config TIMER_USE_PWM3
endchoice
-endif # MACH_LOONGSON1
+endif # MACH_LOONGSON32
diff --git a/kernel/arch/mips/loongson1/Makefile b/kernel/arch/mips/loongson32/Makefile
index 9719c7588..5f4bd6e07 100644
--- a/kernel/arch/mips/loongson1/Makefile
+++ b/kernel/arch/mips/loongson32/Makefile
@@ -2,7 +2,7 @@
# Common code for all Loongson 1 based systems
#
-obj-$(CONFIG_MACH_LOONGSON1) += common/
+obj-$(CONFIG_MACH_LOONGSON32) += common/
#
# Loongson LS1B board
diff --git a/kernel/arch/mips/loongson1/Platform b/kernel/arch/mips/loongson32/Platform
index 11863441d..ebb6dc290 100644
--- a/kernel/arch/mips/loongson1/Platform
+++ b/kernel/arch/mips/loongson32/Platform
@@ -2,6 +2,6 @@ cflags-$(CONFIG_CPU_LOONGSON1) += \
$(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32r2 -Wa,--trap
-platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
-cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1
+platform-$(CONFIG_MACH_LOONGSON32) += loongson32/
+cflags-$(CONFIG_MACH_LOONGSON32) += -I$(srctree)/arch/mips/include/asm/mach-loongson32
load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80100000
diff --git a/kernel/arch/mips/loongson1/common/Makefile b/kernel/arch/mips/loongson32/common/Makefile
index 723b4ce3b..723b4ce3b 100644
--- a/kernel/arch/mips/loongson1/common/Makefile
+++ b/kernel/arch/mips/loongson32/common/Makefile
diff --git a/kernel/arch/mips/loongson1/common/irq.c b/kernel/arch/mips/loongson32/common/irq.c
index 455a7704a..455a7704a 100644
--- a/kernel/arch/mips/loongson1/common/irq.c
+++ b/kernel/arch/mips/loongson32/common/irq.c
diff --git a/kernel/arch/mips/loongson1/common/platform.c b/kernel/arch/mips/loongson32/common/platform.c
index ddf1d4cbf..ddf1d4cbf 100644
--- a/kernel/arch/mips/loongson1/common/platform.c
+++ b/kernel/arch/mips/loongson32/common/platform.c
diff --git a/kernel/arch/mips/loongson1/common/prom.c b/kernel/arch/mips/loongson32/common/prom.c
index 68600980e..68600980e 100644
--- a/kernel/arch/mips/loongson1/common/prom.c
+++ b/kernel/arch/mips/loongson32/common/prom.c
diff --git a/kernel/arch/mips/loongson1/common/reset.c b/kernel/arch/mips/loongson32/common/reset.c
index c41e4ca56..c41e4ca56 100644
--- a/kernel/arch/mips/loongson1/common/reset.c
+++ b/kernel/arch/mips/loongson32/common/reset.c
diff --git a/kernel/arch/mips/loongson1/common/setup.c b/kernel/arch/mips/loongson32/common/setup.c
index 62f41afee..62f41afee 100644
--- a/kernel/arch/mips/loongson1/common/setup.c
+++ b/kernel/arch/mips/loongson32/common/setup.c
diff --git a/kernel/arch/mips/loongson1/common/time.c b/kernel/arch/mips/loongson32/common/time.c
index df0f850d6..0996b025e 100644
--- a/kernel/arch/mips/loongson1/common/time.c
+++ b/kernel/arch/mips/loongson32/common/time.c
@@ -126,26 +126,34 @@ static irqreturn_t ls1x_clockevent_isr(int irq, void *devid)
return IRQ_HANDLED;
}
-static void ls1x_clockevent_set_mode(enum clock_event_mode mode,
- struct clock_event_device *cd)
+static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd)
{
raw_spin_lock(&ls1x_timer_lock);
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
- ls1x_pwmtimer_restart();
- case CLOCK_EVT_MODE_RESUME:
- __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
- timer_base + PWM_CTRL);
- break;
- default:
- break;
- }
+ ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
+ ls1x_pwmtimer_restart();
+ __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static int ls1x_clockevent_tick_resume(struct clock_event_device *cd)
+{
+ raw_spin_lock(&ls1x_timer_lock);
+ __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
+}
+
+static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd)
+{
+ raw_spin_lock(&ls1x_timer_lock);
+ __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
+ timer_base + PWM_CTRL);
+ raw_spin_unlock(&ls1x_timer_lock);
+
+ return 0;
}
static int ls1x_clockevent_set_next(unsigned long evt,
@@ -160,12 +168,15 @@ static int ls1x_clockevent_set_next(unsigned long evt,
}
static struct clock_event_device ls1x_clockevent = {
- .name = "ls1x-pwmtimer",
- .features = CLOCK_EVT_FEAT_PERIODIC,
- .rating = 300,
- .irq = LS1X_TIMER_IRQ,
- .set_next_event = ls1x_clockevent_set_next,
- .set_mode = ls1x_clockevent_set_mode,
+ .name = "ls1x-pwmtimer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .rating = 300,
+ .irq = LS1X_TIMER_IRQ,
+ .set_next_event = ls1x_clockevent_set_next,
+ .set_state_shutdown = ls1x_clockevent_set_state_shutdown,
+ .set_state_periodic = ls1x_clockevent_set_state_periodic,
+ .set_state_oneshot = ls1x_clockevent_set_state_shutdown,
+ .tick_resume = ls1x_clockevent_tick_resume,
};
static struct irqaction ls1x_pwmtimer_irqaction = {
diff --git a/kernel/arch/mips/loongson1/ls1b/Makefile b/kernel/arch/mips/loongson32/ls1b/Makefile
index 891eac482..891eac482 100644
--- a/kernel/arch/mips/loongson1/ls1b/Makefile
+++ b/kernel/arch/mips/loongson32/ls1b/Makefile
diff --git a/kernel/arch/mips/loongson1/ls1b/board.c b/kernel/arch/mips/loongson32/ls1b/board.c
index 58daeea25..58daeea25 100644
--- a/kernel/arch/mips/loongson1/ls1b/board.c
+++ b/kernel/arch/mips/loongson32/ls1b/board.c
diff --git a/kernel/arch/mips/loongson/Kconfig b/kernel/arch/mips/loongson64/Kconfig
index 156de85b8..8e6e29267 100644
--- a/kernel/arch/mips/loongson/Kconfig
+++ b/kernel/arch/mips/loongson64/Kconfig
@@ -1,4 +1,4 @@
-if MACH_LOONGSON
+if MACH_LOONGSON64
choice
prompt "Machine Type"
@@ -15,7 +15,7 @@ config LEMOTE_FULOONG2E
select HW_HAS_PCI
select I8259
select ISA
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -44,7 +44,7 @@ config LEMOTE_MACH2F
select HAVE_CLK
select HW_HAS_PCI
select I8259
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ISA
select SYS_HAS_CPU_LOONGSON2F
select SYS_HAS_EARLY_PRINTK
@@ -73,7 +73,7 @@ config LOONGSON_MACH3X
select ISA
select HT_PCI
select I8259
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select NR_CPUS_DEFAULT_4
select SYS_HAS_CPU_LOONGSON3
select SYS_HAS_EARLY_PRINTK
@@ -120,11 +120,6 @@ config RS780_HPET
If unsure, say Yes.
-config LOONGSON_SUSPEND
- bool
- default y
- depends on CPU_SUPPORTS_CPUFREQ && SUSPEND
-
config LOONGSON_UART_BASE
bool
default y
@@ -155,4 +150,4 @@ config LOONGSON_MC146818
config LEFI_FIRMWARE_INTERFACE
bool
-endif # MACH_LOONGSON
+endif # MACH_LOONGSON64
diff --git a/kernel/arch/mips/loongson/Makefile b/kernel/arch/mips/loongson64/Makefile
index 7429994e7..4fe3d88fc 100644
--- a/kernel/arch/mips/loongson/Makefile
+++ b/kernel/arch/mips/loongson64/Makefile
@@ -2,7 +2,7 @@
# Common code for all Loongson based systems
#
-obj-$(CONFIG_MACH_LOONGSON) += common/
+obj-$(CONFIG_MACH_LOONGSON64) += common/
#
# Lemote Fuloong mini-PC (Loongson 2E-based)
diff --git a/kernel/arch/mips/loongson/Platform b/kernel/arch/mips/loongson64/Platform
index 0ac20eb84..2e48e83d5 100644
--- a/kernel/arch/mips/loongson/Platform
+++ b/kernel/arch/mips/loongson64/Platform
@@ -26,8 +26,8 @@ endif
# Loongson Machines' Support
#
-platform-$(CONFIG_MACH_LOONGSON) += loongson/
-cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
+platform-$(CONFIG_MACH_LOONGSON64) += loongson64/
+cflags-$(CONFIG_MACH_LOONGSON64) += -I$(srctree)/arch/mips/include/asm/mach-loongson64 -mno-branch-likely
load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
diff --git a/kernel/arch/mips/loongson/common/Makefile b/kernel/arch/mips/loongson64/common/Makefile
index f2e8153e4..074d9cb15 100644
--- a/kernel/arch/mips/loongson/common/Makefile
+++ b/kernel/arch/mips/loongson64/common/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_CS5536) += cs5536/
# Suspend Support
#
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
#
# Big Memory (SWIOTLB) Support
diff --git a/kernel/arch/mips/loongson/common/bonito-irq.c b/kernel/arch/mips/loongson64/common/bonito-irq.c
index cc0e4fd54..4e116d23b 100644
--- a/kernel/arch/mips/loongson/common/bonito-irq.c
+++ b/kernel/arch/mips/loongson64/common/bonito-irq.c
@@ -3,7 +3,7 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
* Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/kernel/arch/mips/loongson/common/cmdline.c b/kernel/arch/mips/loongson64/common/cmdline.c
index 72fed003a..01fbed137 100644
--- a/kernel/arch/mips/loongson/common/cmdline.c
+++ b/kernel/arch/mips/loongson64/common/cmdline.c
@@ -6,7 +6,7 @@
* Copyright 2003 ICT CAS
* Author: Michael Guo <guoyi@ict.ac.cn>
*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* Copyright (C) 2009 Lemote Inc.
diff --git a/kernel/arch/mips/loongson/common/cs5536/Makefile b/kernel/arch/mips/loongson64/common/cs5536/Makefile
index f12e64007..f12e64007 100644
--- a/kernel/arch/mips/loongson/common/cs5536/Makefile
+++ b/kernel/arch/mips/loongson64/common/cs5536/Makefile
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_acc.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_acc.c
index ab4d6cc57..ab4d6cc57 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_acc.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_acc.c
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ehci.c
index ec2e36026..ec2e36026 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_ehci.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ehci.c
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_ide.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ide.c
index a73414d9e..a73414d9e 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_ide.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ide.c
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_isa.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_isa.c
index 924be39e7..924be39e7 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_isa.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_isa.c
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c
index 12c75db23..da77d4125 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c
@@ -1,7 +1,7 @@
/*
* CS5536 General timer functions
*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Yanhua, yanh@lemote.com
*
* Copyright (C) 2009 Lemote Inc.
@@ -51,40 +51,36 @@ void enable_mfgpt0_counter(void)
}
EXPORT_SYMBOL(enable_mfgpt0_counter);
-static void init_mfgpt_timer(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int mfgpt_timer_set_periodic(struct clock_event_device *evt)
{
raw_spin_lock(&mfgpt_lock);
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- outw(COMPARE, MFGPT0_CMP2); /* set comparator2 */
- outw(0, MFGPT0_CNT); /* set counter to 0 */
- enable_mfgpt0_counter();
- break;
-
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
- evt->mode == CLOCK_EVT_MODE_ONESHOT)
- disable_mfgpt0_counter();
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* The oneshot mode have very high deviation, Not use it! */
- break;
-
- case CLOCK_EVT_MODE_RESUME:
- /* Nothing to do here */
- break;
- }
+ outw(COMPARE, MFGPT0_CMP2); /* set comparator2 */
+ outw(0, MFGPT0_CNT); /* set counter to 0 */
+ enable_mfgpt0_counter();
+
raw_spin_unlock(&mfgpt_lock);
+ return 0;
+}
+
+static int mfgpt_timer_shutdown(struct clock_event_device *evt)
+{
+ if (clockevent_state_periodic(evt) || clockevent_state_oneshot(evt)) {
+ raw_spin_lock(&mfgpt_lock);
+ disable_mfgpt0_counter();
+ raw_spin_unlock(&mfgpt_lock);
+ }
+
+ return 0;
}
static struct clock_event_device mfgpt_clockevent = {
.name = "mfgpt",
.features = CLOCK_EVT_FEAT_PERIODIC,
- .set_mode = init_mfgpt_timer,
+
+ /* The oneshot mode have very high deviation, don't use it! */
+ .set_state_shutdown = mfgpt_timer_shutdown,
+ .set_state_periodic = mfgpt_timer_set_periodic,
.irq = CS5536_MFGPT_INTR,
};
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ohci.c
index f7c905e50..f7c905e50 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_ohci.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_ohci.c
diff --git a/kernel/arch/mips/loongson/common/cs5536/cs5536_pci.c b/kernel/arch/mips/loongson64/common/cs5536/cs5536_pci.c
index b73972320..b73972320 100644
--- a/kernel/arch/mips/loongson/common/cs5536/cs5536_pci.c
+++ b/kernel/arch/mips/loongson64/common/cs5536/cs5536_pci.c
diff --git a/kernel/arch/mips/loongson/common/dma-swiotlb.c b/kernel/arch/mips/loongson64/common/dma-swiotlb.c
index 2c6b989c1..4ffa6fc81 100644
--- a/kernel/arch/mips/loongson/common/dma-swiotlb.c
+++ b/kernel/arch/mips/loongson64/common/dma-swiotlb.c
@@ -14,9 +14,6 @@ static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
{
void *ret;
- if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
- return ret;
-
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
@@ -46,11 +43,6 @@ static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
static void loongson_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
{
- int order = get_order(size);
-
- if (dma_release_from_coherent(dev, order, vaddr))
- return;
-
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
@@ -93,6 +85,9 @@ static void loongson_dma_sync_sg_for_device(struct device *dev,
static int loongson_dma_set_mask(struct device *dev, u64 mask)
{
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+
if (mask > DMA_BIT_MASK(loongson_sysconf.dma_mask_bits)) {
*dev->dma_mask = DMA_BIT_MASK(loongson_sysconf.dma_mask_bits);
return -EIO;
diff --git a/kernel/arch/mips/loongson/common/early_printk.c b/kernel/arch/mips/loongson64/common/early_printk.c
index 6ca632e52..6ca632e52 100644
--- a/kernel/arch/mips/loongson/common/early_printk.c
+++ b/kernel/arch/mips/loongson64/common/early_printk.c
diff --git a/kernel/arch/mips/loongson/common/env.c b/kernel/arch/mips/loongson64/common/env.c
index 22f04ca2f..d6d07ad56 100644
--- a/kernel/arch/mips/loongson/common/env.c
+++ b/kernel/arch/mips/loongson64/common/env.c
@@ -6,7 +6,7 @@
* Copyright 2003 ICT CAS
* Author: Michael Guo <guoyi@ict.ac.cn>
*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* Copyright (C) 2009 Lemote Inc.
@@ -64,6 +64,9 @@ void __init prom_init_env(void)
}
if (memsize == 0)
memsize = 256;
+
+ loongson_sysconf.nr_uarts = 1;
+
pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize);
#else
struct boot_params *boot_p;
diff --git a/kernel/arch/mips/loongson/common/init.c b/kernel/arch/mips/loongson64/common/init.c
index 9b987fe98..9b987fe98 100644
--- a/kernel/arch/mips/loongson/common/init.c
+++ b/kernel/arch/mips/loongson64/common/init.c
diff --git a/kernel/arch/mips/loongson/common/irq.c b/kernel/arch/mips/loongson64/common/irq.c
index 687003b19..d36d969a4 100644
--- a/kernel/arch/mips/loongson/common/irq.c
+++ b/kernel/arch/mips/loongson64/common/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/kernel/arch/mips/loongson/common/machtype.c b/kernel/arch/mips/loongson64/common/machtype.c
index f2807bc66..f2807bc66 100644
--- a/kernel/arch/mips/loongson/common/machtype.c
+++ b/kernel/arch/mips/loongson64/common/machtype.c
diff --git a/kernel/arch/mips/loongson/common/mem.c b/kernel/arch/mips/loongson64/common/mem.c
index b01d52473..b01d52473 100644
--- a/kernel/arch/mips/loongson/common/mem.c
+++ b/kernel/arch/mips/loongson64/common/mem.c
diff --git a/kernel/arch/mips/loongson/common/pci.c b/kernel/arch/mips/loongson64/common/pci.c
index 4e2575643..4e2575643 100644
--- a/kernel/arch/mips/loongson/common/pci.c
+++ b/kernel/arch/mips/loongson64/common/pci.c
diff --git a/kernel/arch/mips/loongson/common/platform.c b/kernel/arch/mips/loongson64/common/platform.c
index 0ed38321a..0ed38321a 100644
--- a/kernel/arch/mips/loongson/common/platform.c
+++ b/kernel/arch/mips/loongson64/common/platform.c
diff --git a/kernel/arch/mips/loongson/common/pm.c b/kernel/arch/mips/loongson64/common/pm.c
index a6b67ccfc..a6b67ccfc 100644
--- a/kernel/arch/mips/loongson/common/pm.c
+++ b/kernel/arch/mips/loongson64/common/pm.c
diff --git a/kernel/arch/mips/loongson/common/reset.c b/kernel/arch/mips/loongson64/common/reset.c
index a60715e11..a60715e11 100644
--- a/kernel/arch/mips/loongson/common/reset.c
+++ b/kernel/arch/mips/loongson64/common/reset.c
diff --git a/kernel/arch/mips/loongson/common/rtc.c b/kernel/arch/mips/loongson64/common/rtc.c
index b5709af09..b5709af09 100644
--- a/kernel/arch/mips/loongson/common/rtc.c
+++ b/kernel/arch/mips/loongson64/common/rtc.c
diff --git a/kernel/arch/mips/loongson/common/serial.c b/kernel/arch/mips/loongson64/common/serial.c
index c23fa1373..ffefc1cb2 100644
--- a/kernel/arch/mips/loongson/common/serial.c
+++ b/kernel/arch/mips/loongson64/common/serial.c
@@ -11,7 +11,7 @@
*/
#include <linux/io.h>
-#include <linux/init.h>
+#include <linux/module.h>
#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
@@ -108,5 +108,10 @@ static int __init serial_init(void)
return platform_device_register(&uart8250_device);
}
+module_init(serial_init);
-device_initcall(serial_init);
+static void __init serial_exit(void)
+{
+ platform_device_unregister(&uart8250_device);
+}
+module_exit(serial_exit);
diff --git a/kernel/arch/mips/loongson/common/setup.c b/kernel/arch/mips/loongson64/common/setup.c
index d477dd6bb..2dc5122f0 100644
--- a/kernel/arch/mips/loongson/common/setup.c
+++ b/kernel/arch/mips/loongson64/common/setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/kernel/arch/mips/loongson/common/time.c b/kernel/arch/mips/loongson64/common/time.c
index e1a5382ad..e1a5382ad 100644
--- a/kernel/arch/mips/loongson/common/time.c
+++ b/kernel/arch/mips/loongson64/common/time.c
diff --git a/kernel/arch/mips/loongson/common/uart_base.c b/kernel/arch/mips/loongson64/common/uart_base.c
index 9de559d58..9de559d58 100644
--- a/kernel/arch/mips/loongson/common/uart_base.c
+++ b/kernel/arch/mips/loongson64/common/uart_base.c
diff --git a/kernel/arch/mips/loongson/fuloong-2e/Makefile b/kernel/arch/mips/loongson64/fuloong-2e/Makefile
index b7622720c..b7622720c 100644
--- a/kernel/arch/mips/loongson/fuloong-2e/Makefile
+++ b/kernel/arch/mips/loongson64/fuloong-2e/Makefile
diff --git a/kernel/arch/mips/loongson/fuloong-2e/irq.c b/kernel/arch/mips/loongson64/fuloong-2e/irq.c
index ef5ec8f3d..892963f86 100644
--- a/kernel/arch/mips/loongson/fuloong-2e/irq.c
+++ b/kernel/arch/mips/loongson64/fuloong-2e/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.com
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/kernel/arch/mips/loongson/fuloong-2e/reset.c b/kernel/arch/mips/loongson64/fuloong-2e/reset.c
index da4d2ae2a..da4d2ae2a 100644
--- a/kernel/arch/mips/loongson/fuloong-2e/reset.c
+++ b/kernel/arch/mips/loongson64/fuloong-2e/reset.c
diff --git a/kernel/arch/mips/loongson/lemote-2f/Makefile b/kernel/arch/mips/loongson64/lemote-2f/Makefile
index 4f9eaa328..08b8abcbf 100644
--- a/kernel/arch/mips/loongson/lemote-2f/Makefile
+++ b/kernel/arch/mips/loongson64/lemote-2f/Makefile
@@ -8,4 +8,4 @@ obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
# Suspend Support
#
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
diff --git a/kernel/arch/mips/loongson/lemote-2f/clock.c b/kernel/arch/mips/loongson64/lemote-2f/clock.c
index 462e34d46..a78fb6570 100644
--- a/kernel/arch/mips/loongson/lemote-2f/clock.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/clock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology
* Author: Yanhua, yanh@lemote.com
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -15,7 +15,7 @@
#include <linux/spinlock.h>
#include <asm/clock.h>
-#include <asm/mach-loongson/loongson.h>
+#include <asm/mach-loongson64/loongson.h>
static LIST_HEAD(clock_list);
static DEFINE_SPINLOCK(clock_lock);
diff --git a/kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
index 2b666d3a3..2b666d3a3 100644
--- a/kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.c
diff --git a/kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.h b/kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
index 5a3f1860d..5a3f1860d 100644
--- a/kernel/arch/mips/loongson/lemote-2f/ec_kb3310b.h
+++ b/kernel/arch/mips/loongson64/lemote-2f/ec_kb3310b.h
diff --git a/kernel/arch/mips/loongson/lemote-2f/irq.c b/kernel/arch/mips/loongson64/lemote-2f/irq.c
index cab5f43e0..cab5f43e0 100644
--- a/kernel/arch/mips/loongson/lemote-2f/irq.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/irq.c
diff --git a/kernel/arch/mips/loongson/lemote-2f/machtype.c b/kernel/arch/mips/loongson64/lemote-2f/machtype.c
index b55e6eece..b55e6eece 100644
--- a/kernel/arch/mips/loongson/lemote-2f/machtype.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/machtype.c
diff --git a/kernel/arch/mips/loongson/lemote-2f/pm.c b/kernel/arch/mips/loongson64/lemote-2f/pm.c
index cac4d382e..cac4d382e 100644
--- a/kernel/arch/mips/loongson/lemote-2f/pm.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/pm.c
diff --git a/kernel/arch/mips/loongson/lemote-2f/reset.c b/kernel/arch/mips/loongson64/lemote-2f/reset.c
index a26ca7fcd..a26ca7fcd 100644
--- a/kernel/arch/mips/loongson/lemote-2f/reset.c
+++ b/kernel/arch/mips/loongson64/lemote-2f/reset.c
diff --git a/kernel/arch/mips/loongson/loongson-3/Makefile b/kernel/arch/mips/loongson64/loongson-3/Makefile
index 622fead5e..622fead5e 100644
--- a/kernel/arch/mips/loongson/loongson-3/Makefile
+++ b/kernel/arch/mips/loongson64/loongson-3/Makefile
diff --git a/kernel/arch/mips/loongson/loongson-3/cop2-ex.c b/kernel/arch/mips/loongson64/loongson-3/cop2-ex.c
index ea13764d0..ea13764d0 100644
--- a/kernel/arch/mips/loongson/loongson-3/cop2-ex.c
+++ b/kernel/arch/mips/loongson64/loongson-3/cop2-ex.c
diff --git a/kernel/arch/mips/loongson/loongson-3/hpet.c b/kernel/arch/mips/loongson64/loongson-3/hpet.c
index 5c21cd3bd..a2631a52c 100644
--- a/kernel/arch/mips/loongson/loongson-3/hpet.c
+++ b/kernel/arch/mips/loongson64/loongson-3/hpet.c
@@ -13,6 +13,9 @@
#define SMBUS_PCI_REG64 0x64
#define SMBUS_PCI_REGB4 0xb4
+#define HPET_MIN_CYCLES 64
+#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+
static DEFINE_SPINLOCK(hpet_lock);
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
@@ -78,55 +81,77 @@ static void hpet_enable_legacy_int(void)
/* Do nothing on Loongson-3 */
}
-static void hpet_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int hpet_set_state_periodic(struct clock_event_device *evt)
{
- int cfg = 0;
+ int cfg;
spin_lock(&hpet_lock);
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- pr_info("set clock event to periodic mode!\n");
- /* stop counter */
- hpet_stop_counter();
-
- /* enables the timer0 to generate a periodic interrupt */
- cfg = hpet_read(HPET_T0_CFG);
- cfg &= ~HPET_TN_LEVEL;
- cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
- HPET_TN_SETVAL | HPET_TN_32BIT;
- hpet_write(HPET_T0_CFG, cfg);
-
- /* set the comparator */
- hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
- udelay(1);
- hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
-
- /* start counter */
- hpet_start_counter();
- break;
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_UNUSED:
- cfg = hpet_read(HPET_T0_CFG);
- cfg &= ~HPET_TN_ENABLE;
- hpet_write(HPET_T0_CFG, cfg);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- pr_info("set clock event to one shot mode!\n");
- cfg = hpet_read(HPET_T0_CFG);
- /* set timer0 type
- * 1 : periodic interrupt
- * 0 : non-periodic(oneshot) interrupt
- */
- cfg &= ~HPET_TN_PERIODIC;
- cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
- hpet_write(HPET_T0_CFG, cfg);
- break;
- case CLOCK_EVT_MODE_RESUME:
- hpet_enable_legacy_int();
- break;
- }
+
+ pr_info("set clock event to periodic mode!\n");
+ /* stop counter */
+ hpet_stop_counter();
+
+ /* enables the timer0 to generate a periodic interrupt */
+ cfg = hpet_read(HPET_T0_CFG);
+ cfg &= ~HPET_TN_LEVEL;
+ cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+ HPET_TN_32BIT;
+ hpet_write(HPET_T0_CFG, cfg);
+
+ /* set the comparator */
+ hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
+ udelay(1);
+ hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL);
+
+ /* start counter */
+ hpet_start_counter();
+
+ spin_unlock(&hpet_lock);
+ return 0;
+}
+
+static int hpet_set_state_shutdown(struct clock_event_device *evt)
+{
+ int cfg;
+
+ spin_lock(&hpet_lock);
+
+ cfg = hpet_read(HPET_T0_CFG);
+ cfg &= ~HPET_TN_ENABLE;
+ hpet_write(HPET_T0_CFG, cfg);
+
spin_unlock(&hpet_lock);
+ return 0;
+}
+
+static int hpet_set_state_oneshot(struct clock_event_device *evt)
+{
+ int cfg;
+
+ spin_lock(&hpet_lock);
+
+ pr_info("set clock event to one shot mode!\n");
+ cfg = hpet_read(HPET_T0_CFG);
+ /*
+ * set timer0 type
+ * 1 : periodic interrupt
+ * 0 : non-periodic(oneshot) interrupt
+ */
+ cfg &= ~HPET_TN_PERIODIC;
+ cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
+ hpet_write(HPET_T0_CFG, cfg);
+
+ spin_unlock(&hpet_lock);
+ return 0;
+}
+
+static int hpet_tick_resume(struct clock_event_device *evt)
+{
+ spin_lock(&hpet_lock);
+ hpet_enable_legacy_int();
+ spin_unlock(&hpet_lock);
+
+ return 0;
}
static int hpet_next_event(unsigned long delta,
@@ -139,8 +164,9 @@ static int hpet_next_event(unsigned long delta,
cnt += delta;
hpet_write(HPET_T0_CMP, cnt);
- res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
- return res;
+ res = (int)(cnt - hpet_read(HPET_COUNTER));
+
+ return res < HPET_MIN_CYCLES ? -ETIME : 0;
}
static irqreturn_t hpet_irq_handler(int irq, void *data)
@@ -206,13 +232,16 @@ void __init setup_hpet_timer(void)
cd->name = "hpet";
cd->rating = 320;
cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
- cd->set_mode = hpet_set_mode;
+ cd->set_state_shutdown = hpet_set_state_shutdown;
+ cd->set_state_periodic = hpet_set_state_periodic;
+ cd->set_state_oneshot = hpet_set_state_oneshot;
+ cd->tick_resume = hpet_tick_resume;
cd->set_next_event = hpet_next_event;
cd->irq = HPET_T0_IRQ;
cd->cpumask = cpumask_of(cpu);
clockevent_set_clock(cd, HPET_FREQ);
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
- cd->min_delta_ns = 5000;
+ cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd);
clockevents_register_device(cd);
setup_irq(HPET_T0_IRQ, &hpet_irq);
diff --git a/kernel/arch/mips/loongson/loongson-3/irq.c b/kernel/arch/mips/loongson64/loongson-3/irq.c
index 0f75b6b3d..0f75b6b3d 100644
--- a/kernel/arch/mips/loongson/loongson-3/irq.c
+++ b/kernel/arch/mips/loongson64/loongson-3/irq.c
diff --git a/kernel/arch/mips/loongson/loongson-3/numa.c b/kernel/arch/mips/loongson64/loongson-3/numa.c
index 12d14ed48..6f9e010ce 100644
--- a/kernel/arch/mips/loongson/loongson-3/numa.c
+++ b/kernel/arch/mips/loongson64/loongson-3/numa.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
- * Insititute of Computing Technology
+ * Institute of Computing Technology
* Author: Xiang Gao, gaoxiang@ict.ac.cn
* Huacai Chen, chenhc@lemote.com
* Xiaofu Meng, Shuangshuang Zhang
diff --git a/kernel/arch/mips/loongson/loongson-3/platform.c b/kernel/arch/mips/loongson64/loongson-3/platform.c
index 25a97cc0e..25a97cc0e 100644
--- a/kernel/arch/mips/loongson/loongson-3/platform.c
+++ b/kernel/arch/mips/loongson64/loongson-3/platform.c
diff --git a/kernel/arch/mips/loongson/loongson-3/smp.c b/kernel/arch/mips/loongson64/loongson-3/smp.c
index 509877c6e..509832a98 100644
--- a/kernel/arch/mips/loongson/loongson-3/smp.c
+++ b/kernel/arch/mips/loongson64/loongson-3/smp.c
@@ -30,13 +30,13 @@
#include "smp.h"
DEFINE_PER_CPU(int, cpu_state);
-DEFINE_PER_CPU(uint32_t, core0_c0count);
static void *ipi_set0_regs[16];
static void *ipi_clear0_regs[16];
static void *ipi_status0_regs[16];
static void *ipi_en0_regs[16];
static void *ipi_mailbox_buf[16];
+static uint32_t core0_c0count[NR_CPUS];
/* read a 32bit value from ipi register */
#define loongson3_ipi_read32(addr) readl(addr)
@@ -266,18 +266,23 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
c0count = read_c0_count();
- for (i = 1; i < num_possible_cpus(); i++)
- per_cpu(core0_c0count, i) = c0count;
+ c0count = c0count ? c0count : 1;
+ for (i = 1; i < nr_cpu_ids; i++)
+ core0_c0count[i] = c0count;
+ __wbflush(); /* Let others see the result ASAP */
}
}
-#define MAX_LOOPS 1111
+#define MAX_LOOPS 800
/*
* SMP init and finish on secondary CPUs
*/
@@ -302,16 +307,20 @@ static void loongson3_init_secondary(void)
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
i = 0;
- __this_cpu_write(core0_c0count, 0);
+ core0_c0count[cpu] = 0;
loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
- while (!__this_cpu_read(core0_c0count)) {
+ while (!core0_c0count[cpu]) {
i++;
cpu_relax();
}
if (i > MAX_LOOPS)
i = MAX_LOOPS;
- initcount = __this_cpu_read(core0_c0count) + i;
+ if (cpu_data[cpu].package)
+ initcount = core0_c0count[cpu] + i;
+ else /* Local access is faster for loops */
+ initcount = core0_c0count[cpu] + i/2;
+
write_c0_count(initcount);
}
diff --git a/kernel/arch/mips/loongson/loongson-3/smp.h b/kernel/arch/mips/loongson64/loongson-3/smp.h
index d98ff654b..d98ff654b 100644
--- a/kernel/arch/mips/loongson/loongson-3/smp.h
+++ b/kernel/arch/mips/loongson64/loongson-3/smp.h
diff --git a/kernel/arch/mips/math-emu/Makefile b/kernel/arch/mips/math-emu/Makefile
index 2e5f96275..a19641d3a 100644
--- a/kernel/arch/mips/math-emu/Makefile
+++ b/kernel/arch/mips/math-emu/Makefile
@@ -4,9 +4,9 @@
obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
- dp_tint.o dp_fint.o \
+ dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \
sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
- sp_tint.o sp_fint.o \
+ sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o sp_fmin.o sp_fmax.o \
dsemul.o
lib-y += ieee754d.o \
diff --git a/kernel/arch/mips/math-emu/cp1emu.c b/kernel/arch/mips/math-emu/cp1emu.c
index 2b95e34fa..32f0e19a0 100644
--- a/kernel/arch/mips/math-emu/cp1emu.c
+++ b/kernel/arch/mips/math-emu/cp1emu.c
@@ -551,7 +551,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
dec_insn.next_pc_inc;
return 1;
case blezl_op:
- if (NO_R6EMU)
+ if (!insn.i_format.rt && NO_R6EMU)
break;
case blez_op:
@@ -588,7 +588,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
dec_insn.next_pc_inc;
return 1;
case bgtzl_op:
- if (NO_R6EMU)
+ if (!insn.i_format.rt && NO_R6EMU)
break;
case bgtz_op:
/*
@@ -1394,6 +1394,14 @@ static const unsigned char cmptab[8] = {
IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
};
+static const unsigned char negative_cmptab[8] = {
+ 0, /* Reserved */
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CEQ,
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN,
+ IEEE754_CLT | IEEE754_CGT,
+ /* Reserved */
+};
+
/*
* Additional MIPS4 instructions
@@ -1735,6 +1743,126 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
SPFROMREG(rv.s, MIPSInst_FS(ir));
break;
+ case fseleqz_op:
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(rv.s, MIPSInst_FT(ir));
+ if (rv.w & 0x1)
+ rv.w = 0;
+ else
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+
+ case fselnez_op:
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(rv.s, MIPSInst_FT(ir));
+ if (rv.w & 0x1)
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ else
+ rv.w = 0;
+ break;
+
+ case fmaddf_op: {
+ union ieee754sp ft, fs, fd;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(fd, MIPSInst_FD(ir));
+ rv.s = ieee754sp_maddf(fd, fs, ft);
+ break;
+ }
+
+ case fmsubf_op: {
+ union ieee754sp ft, fs, fd;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(fd, MIPSInst_FD(ir));
+ rv.s = ieee754sp_msubf(fd, fs, ft);
+ break;
+ }
+
+ case frint_op: {
+ union ieee754sp fs;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754sp_tlong(fs);
+ rv.s = ieee754sp_flong(rv.l);
+ goto copcsr;
+ }
+
+ case fclass_op: {
+ union ieee754sp fs;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754sp_2008class(fs);
+ rfmt = w_fmt;
+ break;
+ }
+
+ case fmin_op: {
+ union ieee754sp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fmin(fs, ft);
+ break;
+ }
+
+ case fmina_op: {
+ union ieee754sp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fmina(fs, ft);
+ break;
+ }
+
+ case fmax_op: {
+ union ieee754sp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fmax(fs, ft);
+ break;
+ }
+
+ case fmaxa_op: {
+ union ieee754sp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fmaxa(fs, ft);
+ break;
+ }
+
case fabs_op:
handler.u = ieee754sp_abs;
goto scopuop;
@@ -1838,7 +1966,7 @@ copcsr:
goto copcsr;
default:
- if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
union ieee754sp fs, ft;
@@ -1932,6 +2060,127 @@ copcsr:
return 0;
DPFROMREG(rv.d, MIPSInst_FS(ir));
break;
+
+ case fseleqz_op:
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(rv.d, MIPSInst_FT(ir));
+ if (rv.l & 0x1)
+ rv.l = 0;
+ else
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+
+ case fselnez_op:
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(rv.d, MIPSInst_FT(ir));
+ if (rv.l & 0x1)
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ else
+ rv.l = 0;
+ break;
+
+ case fmaddf_op: {
+ union ieee754dp ft, fs, fd;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(fd, MIPSInst_FD(ir));
+ rv.d = ieee754dp_maddf(fd, fs, ft);
+ break;
+ }
+
+ case fmsubf_op: {
+ union ieee754dp ft, fs, fd;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(fd, MIPSInst_FD(ir));
+ rv.d = ieee754dp_msubf(fd, fs, ft);
+ break;
+ }
+
+ case frint_op: {
+ union ieee754dp fs;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754dp_tlong(fs);
+ rv.d = ieee754dp_flong(rv.l);
+ goto copcsr;
+ }
+
+ case fclass_op: {
+ union ieee754dp fs;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754dp_2008class(fs);
+ rfmt = w_fmt;
+ break;
+ }
+
+ case fmin_op: {
+ union ieee754dp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fmin(fs, ft);
+ break;
+ }
+
+ case fmina_op: {
+ union ieee754dp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fmina(fs, ft);
+ break;
+ }
+
+ case fmax_op: {
+ union ieee754dp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fmax(fs, ft);
+ break;
+ }
+
+ case fmaxa_op: {
+ union ieee754dp fs, ft;
+
+ if (!cpu_has_mips_r6)
+ return SIGILL;
+
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fmaxa(fs, ft);
+ break;
+ }
+
case fabs_op:
handler.u = ieee754dp_abs;
goto dcopuop;
@@ -2015,7 +2264,7 @@ dcopuop:
goto copcsr;
default:
- if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
union ieee754dp fs, ft;
@@ -2039,8 +2288,11 @@ dcopuop:
break;
}
break;
+ }
+
+ case w_fmt: {
+ union ieee754dp fs;
- case w_fmt:
switch (MIPSInst_FUNC(ir)) {
case fcvts_op:
/* convert word to single precision real */
@@ -2054,10 +2306,65 @@ dcopuop:
rv.d = ieee754dp_fint(fs.bits);
rfmt = d_fmt;
goto copcsr;
- default:
- return SIGILL;
+ default: {
+ /* Emulating the new CMP.condn.fmt R6 instruction */
+#define CMPOP_MASK 0x7
+#define SIGN_BIT (0x1 << 3)
+#define PREDICATE_BIT (0x1 << 4)
+
+ int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
+ int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
+ union ieee754sp fs, ft;
+
+ /* This is an R6 only instruction */
+ if (!cpu_has_mips_r6 ||
+ (MIPSInst_FUNC(ir) & 0x20))
+ return SIGILL;
+
+ /* fmt is w_fmt for single precision so fix it */
+ rfmt = s_fmt;
+ /* default to false */
+ rv.w = 0;
+
+ /* CMP.condn.S */
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+
+ /* positive predicates */
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ if (ieee754sp_cmp(fs, ft, cmptab[cmpop],
+ sig))
+ rv.w = -1; /* true, all 1s */
+ if ((sig) &&
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+ } else {
+ /* negative predicates */
+ switch (cmpop) {
+ case 1:
+ case 2:
+ case 3:
+ if (ieee754sp_cmp(fs, ft,
+ negative_cmptab[cmpop],
+ sig))
+ rv.w = -1; /* true, all 1s */
+ if (sig &&
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+ break;
+ default:
+ /* Reserved R6 ops */
+ pr_err("Reserved MIPS R6 CMP.condn.S operation\n");
+ return SIGILL;
+ }
+ }
+ break;
+ }
}
- break;
}
case l_fmt:
@@ -2078,11 +2385,60 @@ dcopuop:
rv.d = ieee754dp_flong(bits);
rfmt = d_fmt;
goto copcsr;
- default:
- return SIGILL;
- }
- break;
+ default: {
+ /* Emulating the new CMP.condn.fmt R6 instruction */
+ int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
+ int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
+ union ieee754dp fs, ft;
+
+ if (!cpu_has_mips_r6 ||
+ (MIPSInst_FUNC(ir) & 0x20))
+ return SIGILL;
+
+ /* fmt is l_fmt for double precision so fix it */
+ rfmt = d_fmt;
+ /* default to false */
+ rv.l = 0;
+
+ /* CMP.condn.D */
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ /* positive predicates */
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
+ if (ieee754dp_cmp(fs, ft,
+ cmptab[cmpop], sig))
+ rv.l = -1LL; /* true, all 1s */
+ if (sig &&
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+ } else {
+ /* negative predicates */
+ switch (cmpop) {
+ case 1:
+ case 2:
+ case 3:
+ if (ieee754dp_cmp(fs, ft,
+ negative_cmptab[cmpop],
+ sig))
+ rv.l = -1LL; /* true, all 1s */
+ if (sig &&
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+ break;
+ default:
+ /* Reserved R6 ops */
+ pr_err("Reserved MIPS R6 CMP.condn.D operation\n");
+ return SIGILL;
+ }
+ }
+ break;
+ }
+ }
default:
return SIGILL;
}
diff --git a/kernel/arch/mips/math-emu/dp_2008class.c b/kernel/arch/mips/math-emu/dp_2008class.c
new file mode 100644
index 000000000..9dc39fc48
--- /dev/null
+++ b/kernel/arch/mips/math-emu/dp_2008class.c
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+int ieee754dp_2008class(union ieee754dp x)
+{
+ COMPXDP;
+
+ EXPLODEXDP;
+
+ /*
+ * 10 bit mask as follows:
+ *
+ * bit0 = SNAN
+ * bit1 = QNAN
+ * bit2 = -INF
+ * bit3 = -NORM
+ * bit4 = -DNORM
+ * bit5 = -ZERO
+ * bit6 = INF
+ * bit7 = NORM
+ * bit8 = DNORM
+ * bit9 = ZERO
+ */
+
+ switch(xc) {
+ case IEEE754_CLASS_SNAN:
+ return 0x01;
+ case IEEE754_CLASS_QNAN:
+ return 0x02;
+ case IEEE754_CLASS_INF:
+ return 0x04 << (xs ? 0 : 4);
+ case IEEE754_CLASS_NORM:
+ return 0x08 << (xs ? 0 : 4);
+ case IEEE754_CLASS_DNORM:
+ return 0x10 << (xs ? 0 : 4);
+ case IEEE754_CLASS_ZERO:
+ return 0x20 << (xs ? 0 : 4);
+ default:
+ pr_err("Unknown class: %d\n", xc);
+ return 0;
+ }
+}
diff --git a/kernel/arch/mips/math-emu/dp_fmax.c b/kernel/arch/mips/math-emu/dp_fmax.c
new file mode 100644
index 000000000..fd71b8daa
--- /dev/null
+++ b/kernel/arch/mips/math-emu/dp_fmax.c
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return xs ? y : x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ys ? x : y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754dp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* Compare signs */
+ if (xs > ys)
+ return y;
+ else if (xs < ys)
+ return x;
+
+ /* Compare exponent */
+ if (xe > ye)
+ return x;
+ else if (xe < ye)
+ return y;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return y;
+ return x;
+}
+
+union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754dp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* Compare exponent */
+ if (xe > ye)
+ return x;
+ else if (xe < ye)
+ return y;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return y;
+ return x;
+}
diff --git a/kernel/arch/mips/math-emu/dp_fmin.c b/kernel/arch/mips/math-emu/dp_fmin.c
new file mode 100644
index 000000000..c1072b0df
--- /dev/null
+++ b/kernel/arch/mips/math-emu/dp_fmin.c
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.D : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.D: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return xs ? x : y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ys ? y : x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754dp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* Compare signs */
+ if (xs > ys)
+ return x;
+ else if (xs < ys)
+ return y;
+
+ /* Compare exponent */
+ if (xe > ye)
+ return y;
+ else if (xe < ye)
+ return x;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return x;
+ return y;
+}
+
+union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754dp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* Compare exponent */
+ if (xe > ye)
+ return y;
+ else if (xe < ye)
+ return x;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return x;
+ return y;
+}
diff --git a/kernel/arch/mips/math-emu/dp_maddf.c b/kernel/arch/mips/math-emu/dp_maddf.c
new file mode 100644
index 000000000..119eda9fa
--- /dev/null
+++ b/kernel/arch/mips/math-emu/dp_maddf.c
@@ -0,0 +1,265 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MADDF.f (Fused Multiply Add)
+ * MADDF.fmt: FPR[fd] = FPR[fd] + (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+ union ieee754dp y)
+{
+ int re;
+ int rs;
+ u64 rm;
+ unsigned lxm;
+ unsigned hxm;
+ unsigned lym;
+ unsigned hym;
+ u64 lrm;
+ u64 hrm;
+ u64 t;
+ u64 at;
+ int s;
+
+ COMPXDP;
+ COMPYDP;
+
+ u64 zm; int ze; int zs __maybe_unused; int zc;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+ EXPLODEDP(z, zc, zs, ze, zm)
+
+ FLUSHXDP;
+ FLUSHYDP;
+ FLUSHDP(z, zc, zs, ze, zm);
+
+ ieee754_clearcx();
+
+ switch (zc) {
+ case IEEE754_CLASS_SNAN:
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(z);
+ case IEEE754_CLASS_DNORM:
+ DPDNORMx(zm, ze);
+ /* QNAN is handled separately below */
+ }
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /*
+ * Infinity handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ return ieee754dp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ /* Multiplication is 0 so just return z */
+ return z;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ /* fall through to real computations */
+ }
+
+ /* Finally get to do some computation */
+
+ /*
+ * Do the multiplication bit first
+ *
+ * rm = xm * ym, re = xe + ye basically
+ *
+ * At this point xm and ym should have been normalized.
+ */
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ re = xe + ye;
+ rs = xs ^ ys;
+
+ /* shunt to top of word */
+ xm <<= 64 - (DP_FBITS + 1);
+ ym <<= 64 - (DP_FBITS + 1);
+
+ /*
+ * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+ */
+
+ /* 32 * 32 => 64 */
+#define DPXMULT(x, y) ((u64)(x) * (u64)y)
+
+ lxm = xm;
+ hxm = xm >> 32;
+ lym = ym;
+ hym = ym >> 32;
+
+ lrm = DPXMULT(lxm, lym);
+ hrm = DPXMULT(hxm, hym);
+
+ t = DPXMULT(lxm, hym);
+
+ at = lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+
+ hrm = hrm + (t >> 32);
+
+ t = DPXMULT(hxm, lym);
+
+ at = lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+
+ hrm = hrm + (t >> 32);
+
+ rm = hrm | (lrm != 0);
+
+ /*
+ * Sticky shift down to normal rounding precision.
+ */
+ if ((s64) rm < 0) {
+ rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
+ ((rm << (DP_FBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
+ ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (DP_HIDDEN_BIT << 3));
+
+ /* And now the addition */
+ assert(zm & DP_HIDDEN_BIT);
+
+ /*
+ * Provide guard,round and stick bit space.
+ */
+ zm <<= 3;
+
+ if (ze > re) {
+ /*
+ * Have to shift y fraction right to align.
+ */
+ s = ze - re;
+ rm = XDPSRS(rm, s);
+ re += s;
+ } else if (re > ze) {
+ /*
+ * Have to shift x fraction right to align.
+ */
+ s = re - ze;
+ zm = XDPSRS(zm, s);
+ ze += s;
+ }
+ assert(ze == re);
+ assert(ze <= DP_EMAX);
+
+ if (zs == rs) {
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm, xs and xe.
+ */
+ zm = zm + rm;
+
+ if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
+ zm = XDPSRS1(zm);
+ ze++;
+ }
+ } else {
+ if (zm >= rm) {
+ zm = zm - rm;
+ } else {
+ zm = rm - zm;
+ zs = rs;
+ }
+ if (zm == 0)
+ return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+ /*
+ * Normalize to rounding precision.
+ */
+ while ((zm >> (DP_FBITS + 3)) == 0) {
+ zm <<= 1;
+ ze--;
+ }
+ }
+
+ return ieee754dp_format(zs, ze, zm);
+}
diff --git a/kernel/arch/mips/math-emu/dp_msubf.c b/kernel/arch/mips/math-emu/dp_msubf.c
new file mode 100644
index 000000000..12241262f
--- /dev/null
+++ b/kernel/arch/mips/math-emu/dp_msubf.c
@@ -0,0 +1,269 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: MSUB.f (Fused Multiply Subtract)
+ * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+ union ieee754dp y)
+{
+ int re;
+ int rs;
+ u64 rm;
+ unsigned lxm;
+ unsigned hxm;
+ unsigned lym;
+ unsigned hym;
+ u64 lrm;
+ u64 hrm;
+ u64 t;
+ u64 at;
+ int s;
+
+ COMPXDP;
+ COMPYDP;
+
+ u64 zm; int ze; int zs __maybe_unused; int zc;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+ EXPLODEDP(z, zc, zs, ze, zm)
+
+ FLUSHXDP;
+ FLUSHYDP;
+ FLUSHDP(z, zc, zs, ze, zm);
+
+ ieee754_clearcx();
+
+ switch (zc) {
+ case IEEE754_CLASS_SNAN:
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(z);
+ case IEEE754_CLASS_DNORM:
+ DPDNORMx(zm, ze);
+ /* QNAN is handled separately below */
+ }
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754dp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754dp_nanxcpt(x);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /*
+ * Infinity handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754dp_indef();
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ return ieee754dp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ /* Multiplication is 0 so just return z */
+ return z;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754dp_inf(zs);
+ /* fall through to real computations */
+ }
+
+ /* Finally get to do some computation */
+
+ /*
+ * Do the multiplication bit first
+ *
+ * rm = xm * ym, re = xe + ye basically
+ *
+ * At this point xm and ym should have been normalized.
+ */
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ re = xe + ye;
+ rs = xs ^ ys;
+
+ /* shunt to top of word */
+ xm <<= 64 - (DP_FBITS + 1);
+ ym <<= 64 - (DP_FBITS + 1);
+
+ /*
+ * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+ */
+
+ /* 32 * 32 => 64 */
+#define DPXMULT(x, y) ((u64)(x) * (u64)y)
+
+ lxm = xm;
+ hxm = xm >> 32;
+ lym = ym;
+ hym = ym >> 32;
+
+ lrm = DPXMULT(lxm, lym);
+ hrm = DPXMULT(hxm, hym);
+
+ t = DPXMULT(lxm, hym);
+
+ at = lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+
+ hrm = hrm + (t >> 32);
+
+ t = DPXMULT(hxm, lym);
+
+ at = lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+
+ hrm = hrm + (t >> 32);
+
+ rm = hrm | (lrm != 0);
+
+ /*
+ * Sticky shift down to normal rounding precision.
+ */
+ if ((s64) rm < 0) {
+ rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
+ ((rm << (DP_FBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
+ ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (DP_HIDDEN_BIT << 3));
+
+ /* And now the subtraction */
+
+ /* flip sign of r and handle as add */
+ rs ^= 1;
+
+ assert(zm & DP_HIDDEN_BIT);
+
+ /*
+ * Provide guard,round and stick bit space.
+ */
+ zm <<= 3;
+
+ if (ze > re) {
+ /*
+ * Have to shift y fraction right to align.
+ */
+ s = ze - re;
+ rm = XDPSRS(rm, s);
+ re += s;
+ } else if (re > ze) {
+ /*
+ * Have to shift x fraction right to align.
+ */
+ s = re - ze;
+ zm = XDPSRS(zm, s);
+ ze += s;
+ }
+ assert(ze == re);
+ assert(ze <= DP_EMAX);
+
+ if (zs == rs) {
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm, xs and xe.
+ */
+ zm = zm + rm;
+
+ if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
+ zm = XDPSRS1(zm);
+ ze++;
+ }
+ } else {
+ if (zm >= rm) {
+ zm = zm - rm;
+ } else {
+ zm = rm - zm;
+ zs = rs;
+ }
+ if (zm == 0)
+ return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+ /*
+ * Normalize to rounding precision.
+ */
+ while ((zm >> (DP_FBITS + 3)) == 0) {
+ zm <<= 1;
+ ze--;
+ }
+ }
+
+ return ieee754dp_format(zs, ze, zm);
+}
diff --git a/kernel/arch/mips/math-emu/dsemul.c b/kernel/arch/mips/math-emu/dsemul.c
index e0b5cc27d..cbb36c14b 100644
--- a/kernel/arch/mips/math-emu/dsemul.c
+++ b/kernel/arch/mips/math-emu/dsemul.c
@@ -33,7 +33,6 @@ struct emuframe {
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
{
- extern asmlinkage void handle_dsemulret(void);
struct emuframe __user *fr;
int err;
diff --git a/kernel/arch/mips/math-emu/ieee754.h b/kernel/arch/mips/math-emu/ieee754.h
index a5ca108ce..df9472071 100644
--- a/kernel/arch/mips/math-emu/ieee754.h
+++ b/kernel/arch/mips/math-emu/ieee754.h
@@ -75,6 +75,16 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig);
union ieee754sp ieee754sp_sqrt(union ieee754sp x);
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+ union ieee754sp y);
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+ union ieee754sp y);
+int ieee754sp_2008class(union ieee754sp x);
+union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y);
+union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y);
+
/*
* double precision (often aka double)
*/
@@ -99,6 +109,15 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig);
union ieee754dp ieee754dp_sqrt(union ieee754dp x);
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+ union ieee754dp y);
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+ union ieee754dp y);
+int ieee754dp_2008class(union ieee754dp x);
+union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y);
+union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y);
/* 5 types of floating point number
diff --git a/kernel/arch/mips/math-emu/ieee754int.h b/kernel/arch/mips/math-emu/ieee754int.h
index 05389d5e3..6383e2c5c 100644
--- a/kernel/arch/mips/math-emu/ieee754int.h
+++ b/kernel/arch/mips/math-emu/ieee754int.h
@@ -65,8 +65,8 @@ static inline int ieee754_class_nan(int xc)
vc = IEEE754_CLASS_INF; \
else if (vm & SP_MBIT(SP_FBITS-1)) \
vc = IEEE754_CLASS_SNAN; \
- else \
- vc = IEEE754_CLASS_QNAN; \
+ else \
+ vc = IEEE754_CLASS_QNAN; \
} else if (ve == SP_EMIN-1+SP_EBIAS) { \
if (vm) { \
ve = SP_EMIN; \
@@ -105,8 +105,8 @@ static inline int ieee754_class_nan(int xc)
if (vm) { \
ve = DP_EMIN; \
vc = IEEE754_CLASS_DNORM; \
- } else \
- vc = IEEE754_CLASS_ZERO; \
+ } else \
+ vc = IEEE754_CLASS_ZERO; \
} else { \
ve -= DP_EBIAS; \
vm |= DP_HIDDEN_BIT; \
diff --git a/kernel/arch/mips/math-emu/me-debugfs.c b/kernel/arch/mips/math-emu/me-debugfs.c
index f308e0f05..be650ed7d 100644
--- a/kernel/arch/mips/math-emu/me-debugfs.c
+++ b/kernel/arch/mips/math-emu/me-debugfs.c
@@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/types.h>
+#include <asm/debug.h>
#include <asm/fpu_emulator.h>
#include <asm/local.h>
@@ -27,7 +28,6 @@ static int fpuemu_stat_get(void *data, u64 *val)
}
DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
-extern struct dentry *mips_debugfs_dir;
static int __init debugfs_fpuemu(void)
{
struct dentry *d, *dir;
@@ -65,4 +65,4 @@ do { \
return 0;
}
-__initcall(debugfs_fpuemu);
+arch_initcall(debugfs_fpuemu);
diff --git a/kernel/arch/mips/math-emu/sp_2008class.c b/kernel/arch/mips/math-emu/sp_2008class.c
new file mode 100644
index 000000000..ff62606a1
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_2008class.c
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+int ieee754sp_2008class(union ieee754sp x)
+{
+ COMPXSP;
+
+ EXPLODEXSP;
+
+ /*
+ * 10 bit mask as follows:
+ *
+ * bit0 = SNAN
+ * bit1 = QNAN
+ * bit2 = -INF
+ * bit3 = -NORM
+ * bit4 = -DNORM
+ * bit5 = -ZERO
+ * bit6 = INF
+ * bit7 = NORM
+ * bit8 = DNORM
+ * bit9 = ZERO
+ */
+
+ switch(xc) {
+ case IEEE754_CLASS_SNAN:
+ return 0x01;
+ case IEEE754_CLASS_QNAN:
+ return 0x02;
+ case IEEE754_CLASS_INF:
+ return 0x04 << (xs ? 0 : 4);
+ case IEEE754_CLASS_NORM:
+ return 0x08 << (xs ? 0 : 4);
+ case IEEE754_CLASS_DNORM:
+ return 0x10 << (xs ? 0 : 4);
+ case IEEE754_CLASS_ZERO:
+ return 0x20 << (xs ? 0 : 4);
+ default:
+ pr_err("Unknown class: %d\n", xc);
+ return 0;
+ }
+}
diff --git a/kernel/arch/mips/math-emu/sp_fmax.c b/kernel/arch/mips/math-emu/sp_fmax.c
new file mode 100644
index 000000000..4d000844e
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_fmax.c
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MAX{,A}.f
+ * MAX : Scalar Floating-Point Maximum
+ * MAXA: Scalar Floating-Point argument with Maximum Absolute Value
+ *
+ * MAX.S : FPR[fd] = maxNum(FPR[fs],FPR[ft])
+ * MAXA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return xs ? y : x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ys ? x : y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754sp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* Compare signs */
+ if (xs > ys)
+ return y;
+ else if (xs < ys)
+ return x;
+
+ /* Compare exponent */
+ if (xe > ye)
+ return x;
+ else if (xe < ye)
+ return y;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return y;
+ return x;
+}
+
+union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754sp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* Compare exponent */
+ if (xe > ye)
+ return x;
+ else if (xe < ye)
+ return y;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return y;
+ return x;
+}
diff --git a/kernel/arch/mips/math-emu/sp_fmin.c b/kernel/arch/mips/math-emu/sp_fmin.c
new file mode 100644
index 000000000..4eb1bb9e9
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_fmin.c
@@ -0,0 +1,213 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MIN{,A}.f
+ * MIN : Scalar Floating-Point Minimum
+ * MINA: Scalar Floating-Point argument with Minimum Absolute Value
+ *
+ * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
+ * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return xs ? x : y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ys ? y : x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754sp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* Compare signs */
+ if (xs > ys)
+ return x;
+ else if (xs < ys)
+ return y;
+
+ /* Compare exponent */
+ if (xe > ye)
+ return y;
+ else if (xe < ye)
+ return x;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return x;
+ return y;
+}
+
+union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ ieee754_clearcx();
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ /* numbers are preferred to NaNs */
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return y;
+
+ /*
+ * Infinity and zero handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ return ieee754sp_zero(1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ }
+
+ /* Finally get to do some computation */
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* Compare exponent */
+ if (xe > ye)
+ return y;
+ else if (xe < ye)
+ return x;
+
+ /* Compare mantissa */
+ if (xm <= ym)
+ return x;
+ return y;
+}
diff --git a/kernel/arch/mips/math-emu/sp_maddf.c b/kernel/arch/mips/math-emu/sp_maddf.c
new file mode 100644
index 000000000..dd1dd83e3
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_maddf.c
@@ -0,0 +1,255 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MADDF.f (Fused Multiply Add)
+ * MADDF.fmt: FPR[fd] = FPR[fd] + (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+ union ieee754sp y)
+{
+ int re;
+ int rs;
+ unsigned rm;
+ unsigned short lxm;
+ unsigned short hxm;
+ unsigned short lym;
+ unsigned short hym;
+ unsigned lrm;
+ unsigned hrm;
+ unsigned t;
+ unsigned at;
+ int s;
+
+ COMPXSP;
+ COMPYSP;
+ u32 zm; int ze; int zs __maybe_unused; int zc;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+ EXPLODESP(z, zc, zs, ze, zm)
+
+ FLUSHXSP;
+ FLUSHYSP;
+ FLUSHSP(z, zc, zs, ze, zm);
+
+ ieee754_clearcx();
+
+ switch (zc) {
+ case IEEE754_CLASS_SNAN:
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(z);
+ case IEEE754_CLASS_DNORM:
+ SPDNORMx(zm, ze);
+ /* QNAN is handled separately below */
+ }
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+ /*
+ * Infinity handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ return ieee754sp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ /* Multiplication is 0 so just return z */
+ return z;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ /* fall through to real computations */
+ }
+
+ /* Finally get to do some computation */
+
+ /*
+ * Do the multiplication bit first
+ *
+ * rm = xm * ym, re = xe + ye basically
+ *
+ * At this point xm and ym should have been normalized.
+ */
+
+ /* rm = xm * ym, re = xe+ye basically */
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ re = xe + ye;
+ rs = xs ^ ys;
+
+ /* shunt to top of word */
+ xm <<= 32 - (SP_FBITS + 1);
+ ym <<= 32 - (SP_FBITS + 1);
+
+ /*
+ * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+ */
+ lxm = xm & 0xffff;
+ hxm = xm >> 16;
+ lym = ym & 0xffff;
+ hym = ym >> 16;
+
+ lrm = lxm * lym; /* 16 * 16 => 32 */
+ hrm = hxm * hym; /* 16 * 16 => 32 */
+
+ t = lxm * hym; /* 16 * 16 => 32 */
+ at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ hrm = hrm + (t >> 16);
+
+ t = hxm * lym; /* 16 * 16 => 32 */
+ at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ hrm = hrm + (t >> 16);
+
+ rm = hrm | (lrm != 0);
+
+ /*
+ * Sticky shift down to normal rounding precision.
+ */
+ if ((int) rm < 0) {
+ rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
+ ((rm << (SP_FBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
+ ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (SP_HIDDEN_BIT << 3));
+
+ /* And now the addition */
+
+ assert(zm & SP_HIDDEN_BIT);
+
+ /*
+ * Provide guard,round and stick bit space.
+ */
+ zm <<= 3;
+
+ if (ze > re) {
+ /*
+ * Have to shift y fraction right to align.
+ */
+ s = ze - re;
+ SPXSRSYn(s);
+ } else if (re > ze) {
+ /*
+ * Have to shift x fraction right to align.
+ */
+ s = re - ze;
+ SPXSRSYn(s);
+ }
+ assert(ze == re);
+ assert(ze <= SP_EMAX);
+
+ if (zs == rs) {
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in zm, zs and ze.
+ */
+ zm = zm + rm;
+
+ if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1();
+ }
+ } else {
+ if (zm >= rm) {
+ zm = zm - rm;
+ } else {
+ zm = rm - zm;
+ zs = rs;
+ }
+ if (zm == 0)
+ return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+ /*
+ * Normalize in extended single precision
+ */
+ while ((zm >> (SP_MBITS + 3)) == 0) {
+ zm <<= 1;
+ ze--;
+ }
+
+ }
+ return ieee754sp_format(zs, ze, zm);
+}
diff --git a/kernel/arch/mips/math-emu/sp_msubf.c b/kernel/arch/mips/math-emu/sp_msubf.c
new file mode 100644
index 000000000..81c38b980
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_msubf.c
@@ -0,0 +1,258 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: MSUB.f (Fused Multiply Subtract)
+ * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+ union ieee754sp y)
+{
+ int re;
+ int rs;
+ unsigned rm;
+ unsigned short lxm;
+ unsigned short hxm;
+ unsigned short lym;
+ unsigned short hym;
+ unsigned lrm;
+ unsigned hrm;
+ unsigned t;
+ unsigned at;
+ int s;
+
+ COMPXSP;
+ COMPYSP;
+ u32 zm; int ze; int zs __maybe_unused; int zc;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+ EXPLODESP(z, zc, zs, ze, zm)
+
+ FLUSHXSP;
+ FLUSHYSP;
+ FLUSHSP(z, zc, zs, ze, zm);
+
+ ieee754_clearcx();
+
+ switch (zc) {
+ case IEEE754_CLASS_SNAN:
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(z);
+ case IEEE754_CLASS_DNORM:
+ SPDNORMx(zm, ze);
+ /* QNAN is handled separately below */
+ }
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ return ieee754sp_nanxcpt(y);
+
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ return ieee754sp_nanxcpt(x);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+ /*
+ * Infinity handling
+ */
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ return ieee754sp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ /* Multiplication is 0 so just return z */
+ return z;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ if (zc == IEEE754_CLASS_QNAN)
+ return z;
+ else if (zc == IEEE754_CLASS_INF)
+ return ieee754sp_inf(zs);
+ /* fall through to real compuation */
+ }
+
+ /* Finally get to do some computation */
+
+ /*
+ * Do the multiplication bit first
+ *
+ * rm = xm * ym, re = xe + ye basically
+ *
+ * At this point xm and ym should have been normalized.
+ */
+
+ /* rm = xm * ym, re = xe+ye basically */
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ re = xe + ye;
+ rs = xs ^ ys;
+
+ /* shunt to top of word */
+ xm <<= 32 - (SP_FBITS + 1);
+ ym <<= 32 - (SP_FBITS + 1);
+
+ /*
+ * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+ */
+ lxm = xm & 0xffff;
+ hxm = xm >> 16;
+ lym = ym & 0xffff;
+ hym = ym >> 16;
+
+ lrm = lxm * lym; /* 16 * 16 => 32 */
+ hrm = hxm * hym; /* 16 * 16 => 32 */
+
+ t = lxm * hym; /* 16 * 16 => 32 */
+ at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ hrm = hrm + (t >> 16);
+
+ t = hxm * lym; /* 16 * 16 => 32 */
+ at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ hrm = hrm + (t >> 16);
+
+ rm = hrm | (lrm != 0);
+
+ /*
+ * Sticky shift down to normal rounding precision.
+ */
+ if ((int) rm < 0) {
+ rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
+ ((rm << (SP_FBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
+ ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (SP_HIDDEN_BIT << 3));
+
+ /* And now the subtraction */
+
+ /* Flip sign of r and handle as add */
+ rs ^= 1;
+
+ assert(zm & SP_HIDDEN_BIT);
+
+ /*
+ * Provide guard,round and stick bit space.
+ */
+ zm <<= 3;
+
+ if (ze > re) {
+ /*
+ * Have to shift y fraction right to align.
+ */
+ s = ze - re;
+ SPXSRSYn(s);
+ } else if (re > ze) {
+ /*
+ * Have to shift x fraction right to align.
+ */
+ s = re - ze;
+ SPXSRSYn(s);
+ }
+ assert(ze == re);
+ assert(ze <= SP_EMAX);
+
+ if (zs == rs) {
+ /*
+ * Generate 28 bit result of adding two 27 bit numbers
+ * leaving result in zm, zs and ze.
+ */
+ zm = zm + rm;
+
+ if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1(); /* shift preserving sticky */
+ }
+ } else {
+ if (zm >= rm) {
+ zm = zm - rm;
+ } else {
+ zm = rm - zm;
+ zs = rs;
+ }
+ if (zm == 0)
+ return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
+
+ /*
+ * Normalize in extended single precision
+ */
+ while ((zm >> (SP_MBITS + 3)) == 0) {
+ zm <<= 1;
+ ze--;
+ }
+
+ }
+ return ieee754sp_format(zs, ze, zm);
+}
diff --git a/kernel/arch/mips/mm/Makefile b/kernel/arch/mips/mm/Makefile
index 67ede4ef9..b4c64bd3f 100644
--- a/kernel/arch/mips/mm/Makefile
+++ b/kernel/arch/mips/mm/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
+obj-$(CONFIG_SCACHE_DEBUGFS) += sc-debugfs.o
diff --git a/kernel/arch/mips/mm/c-r4k.c b/kernel/arch/mips/mm/c-r4k.c
index dca0efc07..5d3a25e1c 100644
--- a/kernel/arch/mips/mm/c-r4k.c
+++ b/kernel/arch/mips/mm/c-r4k.c
@@ -303,7 +303,7 @@ static void r4k_blast_icache_page_setup(void)
static void (*r4k_blast_icache_user_page)(unsigned long addr);
-static void __cpuinit r4k_blast_icache_user_page_setup(void)
+static void r4k_blast_icache_user_page_setup(void)
{
unsigned long ic_lsize = cpu_icache_line_size();
@@ -945,7 +945,9 @@ static void b5k_instruction_hazard(void)
}
static char *way_string[] = { NULL, "direct mapped", "2-way",
- "3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
+ "3-way", "4-way", "5-way", "6-way", "7-way", "8-way",
+ "9-way", "10-way", "11-way", "12-way",
+ "13-way", "14-way", "15-way", "16-way",
};
static void probe_pcache(void)
@@ -1274,6 +1276,7 @@ static void probe_pcache(void)
case CPU_PROAPTIV:
case CPU_M5150:
case CPU_QEMU_GENERIC:
+ case CPU_I6400:
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
(c->icache.waysize > PAGE_SIZE))
c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/kernel/arch/mips/mm/c-tx39.c b/kernel/arch/mips/mm/c-tx39.c
index 8d909dbbf..596e18458 100644
--- a/kernel/arch/mips/mm/c-tx39.c
+++ b/kernel/arch/mips/mm/c-tx39.c
@@ -28,8 +28,6 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */
#include <asm/r4kcache.h>
-extern int r3k_have_wired_reg; /* in r3k-tlb.c */
-
/* This sequence is required to ensure icache is disabled immediately */
#define TX39_STOP_STREAMING() \
__asm__ __volatile__( \
@@ -383,8 +381,6 @@ void tx39_cache_init(void)
case CPU_TX3927:
default:
/* TX39/H2,H3 core (writeback 2way-set-associative cache) */
- r3k_have_wired_reg = 1;
- write_c0_wired(0); /* set 8 on reset... */
/* board-dependent init code may set WBON */
__flush_cache_vmap = tx39__flush_cache_vmap;
diff --git a/kernel/arch/mips/mm/cache.c b/kernel/arch/mips/mm/cache.c
index 77d96db82..aab218c36 100644
--- a/kernel/arch/mips/mm/cache.c
+++ b/kernel/arch/mips/mm/cache.c
@@ -160,18 +160,18 @@ static inline void setup_protection_map(void)
protection_map[1] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
protection_map[2] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
protection_map[3] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
- protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[5] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
- protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[7] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[8] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
protection_map[9] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
protection_map[10] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | _PAGE_NO_READ);
protection_map[11] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
- protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[13] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
- protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE | _PAGE_NO_READ);
+ protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
protection_map[15] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
} else {
diff --git a/kernel/arch/mips/mm/dma-default.c b/kernel/arch/mips/mm/dma-default.c
index 609d1241b..730d394ce 100644
--- a/kernel/arch/mips/mm/dma-default.c
+++ b/kernel/arch/mips/mm/dma-default.c
@@ -100,7 +100,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
else
#endif
#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
- if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
dma_flag = __GFP_DMA;
else
#endif
@@ -112,7 +112,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
return gfp | dma_flag;
}
-void *dma_alloc_noncoherent(struct device *dev, size_t size,
+static void *mips_dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp)
{
void *ret;
@@ -128,7 +128,6 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
return ret;
}
-EXPORT_SYMBOL(dma_alloc_noncoherent);
static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
@@ -137,12 +136,16 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
struct page *page = NULL;
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
- return ret;
+ /*
+ * XXX: seems like the coherent and non-coherent implementations could
+ * be consolidated.
+ */
+ if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
+ return mips_dma_alloc_noncoherent(dev, size, dma_handle, gfp);
gfp = massage_gfp_flags(dev, gfp);
- if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
+ if (IS_ENABLED(CONFIG_DMA_CMA) && gfpflags_allow_blocking(gfp))
page = dma_alloc_from_contiguous(dev,
count, get_order(size));
if (!page)
@@ -164,24 +167,24 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
}
-void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+static void mips_dma_free_noncoherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
{
plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
free_pages((unsigned long) vaddr, get_order(size));
}
-EXPORT_SYMBOL(dma_free_noncoherent);
static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, struct dma_attrs *attrs)
{
unsigned long addr = (unsigned long) vaddr;
- int order = get_order(size);
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page *page = NULL;
- if (dma_release_from_coherent(dev, order, vaddr))
+ if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ mips_dma_free_noncoherent(dev, size, vaddr, dma_handle);
return;
+ }
plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
@@ -194,6 +197,40 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
__free_pages(page, get_order(size));
}
+static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_attrs *attrs)
+{
+ unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ unsigned long addr = (unsigned long)cpu_addr;
+ unsigned long off = vma->vm_pgoff;
+ unsigned long pfn;
+ int ret = -ENXIO;
+
+ if (!plat_device_is_coherent(dev) && !hw_coherentio)
+ addr = CAC_ADDR(addr);
+
+ pfn = page_to_pfn(virt_to_page((void *)addr));
+
+ if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
+ return ret;
+
+ if (off < count && user_count <= (count - off)) {
+ ret = remap_pfn_range(vma, vma->vm_start,
+ pfn + off,
+ user_count << PAGE_SHIFT,
+ vma->vm_page_prot);
+ }
+
+ return ret;
+}
+
static inline void __dma_sync_virtual(void *addr, size_t size,
enum dma_data_direction direction)
{
@@ -262,12 +299,13 @@ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
plat_unmap_dma_mem(dev, dma_addr, size, direction);
}
-static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
+static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
{
int i;
+ struct scatterlist *sg;
- for (i = 0; i < nents; i++, sg++) {
+ for_each_sg(sglist, sg, nents, i) {
if (!plat_device_is_coherent(dev))
__dma_sync(sg_page(sg), sg->offset, sg->length,
direction);
@@ -291,13 +329,14 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
return plat_map_dma_mem_page(dev, page) + offset;
}
-static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nhwentries, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
int i;
+ struct scatterlist *sg;
- for (i = 0; i < nhwentries; i++, sg++) {
+ for_each_sg(sglist, sg, nhwentries, i) {
if (!plat_device_is_coherent(dev) &&
direction != DMA_TO_DEVICE)
__dma_sync(sg_page(sg), sg->offset, sg->length,
@@ -324,26 +363,34 @@ static void mips_dma_sync_single_for_device(struct device *dev,
}
static void mips_dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sg, int nelems, enum dma_data_direction direction)
+ struct scatterlist *sglist, int nelems,
+ enum dma_data_direction direction)
{
int i;
+ struct scatterlist *sg;
- if (cpu_needs_post_dma_flush(dev))
- for (i = 0; i < nelems; i++, sg++)
+ if (cpu_needs_post_dma_flush(dev)) {
+ for_each_sg(sglist, sg, nelems, i) {
__dma_sync(sg_page(sg), sg->offset, sg->length,
direction);
+ }
+ }
plat_post_dma_flush(dev);
}
static void mips_dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sg, int nelems, enum dma_data_direction direction)
+ struct scatterlist *sglist, int nelems,
+ enum dma_data_direction direction)
{
int i;
+ struct scatterlist *sg;
- if (!plat_device_is_coherent(dev))
- for (i = 0; i < nelems; i++, sg++)
+ if (!plat_device_is_coherent(dev)) {
+ for_each_sg(sglist, sg, nelems, i) {
__dma_sync(sg_page(sg), sg->offset, sg->length,
direction);
+ }
+ }
}
int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
@@ -370,6 +417,7 @@ EXPORT_SYMBOL(dma_cache_sync);
static struct dma_map_ops mips_default_dma_map_ops = {
.alloc = mips_dma_alloc_coherent,
.free = mips_dma_free_coherent,
+ .mmap = mips_dma_mmap,
.map_page = mips_dma_map_page,
.unmap_page = mips_dma_unmap_page,
.map_sg = mips_dma_map_sg,
diff --git a/kernel/arch/mips/mm/fault.c b/kernel/arch/mips/mm/fault.c
index 36c0f26fa..4b88fa031 100644
--- a/kernel/arch/mips/mm/fault.c
+++ b/kernel/arch/mips/mm/fault.c
@@ -57,12 +57,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
#ifdef CONFIG_KPROBES
/*
- * This is to notify the fault handler of the kprobes. The
- * exception code is redundant as it is also carried in REGS,
- * but we pass it anyhow.
+ * This is to notify the fault handler of the kprobes.
*/
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
- (regs->cp0_cause >> 2) & 0x1f, SIGSEGV) == NOTIFY_STOP)
+ current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
return;
#endif
@@ -133,7 +131,8 @@ good_area:
#endif
goto bad_area;
}
- if (!(vma->vm_flags & VM_READ)) {
+ if (!(vma->vm_flags & VM_READ) &&
+ exception_epc(regs) != address) {
#if 0
pr_notice("Cpu%d[%s:%d:%0*lx:%ld:%0*lx] RI violation\n",
raw_smp_processor_id(),
@@ -223,6 +222,7 @@ bad_area_nosemaphore:
print_vma_addr(" ", regs->regs[31]);
pr_info("\n");
}
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* info.si_code has been set above */
@@ -281,6 +281,7 @@ do_sigbus:
field, (unsigned long) regs->cp0_epc,
field, (unsigned long) regs->regs[31]);
#endif
+ current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
tsk->thread.cp0_badvaddr = address;
info.si_signo = SIGBUS;
info.si_errno = 0;
diff --git a/kernel/arch/mips/mm/highmem.c b/kernel/arch/mips/mm/highmem.c
index 11661cbc1..d7258a103 100644
--- a/kernel/arch/mips/mm/highmem.c
+++ b/kernel/arch/mips/mm/highmem.c
@@ -118,19 +118,6 @@ void *kmap_atomic_pfn(unsigned long pfn)
return (void*) vaddr;
}
-struct page *kmap_atomic_to_page(void *ptr)
-{
- unsigned long idx, vaddr = (unsigned long)ptr;
- pte_t *pte;
-
- if (vaddr < FIXADDR_START)
- return virt_to_page(ptr);
-
- idx = virt_to_fix(vaddr);
- pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
- return pte_page(*pte);
-}
-
void __init kmap_init(void)
{
unsigned long kmap_vstart;
diff --git a/kernel/arch/mips/mm/hugetlbpage.c b/kernel/arch/mips/mm/hugetlbpage.c
index 06e0f421b..74aa6f624 100644
--- a/kernel/arch/mips/mm/hugetlbpage.c
+++ b/kernel/arch/mips/mm/hugetlbpage.c
@@ -51,11 +51,6 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
return (pte_t *) pmd;
}
-int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
-{
- return 0;
-}
-
/*
* This function checks for proper alignment of input addr and len parameters.
*/
diff --git a/kernel/arch/mips/mm/init.c b/kernel/arch/mips/mm/init.c
index 198a3147d..8770e6191 100644
--- a/kernel/arch/mips/mm/init.c
+++ b/kernel/arch/mips/mm/init.c
@@ -37,12 +37,14 @@
#include <asm/cpu.h>
#include <asm/dma.h>
#include <asm/kmap_types.h>
+#include <asm/maar.h>
#include <asm/mmu_context.h>
#include <asm/sections.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/fixmap.h>
+#include <asm/maar.h>
/*
* We have up to 8 empty zeroed pages so we can map one of the right colour
@@ -251,6 +253,119 @@ void __init fixrange_init(unsigned long start, unsigned long end,
#endif
}
+unsigned __weak platform_maar_init(unsigned num_pairs)
+{
+ struct maar_config cfg[BOOT_MEM_MAP_MAX];
+ unsigned i, num_configured, num_cfg = 0;
+ phys_addr_t skip;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ switch (boot_mem_map.map[i].type) {
+ case BOOT_MEM_RAM:
+ case BOOT_MEM_INIT_RAM:
+ break;
+ default:
+ continue;
+ }
+
+ skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff);
+
+ cfg[num_cfg].lower = boot_mem_map.map[i].addr;
+ cfg[num_cfg].lower += skip;
+
+ cfg[num_cfg].upper = cfg[num_cfg].lower;
+ cfg[num_cfg].upper += boot_mem_map.map[i].size - 1;
+ cfg[num_cfg].upper -= skip;
+
+ cfg[num_cfg].attrs = MIPS_MAAR_S;
+ num_cfg++;
+ }
+
+ num_configured = maar_config(cfg, num_cfg, num_pairs);
+ if (num_configured < num_cfg)
+ pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n",
+ num_pairs, num_cfg);
+
+ return num_configured;
+}
+
+void maar_init(void)
+{
+ unsigned num_maars, used, i;
+ phys_addr_t lower, upper, attr;
+ static struct {
+ struct maar_config cfgs[3];
+ unsigned used;
+ } recorded = { { { 0 } }, 0 };
+
+ if (!cpu_has_maar)
+ return;
+
+ /* Detect the number of MAARs */
+ write_c0_maari(~0);
+ back_to_back_c0_hazard();
+ num_maars = read_c0_maari() + 1;
+
+ /* MAARs should be in pairs */
+ WARN_ON(num_maars % 2);
+
+ /* Set MAARs using values we recorded already */
+ if (recorded.used) {
+ used = maar_config(recorded.cfgs, recorded.used, num_maars / 2);
+ BUG_ON(used != recorded.used);
+ } else {
+ /* Configure the required MAARs */
+ used = platform_maar_init(num_maars / 2);
+ }
+
+ /* Disable any further MAARs */
+ for (i = (used * 2); i < num_maars; i++) {
+ write_c0_maari(i);
+ back_to_back_c0_hazard();
+ write_c0_maar(0);
+ back_to_back_c0_hazard();
+ }
+
+ if (recorded.used)
+ return;
+
+ pr_info("MAAR configuration:\n");
+ for (i = 0; i < num_maars; i += 2) {
+ write_c0_maari(i);
+ back_to_back_c0_hazard();
+ upper = read_c0_maar();
+
+ write_c0_maari(i + 1);
+ back_to_back_c0_hazard();
+ lower = read_c0_maar();
+
+ attr = lower & upper;
+ lower = (lower & MIPS_MAAR_ADDR) << 4;
+ upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff;
+
+ pr_info(" [%d]: ", i / 2);
+ if (!(attr & MIPS_MAAR_V)) {
+ pr_cont("disabled\n");
+ continue;
+ }
+
+ pr_cont("%pa-%pa", &lower, &upper);
+
+ if (attr & MIPS_MAAR_S)
+ pr_cont(" speculate");
+
+ pr_cont("\n");
+
+ /* Record the setup for use on secondary CPUs */
+ if (used <= ARRAY_SIZE(recorded.cfgs)) {
+ recorded.cfgs[recorded.used].lower = lower;
+ recorded.cfgs[recorded.used].upper = upper;
+ recorded.cfgs[recorded.used].attrs = attr;
+ recorded.used++;
+ }
+ }
+}
+
#ifndef CONFIG_NEED_MULTIPLE_NODES
int page_is_ram(unsigned long pagenr)
{
@@ -333,38 +448,6 @@ static inline void mem_init_free_highmem(void)
#endif
}
-unsigned __weak platform_maar_init(unsigned num_maars)
-{
- return 0;
-}
-
-static void maar_init(void)
-{
- unsigned num_maars, used, i;
-
- if (!cpu_has_maar)
- return;
-
- /* Detect the number of MAARs */
- write_c0_maari(~0);
- back_to_back_c0_hazard();
- num_maars = read_c0_maari() + 1;
-
- /* MAARs should be in pairs */
- WARN_ON(num_maars % 2);
-
- /* Configure the required MAARs */
- used = platform_maar_init(num_maars / 2);
-
- /* Disable any further MAARs */
- for (i = (used * 2); i < num_maars; i++) {
- write_c0_maari(i);
- back_to_back_c0_hazard();
- write_c0_maar(0);
- back_to_back_c0_hazard();
- }
-}
-
void __init mem_init(void)
{
#ifdef CONFIG_HIGHMEM
diff --git a/kernel/arch/mips/mm/sc-debugfs.c b/kernel/arch/mips/mm/sc-debugfs.c
new file mode 100644
index 000000000..5eefe3281
--- /dev/null
+++ b/kernel/arch/mips/mm/sc-debugfs.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bcache.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+
+static ssize_t sc_prefetch_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ bool enabled = bc_prefetch_is_enabled();
+ char buf[3];
+
+ buf[0] = enabled ? 'Y' : 'N';
+ buf[1] = '\n';
+ buf[2] = 0;
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t sc_prefetch_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[32];
+ ssize_t buf_size;
+ bool enabled;
+ int err;
+
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+ err = strtobool(buf, &enabled);
+ if (err)
+ return err;
+
+ if (enabled)
+ bc_prefetch_enable();
+ else
+ bc_prefetch_disable();
+
+ return count;
+}
+
+static const struct file_operations sc_prefetch_fops = {
+ .open = simple_open,
+ .llseek = default_llseek,
+ .read = sc_prefetch_read,
+ .write = sc_prefetch_write,
+};
+
+static int __init sc_debugfs_init(void)
+{
+ struct dentry *dir, *file;
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+
+ dir = debugfs_create_dir("l2cache", mips_debugfs_dir);
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+
+ file = debugfs_create_file("prefetch", S_IRUGO | S_IWUSR, dir,
+ NULL, &sc_prefetch_fops);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ return 0;
+}
+late_initcall(sc_debugfs_init);
diff --git a/kernel/arch/mips/mm/sc-mips.c b/kernel/arch/mips/mm/sc-mips.c
index 4ceafd138..ddb815461 100644
--- a/kernel/arch/mips/mm/sc-mips.c
+++ b/kernel/arch/mips/mm/sc-mips.c
@@ -14,6 +14,7 @@
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
#include <asm/r4kcache.h>
+#include <asm/mips-cm.h>
/*
* MIPS32/MIPS64 L2 cache handling
@@ -50,11 +51,69 @@ static void mips_sc_disable(void)
/* L2 cache is permanently enabled */
}
+static void mips_sc_prefetch_enable(void)
+{
+ unsigned long pftctl;
+
+ if (mips_cm_revision() < CM_REV_CM2_5)
+ return;
+
+ /*
+ * If there is one or more L2 prefetch unit present then enable
+ * prefetching for both code & data, for all ports.
+ */
+ pftctl = read_gcr_l2_pft_control();
+ if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) {
+ pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+ pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+ pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+ write_gcr_l2_pft_control(pftctl);
+
+ pftctl = read_gcr_l2_pft_control_b();
+ pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+ pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+ write_gcr_l2_pft_control_b(pftctl);
+ }
+}
+
+static void mips_sc_prefetch_disable(void)
+{
+ unsigned long pftctl;
+
+ if (mips_cm_revision() < CM_REV_CM2_5)
+ return;
+
+ pftctl = read_gcr_l2_pft_control();
+ pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+ write_gcr_l2_pft_control(pftctl);
+
+ pftctl = read_gcr_l2_pft_control_b();
+ pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+ pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+ write_gcr_l2_pft_control_b(pftctl);
+}
+
+static bool mips_sc_prefetch_is_enabled(void)
+{
+ unsigned long pftctl;
+
+ if (mips_cm_revision() < CM_REV_CM2_5)
+ return false;
+
+ pftctl = read_gcr_l2_pft_control();
+ if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK))
+ return false;
+ return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK);
+}
+
static struct bcache_ops mips_sc_ops = {
.bc_enable = mips_sc_enable,
.bc_disable = mips_sc_disable,
.bc_wback_inv = mips_sc_wback_inv,
- .bc_inv = mips_sc_inv
+ .bc_inv = mips_sc_inv,
+ .bc_prefetch_enable = mips_sc_prefetch_enable,
+ .bc_prefetch_disable = mips_sc_prefetch_disable,
+ .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled,
};
/*
@@ -94,6 +153,43 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
return 1;
}
+static int __init mips_sc_probe_cm3(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+ unsigned long cfg = read_gcr_l2_config();
+ unsigned long sets, line_sz, assoc;
+
+ if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
+ return 0;
+
+ sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+ sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+ if (sets)
+ c->scache.sets = 64 << sets;
+
+ line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+ line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+ if (line_sz)
+ c->scache.linesz = 2 << line_sz;
+
+ assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+ assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+ c->scache.ways = assoc + 1;
+ c->scache.waysize = c->scache.sets * c->scache.linesz;
+ c->scache.waybit = __ffs(c->scache.waysize);
+
+ if (c->scache.linesz) {
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+ return 1;
+ }
+
+ return 0;
+}
+
+void __weak platform_early_l2_init(void)
+{
+}
+
static inline int __init mips_sc_probe(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -103,6 +199,15 @@ static inline int __init mips_sc_probe(void)
/* Mark as not present until probe completed */
c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
+ /*
+ * Do we need some platform specific probing before
+ * we configure L2?
+ */
+ platform_early_l2_init();
+
+ if (mips_cm_revision() >= CM_REV_CM3)
+ return mips_sc_probe_cm3();
+
/* Ignore anything but MIPSxx processors */
if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
@@ -120,13 +225,13 @@ static inline int __init mips_sc_probe(void)
return 0;
tmp = (config2 >> 8) & 0x0f;
- if (0 <= tmp && tmp <= 7)
+ if (tmp <= 7)
c->scache.sets = 64 << tmp;
else
return 0;
tmp = (config2 >> 0) & 0x0f;
- if (0 <= tmp && tmp <= 7)
+ if (tmp <= 7)
c->scache.ways = tmp + 1;
else
return 0;
@@ -144,6 +249,7 @@ int mips_sc_init(void)
int found = mips_sc_probe();
if (found) {
mips_sc_enable();
+ mips_sc_prefetch_enable();
bcops = &mips_sc_ops;
}
return found;
diff --git a/kernel/arch/mips/mm/tlb-r3k.c b/kernel/arch/mips/mm/tlb-r3k.c
index 4094bbd42..b4f366f7c 100644
--- a/kernel/arch/mips/mm/tlb-r3k.c
+++ b/kernel/arch/mips/mm/tlb-r3k.c
@@ -36,30 +36,33 @@ extern void build_tlb_refill_handler(void);
"nop\n\t" \
".set pop\n\t")
-int r3k_have_wired_reg; /* should be in cpu_data? */
+int r3k_have_wired_reg; /* Should be in cpu_data? */
/* TLB operations. */
-void local_flush_tlb_all(void)
+static void local_flush_tlb_from(int entry)
{
- unsigned long flags;
unsigned long old_ctx;
- int entry;
-
-#ifdef DEBUG_TLB
- printk("[tlball]");
-#endif
- local_irq_save(flags);
old_ctx = read_c0_entryhi() & ASID_MASK;
write_c0_entrylo0(0);
- entry = r3k_have_wired_reg ? read_c0_wired() : 8;
- for (; entry < current_cpu_data.tlbsize; entry++) {
+ while (entry < current_cpu_data.tlbsize) {
write_c0_index(entry << 8);
write_c0_entryhi((entry | 0x80000) << 12);
- BARRIER;
+ entry++; /* BARRIER */
tlb_write_indexed();
}
write_c0_entryhi(old_ctx);
+}
+
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+
+#ifdef DEBUG_TLB
+ printk("[tlball]");
+#endif
+ local_irq_save(flags);
+ local_flush_tlb_from(r3k_have_wired_reg ? read_c0_wired() : 8);
local_irq_restore(flags);
}
@@ -277,7 +280,13 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
void tlb_init(void)
{
- local_flush_tlb_all();
-
+ switch (current_cpu_type()) {
+ case CPU_TX3922:
+ case CPU_TX3927:
+ r3k_have_wired_reg = 1;
+ write_c0_wired(0); /* Set to 8 on reset... */
+ break;
+ }
+ local_flush_tlb_from(0);
build_tlb_refill_handler();
}
diff --git a/kernel/arch/mips/mm/tlb-r4k.c b/kernel/arch/mips/mm/tlb-r4k.c
index 08318ecb8..5037d5868 100644
--- a/kernel/arch/mips/mm/tlb-r4k.c
+++ b/kernel/arch/mips/mm/tlb-r4k.c
@@ -423,7 +423,7 @@ int __init has_transparent_hugepage(void)
* lifetime of the system
*/
-int temp_tlb_entry __cpuinitdata;
+int temp_tlb_entry;
__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
unsigned long entryhi, unsigned long pagemask)
diff --git a/kernel/arch/mips/mm/tlbex.c b/kernel/arch/mips/mm/tlbex.c
index 97c87027c..29f73e002 100644
--- a/kernel/arch/mips/mm/tlbex.c
+++ b/kernel/arch/mips/mm/tlbex.c
@@ -35,7 +35,7 @@
#include <asm/uasm.h>
#include <asm/setup.h>
-static int __cpuinitdata mips_xpa_disabled;
+static int mips_xpa_disabled;
static int __init xpa_disable(char *s)
{
@@ -242,7 +242,7 @@ static void output_pgtable_bits_defines(void)
pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
#endif
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (cpu_has_rixi) {
#ifdef _PAGE_NO_EXEC_SHIFT
pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
@@ -311,6 +311,7 @@ static struct uasm_label labels[128];
static struct uasm_reloc relocs[128];
static int check_for_high_segbits;
+static bool fill_includes_sw_bits;
static unsigned int kscratch_used_mask;
@@ -630,8 +631,14 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
unsigned int reg)
{
- if (cpu_has_rixi) {
- UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+ if (cpu_has_rixi && _PAGE_NO_EXEC) {
+ if (fill_includes_sw_bits) {
+ UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+ } else {
+ UASM_i_SRL(p, reg, reg, ilog2(_PAGE_NO_EXEC));
+ UASM_i_ROTR(p, reg, reg,
+ ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
+ }
} else {
#ifdef CONFIG_PHYS_ADDR_T_64BIT
uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -1005,21 +1012,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
* 64bit address support (36bit on a 32bit CPU) in a 32bit
* Kernel is a special case. Only a few CPUs use it.
*/
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
- if (cpu_has_64bits) {
- uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
- uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
- if (cpu_has_rixi) {
- UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
- UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
- UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
- } else {
- uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
- UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
- uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
- }
- UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
- } else {
+ if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
int pte_off_even = sizeof(pte_t) / 2;
int pte_off_odd = pte_off_even + sizeof(pte_t);
#ifdef CONFIG_XPA
@@ -1043,31 +1036,23 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
#endif
+ return;
}
-#else
+
UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
if (r45k_bvahwbug())
build_tlb_probe_entry(p);
- if (cpu_has_rixi) {
- UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
- if (r4k_250MHZhwbug())
- UASM_i_MTC0(p, 0, C0_ENTRYLO0);
- UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
- UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
- } else {
- UASM_i_SRL(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
- if (r4k_250MHZhwbug())
- UASM_i_MTC0(p, 0, C0_ENTRYLO0);
- UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
- UASM_i_SRL(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
- if (r45k_bvahwbug())
- uasm_i_mfc0(p, tmp, C0_INDEX);
- }
+ build_convert_pte_to_entrylo(p, tmp);
+ if (r4k_250MHZhwbug())
+ UASM_i_MTC0(p, 0, C0_ENTRYLO0);
+ UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
+ build_convert_pte_to_entrylo(p, ptep);
+ if (r45k_bvahwbug())
+ uasm_i_mfc0(p, tmp, C0_INDEX);
if (r4k_250MHZhwbug())
UASM_i_MTC0(p, 0, C0_ENTRYLO1);
UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
-#endif
}
struct mips_huge_tlb_info {
@@ -1608,23 +1593,32 @@ build_pte_present(u32 **p, struct uasm_reloc **r,
int pte, int ptr, int scratch, enum label_id lid)
{
int t = scratch >= 0 ? scratch : pte;
+ int cur = pte;
if (cpu_has_rixi) {
if (use_bbit_insns()) {
uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
uasm_i_nop(p);
} else {
- uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT);
- uasm_i_andi(p, t, t, 1);
+ if (_PAGE_PRESENT_SHIFT) {
+ uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT);
+ cur = t;
+ }
+ uasm_i_andi(p, t, cur, 1);
uasm_il_beqz(p, r, t, lid);
if (pte == t)
/* You lose the SMP race :-(*/
iPTE_LW(p, pte, ptr);
}
} else {
- uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT);
- uasm_i_andi(p, t, t, 3);
- uasm_i_xori(p, t, t, 3);
+ if (_PAGE_PRESENT_SHIFT) {
+ uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT);
+ cur = t;
+ }
+ uasm_i_andi(p, t, cur,
+ (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
+ uasm_i_xori(p, t, t,
+ (_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
uasm_il_bnez(p, r, t, lid);
if (pte == t)
/* You lose the SMP race :-(*/
@@ -1652,10 +1646,16 @@ build_pte_writable(u32 **p, struct uasm_reloc **r,
enum label_id lid)
{
int t = scratch >= 0 ? scratch : pte;
+ int cur = pte;
- uasm_i_srl(p, t, pte, _PAGE_PRESENT_SHIFT);
- uasm_i_andi(p, t, t, 5);
- uasm_i_xori(p, t, t, 5);
+ if (_PAGE_PRESENT_SHIFT) {
+ uasm_i_srl(p, t, cur, _PAGE_PRESENT_SHIFT);
+ cur = t;
+ }
+ uasm_i_andi(p, t, cur,
+ (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT);
+ uasm_i_xori(p, t, t,
+ (_PAGE_PRESENT | _PAGE_WRITE) >> _PAGE_PRESENT_SHIFT);
uasm_il_bnez(p, r, t, lid);
if (pte == t)
/* You lose the SMP race :-(*/
@@ -2284,6 +2284,10 @@ static void config_htw_params(void)
/* re-initialize the PTI field including the even/odd bit */
pwfield &= ~MIPS_PWFIELD_PTI_MASK;
pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+ if (CONFIG_PGTABLE_LEVELS >= 3) {
+ pwfield &= ~MIPS_PWFIELD_MDI_MASK;
+ pwfield |= PMD_SHIFT << MIPS_PWFIELD_MDI_SHIFT;
+ }
/* Set the PTEI right shift */
ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
pwfield |= ptei;
@@ -2305,9 +2309,11 @@ static void config_htw_params(void)
pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+ if (CONFIG_PGTABLE_LEVELS >= 3)
+ pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
/* If XPA has been enabled, PTEs are 64-bit in size. */
- if (read_c0_pagegrain() & PG_ELPA)
+ if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
pwsize |= 1;
write_c0_pwsize(pwsize);
@@ -2345,6 +2351,41 @@ static void config_xpa_params(void)
#endif
}
+static void check_pabits(void)
+{
+ unsigned long entry;
+ unsigned pabits, fillbits;
+
+ if (!cpu_has_rixi || !_PAGE_NO_EXEC) {
+ /*
+ * We'll only be making use of the fact that we can rotate bits
+ * into the fill if the CPU supports RIXI, so don't bother
+ * probing this for CPUs which don't.
+ */
+ return;
+ }
+
+ write_c0_entrylo0(~0ul);
+ back_to_back_c0_hazard();
+ entry = read_c0_entrylo0();
+
+ /* clear all non-PFN bits */
+ entry &= ~((1 << MIPS_ENTRYLO_PFN_SHIFT) - 1);
+ entry &= ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+
+ /* find a lower bound on PABITS, and upper bound on fill bits */
+ pabits = fls_long(entry) + 6;
+ fillbits = max_t(int, (int)BITS_PER_LONG - pabits, 0);
+
+ /* minus the RI & XI bits */
+ fillbits -= min_t(unsigned, fillbits, 2);
+
+ if (fillbits >= ilog2(_PAGE_NO_EXEC))
+ fill_includes_sw_bits = true;
+
+ pr_debug("Entry* registers contain %u fill bits\n", fillbits);
+}
+
void build_tlb_refill_handler(void)
{
/*
@@ -2355,6 +2396,7 @@ void build_tlb_refill_handler(void)
static int run_once = 0;
output_pgtable_bits_defines();
+ check_pabits();
#ifdef CONFIG_64BIT
check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
diff --git a/kernel/arch/mips/mti-malta/Makefile b/kernel/arch/mips/mti-malta/Makefile
index 6510ace27..5827af77c 100644
--- a/kernel/arch/mips/mti-malta/Makefile
+++ b/kernel/arch/mips/mti-malta/Makefile
@@ -5,9 +5,18 @@
# Copyright (C) 2008 Wind River Systems, Inc.
# written by Ralf Baechle <ralf@linux-mips.org>
#
-obj-y := 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-y += malta-display.o
+obj-y += malta-dt.o
+obj-y += malta-dtshim.o
+obj-y += malta-init.o
+obj-y += malta-int.o
+obj-y += malta-memory.o
+obj-y += malta-platform.o
+obj-y += malta-reset.o
+obj-y += malta-setup.o
+obj-y += malta-time.o
obj-$(CONFIG_MIPS_CMP) += malta-amon.o
obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o
+
+CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/kernel/arch/mips/mti-malta/malta-dt.c b/kernel/arch/mips/mti-malta/malta-dt.c
new file mode 100644
index 000000000..47a228892
--- /dev/null
+++ b/kernel/arch/mips/mti-malta/malta-dt.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+void __init device_tree_init(void)
+{
+ unflatten_and_copy_device_tree();
+}
+
+static const struct of_device_id bus_ids[] __initconst = {
+ { .compatible = "simple-bus", },
+ { .compatible = "isa", },
+ {},
+};
+
+static int __init publish_devices(void)
+{
+ if (!of_have_populated_dt())
+ return 0;
+
+ return of_platform_bus_probe(NULL, bus_ids, NULL);
+}
+device_initcall(publish_devices);
diff --git a/kernel/arch/mips/mti-malta/malta-dtshim.c b/kernel/arch/mips/mti-malta/malta-dtshim.c
new file mode 100644
index 000000000..f7133efc5
--- /dev/null
+++ b/kernel/arch/mips/mti-malta/malta-dtshim.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sizes.h>
+#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
+#include <asm/page.h>
+
+static unsigned char fdt_buf[16 << 10] __initdata;
+
+/* determined physical memory size, not overridden by command line args */
+extern unsigned long physical_memsize;
+
+#define MAX_MEM_ARRAY_ENTRIES 1
+
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
+{
+ unsigned long size_preio;
+ unsigned entries;
+
+ entries = 1;
+ mem_array[0] = cpu_to_be32(PHYS_OFFSET);
+ if (config_enabled(CONFIG_EVA)) {
+ /*
+ * The current Malta EVA configuration is "special" in that it
+ * always makes use of addresses in the upper half of the 32 bit
+ * physical address map, which gives it a contiguous region of
+ * DDR but limits it to 2GB.
+ */
+ mem_array[1] = cpu_to_be32(size);
+ } else {
+ size_preio = min_t(unsigned long, size, SZ_256M);
+ mem_array[1] = cpu_to_be32(size_preio);
+ }
+
+ BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
+ return entries;
+}
+
+static void __init append_memory(void *fdt, int root_off)
+{
+ __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
+ unsigned long memsize;
+ unsigned mem_entries;
+ int i, err, mem_off;
+ char *var, param_name[10], *var_names[] = {
+ "ememsize", "memsize",
+ };
+
+ /* if a memory node already exists, leave it alone */
+ mem_off = fdt_path_offset(fdt, "/memory");
+ if (mem_off >= 0)
+ return;
+
+ /* find memory size from the bootloader environment */
+ for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+ var = fw_getenv(var_names[i]);
+ if (!var)
+ continue;
+
+ err = kstrtoul(var, 0, &physical_memsize);
+ if (!err)
+ break;
+
+ pr_warn("Failed to read the '%s' env variable '%s'\n",
+ var_names[i], var);
+ }
+
+ if (!physical_memsize) {
+ pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
+ physical_memsize = 32 << 20;
+ }
+
+ if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
+ /*
+ * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
+ * the last word of physical memory.
+ */
+ physical_memsize -= PAGE_SIZE;
+ }
+
+ /* default to using all available RAM */
+ memsize = physical_memsize;
+
+ /* allow the user to override the usable memory */
+ for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+ snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
+ var = strstr(arcs_cmdline, param_name);
+ if (!var)
+ continue;
+
+ memsize = memparse(var + strlen(param_name), NULL);
+ }
+
+ /* if the user says there's more RAM than we thought, believe them */
+ physical_memsize = max_t(unsigned long, physical_memsize, memsize);
+
+ /* append memory to the DT */
+ mem_off = fdt_add_subnode(fdt, root_off, "memory");
+ if (mem_off < 0)
+ panic("Unable to add memory node to DT: %d", mem_off);
+
+ err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
+ if (err)
+ panic("Unable to set memory node device_type: %d", err);
+
+ mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
+ err = fdt_setprop(fdt, mem_off, "reg", mem_array,
+ mem_entries * 2 * sizeof(mem_array[0]));
+ if (err)
+ panic("Unable to set memory regs property: %d", err);
+
+ mem_entries = gen_fdt_mem_array(mem_array, memsize);
+ err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
+ mem_entries * 2 * sizeof(mem_array[0]));
+ if (err)
+ panic("Unable to set linux,usable-memory property: %d", err);
+}
+
+void __init *malta_dt_shim(void *fdt)
+{
+ int root_off, len, err;
+ const char *compat;
+
+ if (fdt_check_header(fdt))
+ panic("Corrupt DT");
+
+ err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
+ if (err)
+ panic("Unable to open FDT: %d", err);
+
+ root_off = fdt_path_offset(fdt_buf, "/");
+ if (root_off < 0)
+ panic("No / node in DT");
+
+ compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
+ if (!compat)
+ panic("No root compatible property in DT: %d", len);
+
+ /* if this isn't Malta, leave the DT alone */
+ if (strncmp(compat, "mti,malta", len))
+ return fdt;
+
+ append_memory(fdt_buf, root_off);
+
+ err = fdt_pack(fdt_buf);
+ if (err)
+ panic("Unable to pack FDT: %d\n", err);
+
+ return fdt_buf;
+}
diff --git a/kernel/arch/mips/mti-malta/malta-init.c b/kernel/arch/mips/mti-malta/malta-init.c
index cec3e187c..571148c5f 100644
--- a/kernel/arch/mips/mti-malta/malta-init.c
+++ b/kernel/arch/mips/mti-malta/malta-init.c
@@ -302,4 +302,12 @@ mips_pci_controller:
return;
if (!register_vsmp_smp_ops())
return;
+ register_up_smp_ops();
+}
+
+void platform_early_l2_init(void)
+{
+ /* L2 configuration lives in the CM3 */
+ if (mips_cm_revision() >= CM_REV_CM3)
+ mips_cm_probe();
}
diff --git a/kernel/arch/mips/mti-malta/malta-int.c b/kernel/arch/mips/mti-malta/malta-int.c
index d1392f8f5..c6a6c7afd 100644
--- a/kernel/arch/mips/mti-malta/malta-int.c
+++ b/kernel/arch/mips/mti-malta/malta-int.c
@@ -222,7 +222,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
@@ -382,122 +382,12 @@ void malta_be_init(void)
/* Could change CM error mask register. */
}
-
-static char *tr[8] = {
- "mem", "gcr", "gic", "mmio",
- "0x04", "0x05", "0x06", "0x07"
-};
-
-static char *mcmd[32] = {
- [0x00] = "0x00",
- [0x01] = "Legacy Write",
- [0x02] = "Legacy Read",
- [0x03] = "0x03",
- [0x04] = "0x04",
- [0x05] = "0x05",
- [0x06] = "0x06",
- [0x07] = "0x07",
- [0x08] = "Coherent Read Own",
- [0x09] = "Coherent Read Share",
- [0x0a] = "Coherent Read Discard",
- [0x0b] = "Coherent Ready Share Always",
- [0x0c] = "Coherent Upgrade",
- [0x0d] = "Coherent Writeback",
- [0x0e] = "0x0e",
- [0x0f] = "0x0f",
- [0x10] = "Coherent Copyback",
- [0x11] = "Coherent Copyback Invalidate",
- [0x12] = "Coherent Invalidate",
- [0x13] = "Coherent Write Invalidate",
- [0x14] = "Coherent Completion Sync",
- [0x15] = "0x15",
- [0x16] = "0x16",
- [0x17] = "0x17",
- [0x18] = "0x18",
- [0x19] = "0x19",
- [0x1a] = "0x1a",
- [0x1b] = "0x1b",
- [0x1c] = "0x1c",
- [0x1d] = "0x1d",
- [0x1e] = "0x1e",
- [0x1f] = "0x1f"
-};
-
-static char *core[8] = {
- "Invalid/OK", "Invalid/Data",
- "Shared/OK", "Shared/Data",
- "Modified/OK", "Modified/Data",
- "Exclusive/OK", "Exclusive/Data"
-};
-
-static char *causes[32] = {
- "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
- "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
- "0x08", "0x09", "0x0a", "0x0b",
- "0x0c", "0x0d", "0x0e", "0x0f",
- "0x10", "0x11", "0x12", "0x13",
- "0x14", "0x15", "0x16", "INTVN_WR_ERR",
- "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
- "0x1c", "0x1d", "0x1e", "0x1f"
-};
-
int malta_be_handler(struct pt_regs *regs, int is_fixup)
{
/* This duplicates the handling in do_be which seems wrong */
int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
- if (mips_cm_present()) {
- unsigned long cm_error = read_gcr_error_cause();
- unsigned long cm_addr = read_gcr_error_addr();
- unsigned long cm_other = read_gcr_error_mult();
- unsigned long cause, ocause;
- char buf[256];
-
- cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
- if (cause != 0) {
- cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
- if (cause < 16) {
- unsigned long cca_bits = (cm_error >> 15) & 7;
- unsigned long tr_bits = (cm_error >> 12) & 7;
- 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[cmd_bits],
- stag_bits, sport_bits);
- } else {
- /* glob state & sresp together */
- unsigned long c3_bits = (cm_error >> 18) & 7;
- unsigned long c2_bits = (cm_error >> 15) & 7;
- 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 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 "
- "MCmd=%s SPort=%lu\n",
- core[c3_bits], core[c2_bits],
- core[c1_bits], core[c0_bits],
- sc_bit ? "True" : "False",
- mcmd[cmd_bits], sport_bits);
- }
-
- ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
- CM_GCR_ERROR_MULT_ERR2ND_SHF;
-
- pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
- causes[cause], buf);
- pr_err("CM_ADDR =%08lx\n", cm_addr);
- pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
-
- /* reprime cause register */
- write_gcr_error_cause(0);
- }
- }
+ mips_cm_error_report();
return retval;
}
diff --git a/kernel/arch/mips/mti-malta/malta-memory.c b/kernel/arch/mips/mti-malta/malta-memory.c
index b769657be..d5f8dae6a 100644
--- a/kernel/arch/mips/mti-malta/malta-memory.c
+++ b/kernel/arch/mips/mti-malta/malta-memory.c
@@ -21,147 +21,20 @@
#include <asm/sections.h>
#include <asm/fw/fw.h>
-static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS];
-
/* determined physical memory size, not overridden by command line args */
unsigned long physical_memsize = 0L;
-fw_memblock_t * __init fw_getmdesc(int eva)
-{
- char *memsize_str, *ememsize_str = NULL, *ptr;
- unsigned long memsize = 0, ememsize = 0;
- static char cmdline[COMMAND_LINE_SIZE] __initdata;
- int tmp;
-
- /* otherwise look in the environment */
-
- memsize_str = fw_getenv("memsize");
- if (memsize_str) {
- tmp = kstrtoul(memsize_str, 0, &memsize);
- if (tmp)
- pr_warn("Failed to read the 'memsize' env variable.\n");
- }
- if (eva) {
- /* Look for ememsize for EVA */
- ememsize_str = fw_getenv("ememsize");
- if (ememsize_str) {
- tmp = kstrtoul(ememsize_str, 0, &ememsize);
- if (tmp)
- pr_warn("Failed to read the 'ememsize' env variable.\n");
- }
- }
- if (!memsize && !ememsize) {
- pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
- physical_memsize = 0x02000000;
- } else {
- if (memsize > (256 << 20)) { /* memsize should be capped to 256M */
- pr_warn("Unsupported memsize value (0x%lx) detected! "
- "Using 0x10000000 (256M) instead\n",
- memsize);
- memsize = 256 << 20;
- }
- /* If ememsize is set, then set physical_memsize to that */
- physical_memsize = ememsize ? : memsize;
- }
-
-#ifdef CONFIG_CPU_BIG_ENDIAN
- /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
- word of physical memory */
- physical_memsize -= PAGE_SIZE;
-#endif
-
- /* Check the command line for a memsize directive that overrides
- the physical/default amount */
- strcpy(cmdline, arcs_cmdline);
- ptr = strstr(cmdline, "memsize=");
- if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
- ptr = strstr(ptr, " memsize=");
- /* And now look for ememsize */
- if (eva) {
- ptr = strstr(cmdline, "ememsize=");
- if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
- ptr = strstr(ptr, " ememsize=");
- }
-
- if (ptr)
- memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
- else
- memsize = physical_memsize;
-
- /* Last 64K for HIGHMEM arithmetics */
- if (memsize > 0x7fff0000)
- memsize = 0x7fff0000;
-
- memset(mdesc, 0, sizeof(mdesc));
-
- mdesc[0].type = fw_dontuse;
- mdesc[0].base = PHYS_OFFSET;
- mdesc[0].size = 0x00001000;
-
- mdesc[1].type = fw_code;
- mdesc[1].base = mdesc[0].base + 0x00001000UL;
- mdesc[1].size = 0x000ef000;
-
- /*
- * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
- * south bridge and PCI access always forwarded to the ISA Bus and
- * BIOSCS# is always generated.
- * This mean that this area can't be used as DMA memory for PCI
- * devices.
- */
- mdesc[2].type = fw_dontuse;
- mdesc[2].base = mdesc[0].base + 0x000f0000UL;
- mdesc[2].size = 0x00010000;
-
- mdesc[3].type = fw_dontuse;
- mdesc[3].base = mdesc[0].base + 0x00100000UL;
- mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
- 0x00100000UL;
-
- mdesc[4].type = fw_free;
- mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
- mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);
-
- return &mdesc[0];
-}
-
static void free_init_pages_eva_malta(void *begin, void *end)
{
free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
__pa_symbol((unsigned long *)end));
}
-static int __init fw_memtype_classify(unsigned int type)
-{
- switch (type) {
- case fw_free:
- return BOOT_MEM_RAM;
- case fw_code:
- return BOOT_MEM_ROM_DATA;
- default:
- return BOOT_MEM_RESERVED;
- }
-}
-
void __init fw_meminit(void)
{
- fw_memblock_t *p;
-
- p = fw_getmdesc(config_enabled(CONFIG_EVA));
- free_init_pages_eva = (config_enabled(CONFIG_EVA) ?
- free_init_pages_eva_malta : NULL);
-
- while (p->size) {
- long type;
- unsigned long base, size;
-
- type = fw_memtype_classify(p->type);
- base = p->base;
- size = p->size;
+ bool eva = config_enabled(CONFIG_EVA);
- add_memory_region(base, size, type);
- p++;
- }
+ free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
}
void __init prom_free_prom_memory(void)
@@ -179,31 +52,6 @@ void __init prom_free_prom_memory(void)
}
}
-unsigned platform_maar_init(unsigned num_pairs)
-{
- phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
- struct maar_config cfg[] = {
- /* DRAM preceding I/O */
- { 0x00000000, 0x0fffffff, MIPS_MAAR_S },
-
- /* DRAM following I/O */
- { 0x20000000, mem_end, MIPS_MAAR_S },
-
- /* DRAM alias in upper half of physical */
- { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
- };
- unsigned i, num_cfg = ARRAY_SIZE(cfg);
-
- /* If DRAM fits before I/O, drop the region following it */
- if (physical_memsize <= 0x10000000) {
- num_cfg--;
- for (i = 1; i < num_cfg; i++)
- cfg[i] = cfg[i + 1];
- }
-
- return maar_config(cfg, num_cfg, num_pairs);
-}
-
phys_addr_t mips_cdmm_phys_base(void)
{
/* This address is "typically unused" */
diff --git a/kernel/arch/mips/mti-malta/malta-setup.c b/kernel/arch/mips/mti-malta/malta-setup.c
index db7c9e582..4740c82fb 100644
--- a/kernel/arch/mips/mti-malta/malta-setup.c
+++ b/kernel/arch/mips/mti-malta/malta-setup.c
@@ -21,16 +21,19 @@
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/irq.h>
+#include <linux/of_fdt.h>
#include <linux/pci.h>
#include <linux/screen_info.h>
#include <linux/time.h>
#include <asm/fw/fw.h>
+#include <asm/mach-malta/malta-dtshim.h>
#include <asm/mips-cm.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/malta.h>
#include <asm/mips-boards/maltaint.h>
#include <asm/dma.h>
+#include <asm/prom.h>
#include <asm/traps.h>
#ifdef CONFIG_VT
#include <linux/console.h>
@@ -248,6 +251,10 @@ static void __init bonito_quirks_setup(void)
void __init plat_mem_setup(void)
{
unsigned int i;
+ void *fdt = __dtb_start;
+
+ fdt = malta_dt_shim(fdt);
+ __dt_setup_arch(fdt);
if (config_enabled(CONFIG_EVA))
/* EVA has already been configured in mach-malta/kernel-init.h */
diff --git a/kernel/arch/mips/mti-malta/malta-time.c b/kernel/arch/mips/mti-malta/malta-time.c
index a7f7d9ffb..b7bf721ea 100644
--- a/kernel/arch/mips/mti-malta/malta-time.c
+++ b/kernel/arch/mips/mti-malta/malta-time.c
@@ -119,18 +119,24 @@ void read_persistent_clock(struct timespec *ts)
int get_c0_fdc_int(void)
{
- int mips_cpu_fdc_irq;
+ /*
+ * Some cores claim the FDC is routable through the GIC, but it doesn't
+ * actually seem to be connected for those Malta bitstreams.
+ */
+ switch (current_cpu_type()) {
+ case CPU_INTERAPTIV:
+ case CPU_PROAPTIV:
+ return -1;
+ };
if (cpu_has_veic)
- mips_cpu_fdc_irq = -1;
+ return -1;
else if (gic_present)
- mips_cpu_fdc_irq = gic_get_c0_fdc_int();
+ return gic_get_c0_fdc_int();
else if (cp0_fdc_irq >= 0)
- mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
+ return MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
else
- mips_cpu_fdc_irq = -1;
-
- return mips_cpu_fdc_irq;
+ return -1;
}
int get_c0_perfcount_int(void)
diff --git a/kernel/arch/mips/mti-sead3/Makefile b/kernel/arch/mips/mti-sead3/Makefile
index ecd71db62..7a584e0bf 100644
--- a/kernel/arch/mips/mti-sead3/Makefile
+++ b/kernel/arch/mips/mti-sead3/Makefile
@@ -12,8 +12,4 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \
sead3-int.o sead3-platform.o sead3-reset.o \
sead3-setup.o sead3-time.o
-obj-y += leds-sead3.o
-
obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
-
-CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/kernel/arch/mips/mti-sead3/leds-sead3.c b/kernel/arch/mips/mti-sead3/leds-sead3.c
deleted file mode 100644
index c938ceeb8..000000000
--- a/kernel/arch/mips/mti-sead3/leds-sead3.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
- * Copyright (C) 2015 Imagination Technologies, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/mips-boards/sead3-addr.h>
-
-static void sead3_pled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- writel(value, (void __iomem *)SEAD3_CPLD_P_LED);
-}
-
-static void sead3_fled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- writel(value, (void __iomem *)SEAD3_CPLD_F_LED);
-}
-
-static struct led_classdev sead3_pled = {
- .name = "sead3::pled",
- .brightness_set = sead3_pled_set,
- .flags = LED_CORE_SUSPENDRESUME,
-};
-
-static struct led_classdev sead3_fled = {
- .name = "sead3::fled",
- .brightness_set = sead3_fled_set,
- .flags = LED_CORE_SUSPENDRESUME,
-};
-
-static int sead3_led_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = led_classdev_register(&pdev->dev, &sead3_pled);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &sead3_fled);
- if (ret < 0)
- led_classdev_unregister(&sead3_pled);
-
- return ret;
-}
-
-static int sead3_led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&sead3_pled);
- led_classdev_unregister(&sead3_fled);
- return 0;
-}
-
-static struct platform_driver sead3_led_driver = {
- .probe = sead3_led_probe,
- .remove = sead3_led_remove,
- .driver = {
- .name = "sead3-led",
- },
-};
-
-module_platform_driver(sead3_led_driver);
-
-MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
-MODULE_DESCRIPTION("SEAD3 LED driver");
-MODULE_LICENSE("GPL");
diff --git a/kernel/arch/mips/net/Makefile b/kernel/arch/mips/net/Makefile
index ae74b3a91..8c2771401 100644
--- a/kernel/arch/mips/net/Makefile
+++ b/kernel/arch/mips/net/Makefile
@@ -1,3 +1,3 @@
# MIPS networking code
-obj-$(CONFIG_BPF_JIT) += bpf_jit.o
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_asm.o
diff --git a/kernel/arch/mips/net/bpf_jit.c b/kernel/arch/mips/net/bpf_jit.c
index e23fdf2a9..1a8c96035 100644
--- a/kernel/arch/mips/net/bpf_jit.c
+++ b/kernel/arch/mips/net/bpf_jit.c
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <asm/asm.h>
#include <asm/bitops.h>
#include <asm/cacheflush.h>
#include <asm/cpu-features.h>
@@ -28,14 +29,14 @@
#include "bpf_jit.h"
/* ABI
- *
- * s0 1st scratch register
- * s1 2nd scratch register
- * s2 offset register
- * s3 BPF register A
- * s4 BPF register X
- * s5 *skb
- * s6 *scratch memory
+ * r_skb_hl SKB header length
+ * r_data SKB data pointer
+ * r_off Offset
+ * r_A BPF register A
+ * r_X BPF register X
+ * r_skb *skb
+ * r_M *scratch memory
+ * r_skb_len SKB length
*
* On entry (*bpf_func)(*skb, *filter)
* a0 = MIPS_R_A0 = skb;
@@ -63,44 +64,8 @@
* ----------------------------------------------------
*/
-#define RSIZE (sizeof(unsigned long))
#define ptr typeof(unsigned long)
-/* ABI specific return values */
-#ifdef CONFIG_32BIT /* O32 */
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-#define r_err MIPS_R_V1
-#define r_val MIPS_R_V0
-#else /* CONFIG_CPU_LITTLE_ENDIAN */
-#define r_err MIPS_R_V0
-#define r_val MIPS_R_V1
-#endif
-#else /* N64 */
-#define r_err MIPS_R_V0
-#define r_val MIPS_R_V0
-#endif
-
-#define r_ret MIPS_R_V0
-
-/*
- * Use 2 scratch registers to avoid pipeline interlocks.
- * There is no overhead during epilogue and prologue since
- * any of the $s0-$s6 registers will only be preserved if
- * they are going to actually be used.
- */
-#define r_s0 MIPS_R_S0 /* scratch reg 1 */
-#define r_s1 MIPS_R_S1 /* scratch reg 2 */
-#define r_off MIPS_R_S2
-#define r_A MIPS_R_S3
-#define r_X MIPS_R_S4
-#define r_skb MIPS_R_S5
-#define r_M MIPS_R_S6
-#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */
-#define r_tmp MIPS_R_T7 /* No need to preserve this */
-#define r_zero MIPS_R_ZERO
-#define r_sp MIPS_R_SP
-#define r_ra MIPS_R_RA
-
#define SCRATCH_OFF(k) (4 * (k))
/* JIT flags */
@@ -108,13 +73,13 @@
#define SEEN_SREG_SFT (BPF_MEMWORDS + 1)
#define SEEN_SREG_BASE (1 << SEEN_SREG_SFT)
#define SEEN_SREG(x) (SEEN_SREG_BASE << (x))
-#define SEEN_S0 SEEN_SREG(0)
-#define SEEN_S1 SEEN_SREG(1)
#define SEEN_OFF SEEN_SREG(2)
#define SEEN_A SEEN_SREG(3)
#define SEEN_X SEEN_SREG(4)
#define SEEN_SKB SEEN_SREG(5)
#define SEEN_MEM SEEN_SREG(6)
+/* SEEN_SK_DATA also implies skb_hl an skb_len */
+#define SEEN_SKB_DATA (SEEN_SREG(7) | SEEN_SREG(1) | SEEN_SREG(0))
/* Arguments used by JIT */
#define ARGS_USED_BY_JIT 2 /* only applicable to 64-bit */
@@ -556,19 +521,6 @@ static inline u16 align_sp(unsigned int num)
return num;
}
-static bool is_load_to_a(u16 inst)
-{
- switch (inst) {
- case BPF_LD | BPF_W | BPF_LEN:
- case BPF_LD | BPF_W | BPF_ABS:
- case BPF_LD | BPF_H | BPF_ABS:
- case BPF_LD | BPF_B | BPF_ABS:
- return true;
- default:
- return false;
- }
-}
-
static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
{
int i = 0, real_off = 0;
@@ -577,27 +529,13 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
/* Adjust the stack pointer */
emit_stack_offset(-align_sp(offset), ctx);
- if (ctx->flags & SEEN_CALL) {
- /* Argument save area */
- if (config_enabled(CONFIG_64BIT))
- /* Bottom of current frame */
- real_off = align_sp(offset) - RSIZE;
- else
- /* Top of previous frame */
- real_off = align_sp(offset) + RSIZE;
- emit_store_stack_reg(MIPS_R_A0, r_sp, real_off, ctx);
- emit_store_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx);
-
- real_off = 0;
- }
-
tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
/* sflags is essentially a bitmap */
while (tmp_flags) {
if ((sflags >> i) & 0x1) {
emit_store_stack_reg(MIPS_R_S0 + i, r_sp, real_off,
ctx);
- real_off += RSIZE;
+ real_off += SZREG;
}
i++;
tmp_flags >>= 1;
@@ -606,13 +544,13 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
/* save return address */
if (ctx->flags & SEEN_CALL) {
emit_store_stack_reg(r_ra, r_sp, real_off, ctx);
- real_off += RSIZE;
+ real_off += SZREG;
}
/* Setup r_M leaving the alignment gap if necessary */
if (ctx->flags & SEEN_MEM) {
- if (real_off % (RSIZE * 2))
- real_off += RSIZE;
+ if (real_off % (SZREG * 2))
+ real_off += SZREG;
emit_long_instr(ctx, ADDIU, r_M, r_sp, real_off);
}
}
@@ -623,19 +561,6 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx,
int i, real_off = 0;
u32 sflags, tmp_flags;
- if (ctx->flags & SEEN_CALL) {
- if (config_enabled(CONFIG_64BIT))
- /* Bottom of current frame */
- real_off = align_sp(offset) - RSIZE;
- else
- /* Top of previous frame */
- real_off = align_sp(offset) + RSIZE;
- emit_load_stack_reg(MIPS_R_A0, r_sp, real_off, ctx);
- emit_load_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx);
-
- real_off = 0;
- }
-
tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
/* sflags is a bitmap */
i = 0;
@@ -643,7 +568,7 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx,
if ((sflags >> i) & 0x1) {
emit_load_stack_reg(MIPS_R_S0 + i, r_sp, real_off,
ctx);
- real_off += RSIZE;
+ real_off += SZREG;
}
i++;
tmp_flags >>= 1;
@@ -663,30 +588,19 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
/* How may s* regs do we need to preserved? */
- sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * RSIZE;
+ sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * SZREG;
if (ctx->flags & SEEN_MEM)
sp_off += 4 * BPF_MEMWORDS; /* BPF_MEMWORDS are 32-bit */
if (ctx->flags & SEEN_CALL)
- /*
- * The JIT code make calls to external functions using 2
- * arguments. Therefore, for o32 we don't need to allocate
- * space because we don't care if the argumetns are lost
- * across calls. We do need however to preserve incoming
- * arguments but the space is already allocated for us by
- * the caller. On the other hand, for n64, we need to allocate
- * this space ourselves. We need to preserve $ra as well.
- */
- sp_off += config_enabled(CONFIG_64BIT) ?
- (ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE;
+ sp_off += SZREG; /* Space for our ra register */
return sp_off;
}
static void build_prologue(struct jit_ctx *ctx)
{
- u16 first_inst = ctx->skf->insns[0].code;
int sp_off;
/* Calculate the total offset for the stack pointer */
@@ -696,11 +610,24 @@ static void build_prologue(struct jit_ctx *ctx)
if (ctx->flags & SEEN_SKB)
emit_reg_move(r_skb, MIPS_R_A0, ctx);
+ if (ctx->flags & SEEN_SKB_DATA) {
+ /* Load packet length */
+ emit_load(r_skb_len, r_skb, offsetof(struct sk_buff, len),
+ ctx);
+ emit_load(r_tmp, r_skb, offsetof(struct sk_buff, data_len),
+ ctx);
+ /* Load the data pointer */
+ emit_load_ptr(r_skb_data, r_skb,
+ offsetof(struct sk_buff, data), ctx);
+ /* Load the header length */
+ emit_subu(r_skb_hl, r_skb_len, r_tmp, ctx);
+ }
+
if (ctx->flags & SEEN_X)
emit_jit_reg_move(r_X, r_zero, ctx);
/* Do not leak kernel data to userspace */
- if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst)))
+ if (bpf_needs_clear_a(&ctx->skf->insns[0]))
emit_jit_reg_move(r_A, r_zero, ctx);
}
@@ -718,43 +645,17 @@ static void build_epilogue(struct jit_ctx *ctx)
emit_nop(ctx);
}
-static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset)
-{
- u8 ret;
- int err;
-
- err = skb_copy_bits(skb, offset, &ret, 1);
-
- return (u64)err << 32 | ret;
-}
-
-static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset)
-{
- u16 ret;
- int err;
-
- err = skb_copy_bits(skb, offset, &ret, 2);
-
- return (u64)err << 32 | ntohs(ret);
-}
-
-static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset)
-{
- u32 ret;
- int err;
-
- err = skb_copy_bits(skb, offset, &ret, 4);
-
- return (u64)err << 32 | ntohl(ret);
-}
+#define CHOOSE_LOAD_FUNC(K, func) \
+ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \
+ func##_positive)
static int build_body(struct jit_ctx *ctx)
{
- void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
const struct bpf_prog *prog = ctx->skf;
const struct sock_filter *inst;
- unsigned int i, off, load_order, condt;
+ unsigned int i, off, condt;
u32 k, b_off __maybe_unused;
+ u8 (*sk_load_func)(unsigned long *skb, int offset);
for (i = 0; i < prog->len; i++) {
u16 code;
@@ -788,71 +689,46 @@ static int build_body(struct jit_ctx *ctx)
break;
case BPF_LD | BPF_W | BPF_ABS:
/* A <- P[k:4] */
- load_order = 2;
+ sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_word);
goto load;
case BPF_LD | BPF_H | BPF_ABS:
/* A <- P[k:2] */
- load_order = 1;
+ sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_half);
goto load;
case BPF_LD | BPF_B | BPF_ABS:
/* A <- P[k:1] */
- load_order = 0;
+ sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_byte);
load:
- /* the interpreter will deal with the negative K */
- if ((int)k < 0)
- return -ENOTSUPP;
-
emit_load_imm(r_off, k, ctx);
load_common:
- /*
- * We may got here from the indirect loads so
- * return if offset is negative.
- */
- emit_slt(r_s0, r_off, r_zero, ctx);
- emit_bcond(MIPS_COND_NE, r_s0, r_zero,
- b_imm(prog->len, ctx), ctx);
- emit_reg_move(r_ret, r_zero, ctx);
+ ctx->flags |= SEEN_CALL | SEEN_OFF |
+ SEEN_SKB | SEEN_A | SEEN_SKB_DATA;
- ctx->flags |= SEEN_CALL | SEEN_OFF | SEEN_S0 |
- SEEN_SKB | SEEN_A;
-
- emit_load_func(r_s0, (ptr)load_func[load_order],
- ctx);
+ emit_load_func(r_s0, (ptr)sk_load_func, ctx);
emit_reg_move(MIPS_R_A0, r_skb, ctx);
emit_jalr(MIPS_R_RA, r_s0, ctx);
/* Load second argument to delay slot */
emit_reg_move(MIPS_R_A1, r_off, ctx);
/* Check the error value */
- if (config_enabled(CONFIG_64BIT)) {
- /* Get error code from the top 32-bits */
- emit_dsrl32(r_s0, r_val, 0, ctx);
- /* Branch to 3 instructions ahead */
- emit_bcond(MIPS_COND_NE, r_s0, r_zero, 3 << 2,
- ctx);
- } else {
- /* Branch to 3 instructions ahead */
- emit_bcond(MIPS_COND_NE, r_err, r_zero, 3 << 2,
- ctx);
- }
- emit_nop(ctx);
- /* We are good */
- emit_b(b_imm(i + 1, ctx), ctx);
- emit_jit_reg_move(r_A, r_val, ctx);
+ emit_bcond(MIPS_COND_EQ, r_ret, 0, b_imm(i + 1, ctx),
+ ctx);
+ /* Load return register on DS for failures */
+ emit_reg_move(r_ret, r_zero, ctx);
/* Return with error */
emit_b(b_imm(prog->len, ctx), ctx);
- emit_reg_move(r_ret, r_zero, ctx);
+ emit_nop(ctx);
break;
case BPF_LD | BPF_W | BPF_IND:
/* A <- P[X + k:4] */
- load_order = 2;
+ sk_load_func = sk_load_word;
goto load_ind;
case BPF_LD | BPF_H | BPF_IND:
/* A <- P[X + k:2] */
- load_order = 1;
+ sk_load_func = sk_load_half;
goto load_ind;
case BPF_LD | BPF_B | BPF_IND:
/* A <- P[X + k:1] */
- load_order = 0;
+ sk_load_func = sk_load_byte;
load_ind:
ctx->flags |= SEEN_OFF | SEEN_X;
emit_addiu(r_off, r_X, k, ctx);
@@ -874,14 +750,10 @@ load_ind:
emit_load(r_X, r_skb, off, ctx);
break;
case BPF_LDX | BPF_B | BPF_MSH:
- /* the interpreter will deal with the negative K */
- if ((int)k < 0)
- return -ENOTSUPP;
-
/* X <- 4 * (P[k:1] & 0xf) */
- ctx->flags |= SEEN_X | SEEN_CALL | SEEN_S0 | SEEN_SKB;
+ ctx->flags |= SEEN_X | SEEN_CALL | SEEN_SKB;
/* Load offset to a1 */
- emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx);
+ emit_load_func(r_s0, (ptr)sk_load_byte, ctx);
/*
* This may emit two instructions so it may not fit
* in the delay slot. So use a0 in the delay slot.
@@ -890,25 +762,15 @@ load_ind:
emit_jalr(MIPS_R_RA, r_s0, ctx);
emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */
/* Check the error value */
- if (config_enabled(CONFIG_64BIT)) {
- /* Top 32-bits of $v0 on 64-bit */
- emit_dsrl32(r_s0, r_val, 0, ctx);
- emit_bcond(MIPS_COND_NE, r_s0, r_zero,
- 3 << 2, ctx);
- } else {
- emit_bcond(MIPS_COND_NE, r_err, r_zero,
- 3 << 2, ctx);
- }
- /* No need for delay slot */
+ emit_bcond(MIPS_COND_NE, r_ret, 0,
+ b_imm(prog->len, ctx), ctx);
+ emit_reg_move(r_ret, r_zero, ctx);
/* We are good */
/* X <- P[1:K] & 0xf */
- emit_andi(r_X, r_val, 0xf, ctx);
+ emit_andi(r_X, r_A, 0xf, ctx);
/* X << 2 */
emit_b(b_imm(i + 1, ctx), ctx);
emit_sll(r_X, r_X, 2, ctx); /* delay slot */
- /* Return with error */
- emit_b(b_imm(prog->len, ctx), ctx);
- emit_load_imm(r_ret, 0, ctx); /* delay slot */
break;
case BPF_ST:
/* M[k] <- A */
@@ -943,7 +805,7 @@ load_ind:
case BPF_ALU | BPF_MUL | BPF_K:
/* A *= K */
/* Load K to scratch register before MUL */
- ctx->flags |= SEEN_A | SEEN_S0;
+ ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx);
emit_mul(r_A, r_A, r_s0, ctx);
break;
@@ -961,7 +823,7 @@ load_ind:
emit_srl(r_A, r_A, k, ctx);
break;
}
- ctx->flags |= SEEN_A | SEEN_S0;
+ ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx);
emit_div(r_A, r_s0, ctx);
break;
@@ -971,7 +833,7 @@ load_ind:
ctx->flags |= SEEN_A;
emit_jit_reg_move(r_A, r_zero, ctx);
} else {
- ctx->flags |= SEEN_A | SEEN_S0;
+ ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx);
emit_mod(r_A, r_s0, ctx);
}
@@ -982,7 +844,7 @@ load_ind:
/* Check if r_X is zero */
emit_bcond(MIPS_COND_EQ, r_X, r_zero,
b_imm(prog->len, ctx), ctx);
- emit_load_imm(r_val, 0, ctx); /* delay slot */
+ emit_load_imm(r_ret, 0, ctx); /* delay slot */
emit_div(r_A, r_X, ctx);
break;
case BPF_ALU | BPF_MOD | BPF_X:
@@ -991,7 +853,7 @@ load_ind:
/* Check if r_X is zero */
emit_bcond(MIPS_COND_EQ, r_X, r_zero,
b_imm(prog->len, ctx), ctx);
- emit_load_imm(r_val, 0, ctx); /* delay slot */
+ emit_load_imm(r_ret, 0, ctx); /* delay slot */
emit_mod(r_A, r_X, ctx);
break;
case BPF_ALU | BPF_OR | BPF_K:
@@ -1085,10 +947,10 @@ jmp_cmp:
if ((condt & MIPS_COND_GE) ||
(condt & MIPS_COND_GT)) {
if (condt & MIPS_COND_K) { /* K */
- ctx->flags |= SEEN_S0 | SEEN_A;
+ ctx->flags |= SEEN_A;
emit_sltiu(r_s0, r_A, k, ctx);
} else { /* X */
- ctx->flags |= SEEN_S0 | SEEN_A |
+ ctx->flags |= SEEN_A |
SEEN_X;
emit_sltu(r_s0, r_A, r_X, ctx);
}
@@ -1100,7 +962,7 @@ jmp_cmp:
/* A > (K|X) ? scratch = 0 */
if (condt & MIPS_COND_GT) {
/* Checking for equality */
- ctx->flags |= SEEN_S0 | SEEN_A | SEEN_X;
+ ctx->flags |= SEEN_A | SEEN_X;
if (condt & MIPS_COND_K)
emit_load_imm(r_s0, k, ctx);
else
@@ -1123,7 +985,7 @@ jmp_cmp:
} else {
/* A == K|X */
if (condt & MIPS_COND_K) { /* K */
- ctx->flags |= SEEN_S0 | SEEN_A;
+ ctx->flags |= SEEN_A;
emit_load_imm(r_s0, k, ctx);
/* jump true */
b_off = b_imm(i + inst->jt + 1, ctx);
@@ -1153,7 +1015,7 @@ jmp_cmp:
}
break;
case BPF_JMP | BPF_JSET | BPF_K:
- ctx->flags |= SEEN_S0 | SEEN_S1 | SEEN_A;
+ ctx->flags |= SEEN_A;
/* pc += (A & K) ? pc -> jt : pc -> jf */
emit_load_imm(r_s1, k, ctx);
emit_and(r_s0, r_A, r_s1, ctx);
@@ -1167,7 +1029,7 @@ jmp_cmp:
emit_nop(ctx);
break;
case BPF_JMP | BPF_JSET | BPF_X:
- ctx->flags |= SEEN_S0 | SEEN_X | SEEN_A;
+ ctx->flags |= SEEN_X | SEEN_A;
/* pc += (A & X) ? pc -> jt : pc -> jf */
emit_and(r_s0, r_A, r_X, ctx);
/* jump true */
@@ -1251,7 +1113,7 @@ jmp_cmp:
break;
case BPF_ANC | SKF_AD_IFINDEX:
/* A = skb->dev->ifindex */
- ctx->flags |= SEEN_SKB | SEEN_A | SEEN_S0;
+ ctx->flags |= SEEN_SKB | SEEN_A;
off = offsetof(struct sk_buff, dev);
/* Load *dev pointer */
emit_load_ptr(r_s0, r_skb, off, ctx);
@@ -1278,7 +1140,7 @@ jmp_cmp:
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
- ctx->flags |= SEEN_SKB | SEEN_S0 | SEEN_A;
+ ctx->flags |= SEEN_SKB | SEEN_A;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci);
@@ -1375,7 +1237,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
fp->bpf_func = (void *)ctx.target;
- fp->jited = true;
+ fp->jited = 1;
out:
kfree(ctx.offsets);
diff --git a/kernel/arch/mips/net/bpf_jit.h b/kernel/arch/mips/net/bpf_jit.h
index 3a5751b43..8f9f54841 100644
--- a/kernel/arch/mips/net/bpf_jit.h
+++ b/kernel/arch/mips/net/bpf_jit.h
@@ -15,9 +15,10 @@
/* Registers used by JIT */
#define MIPS_R_ZERO 0
#define MIPS_R_V0 2
-#define MIPS_R_V1 3
#define MIPS_R_A0 4
#define MIPS_R_A1 5
+#define MIPS_R_T4 12
+#define MIPS_R_T5 13
#define MIPS_R_T6 14
#define MIPS_R_T7 15
#define MIPS_R_S0 16
@@ -41,4 +42,43 @@
#define MIPS_COND_X (0x1 << 5)
#define MIPS_COND_K (0x1 << 6)
+#define r_ret MIPS_R_V0
+
+/*
+ * Use 2 scratch registers to avoid pipeline interlocks.
+ * There is no overhead during epilogue and prologue since
+ * any of the $s0-$s6 registers will only be preserved if
+ * they are going to actually be used.
+ */
+#define r_skb_hl MIPS_R_S0 /* skb header length */
+#define r_skb_data MIPS_R_S1 /* skb actual data */
+#define r_off MIPS_R_S2
+#define r_A MIPS_R_S3
+#define r_X MIPS_R_S4
+#define r_skb MIPS_R_S5
+#define r_M MIPS_R_S6
+#define r_skb_len MIPS_R_S7
+#define r_s0 MIPS_R_T4 /* scratch reg 1 */
+#define r_s1 MIPS_R_T5 /* scratch reg 2 */
+#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */
+#define r_tmp MIPS_R_T7 /* No need to preserve this */
+#define r_zero MIPS_R_ZERO
+#define r_sp MIPS_R_SP
+#define r_ra MIPS_R_RA
+
+#ifndef __ASSEMBLY__
+
+/* Declare ASM helpers */
+
+#define DECLARE_LOAD_FUNC(func) \
+ extern u8 func(unsigned long *skb, int offset); \
+ extern u8 func##_negative(unsigned long *skb, int offset); \
+ extern u8 func##_positive(unsigned long *skb, int offset)
+
+DECLARE_LOAD_FUNC(sk_load_word);
+DECLARE_LOAD_FUNC(sk_load_half);
+DECLARE_LOAD_FUNC(sk_load_byte);
+
+#endif
+
#endif /* BPF_JIT_MIPS_OP_H */
diff --git a/kernel/arch/mips/net/bpf_jit_asm.S b/kernel/arch/mips/net/bpf_jit_asm.S
new file mode 100644
index 000000000..5d2e0c8d2
--- /dev/null
+++ b/kernel/arch/mips/net/bpf_jit_asm.S
@@ -0,0 +1,283 @@
+/*
+ * bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF
+ * compiler.
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include "bpf_jit.h"
+
+/* ABI
+ *
+ * r_skb_hl skb header length
+ * r_skb_data skb data
+ * r_off(a1) offset register
+ * r_A BPF register A
+ * r_X PF register X
+ * r_skb(a0) *skb
+ * r_M *scratch memory
+ * r_skb_le skb length
+ * r_s0 Scratch register 0
+ * r_s1 Scratch register 1
+ *
+ * On entry:
+ * a0: *skb
+ * a1: offset (imm or imm + X)
+ *
+ * All non-BPF-ABI registers are free for use. On return, we only
+ * care about r_ret. The BPF-ABI registers are assumed to remain
+ * unmodified during the entire filter operation.
+ */
+
+#define skb a0
+#define offset a1
+#define SKF_LL_OFF (-0x200000) /* Can't include linux/filter.h in assembly */
+
+ /* We know better :) so prevent assembler reordering etc */
+ .set noreorder
+
+#define is_offset_negative(TYPE) \
+ /* If offset is negative we have more work to do */ \
+ slti t0, offset, 0; \
+ bgtz t0, bpf_slow_path_##TYPE##_neg; \
+ /* Be careful what follows in DS. */
+
+#define is_offset_in_header(SIZE, TYPE) \
+ /* Reading from header? */ \
+ addiu $r_s0, $r_skb_hl, -SIZE; \
+ slt t0, $r_s0, offset; \
+ bgtz t0, bpf_slow_path_##TYPE; \
+
+LEAF(sk_load_word)
+ is_offset_negative(word)
+FEXPORT(sk_load_word_positive)
+ is_offset_in_header(4, word)
+ /* Offset within header boundaries */
+ PTR_ADDU t1, $r_skb_data, offset
+ .set reorder
+ lw $r_A, 0(t1)
+ .set noreorder
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
+ wsbh t0, $r_A
+ rotr $r_A, t0, 16
+# else
+ sll t0, $r_A, 24
+ srl t1, $r_A, 24
+ srl t2, $r_A, 8
+ or t0, t0, t1
+ andi t2, t2, 0xff00
+ andi t1, $r_A, 0xff00
+ or t0, t0, t2
+ sll t1, t1, 8
+ or $r_A, t0, t1
+# endif
+#endif
+ jr $r_ra
+ move $r_ret, zero
+ END(sk_load_word)
+
+LEAF(sk_load_half)
+ is_offset_negative(half)
+FEXPORT(sk_load_half_positive)
+ is_offset_in_header(2, half)
+ /* Offset within header boundaries */
+ PTR_ADDU t1, $r_skb_data, offset
+ .set reorder
+ lh $r_A, 0(t1)
+ .set noreorder
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
+ wsbh t0, $r_A
+ seh $r_A, t0
+# else
+ sll t0, $r_A, 24
+ andi t1, $r_A, 0xff00
+ sra t0, t0, 16
+ srl t1, t1, 8
+ or $r_A, t0, t1
+# endif
+#endif
+ jr $r_ra
+ move $r_ret, zero
+ END(sk_load_half)
+
+LEAF(sk_load_byte)
+ is_offset_negative(byte)
+FEXPORT(sk_load_byte_positive)
+ is_offset_in_header(1, byte)
+ /* Offset within header boundaries */
+ PTR_ADDU t1, $r_skb_data, offset
+ lb $r_A, 0(t1)
+ jr $r_ra
+ move $r_ret, zero
+ END(sk_load_byte)
+
+/*
+ * call skb_copy_bits:
+ * (prototype in linux/skbuff.h)
+ *
+ * int skb_copy_bits(sk_buff *skb, int offset, void *to, int len)
+ *
+ * o32 mandates we leave 4 spaces for argument registers in case
+ * the callee needs to use them. Even though we don't care about
+ * the argument registers ourselves, we need to allocate that space
+ * to remain ABI compliant since the callee may want to use that space.
+ * We also allocate 2 more spaces for $r_ra and our return register (*to).
+ *
+ * n64 is a bit different. The *caller* will allocate the space to preserve
+ * the arguments. So in 64-bit kernels, we allocate the 4-arg space for no
+ * good reason but it does not matter that much really.
+ *
+ * (void *to) is returned in r_s0
+ *
+ */
+#define bpf_slow_path_common(SIZE) \
+ /* Quick check. Are we within reasonable boundaries? */ \
+ LONG_ADDIU $r_s1, $r_skb_len, -SIZE; \
+ sltu $r_s0, offset, $r_s1; \
+ beqz $r_s0, fault; \
+ /* Load 4th argument in DS */ \
+ LONG_ADDIU a3, zero, SIZE; \
+ PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
+ PTR_LA t0, skb_copy_bits; \
+ PTR_S $r_ra, (5 * SZREG)($r_sp); \
+ /* Assign low slot to a2 */ \
+ move a2, $r_sp; \
+ jalr t0; \
+ /* Reset our destination slot (DS but it's ok) */ \
+ INT_S zero, (4 * SZREG)($r_sp); \
+ /* \
+ * skb_copy_bits returns 0 on success and -EFAULT \
+ * on error. Our data live in a2. Do not bother with \
+ * our data if an error has been returned. \
+ */ \
+ /* Restore our frame */ \
+ PTR_L $r_ra, (5 * SZREG)($r_sp); \
+ INT_L $r_s0, (4 * SZREG)($r_sp); \
+ bltz v0, fault; \
+ PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
+ move $r_ret, zero; \
+
+NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
+ bpf_slow_path_common(4)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
+ wsbh t0, $r_s0
+ jr $r_ra
+ rotr $r_A, t0, 16
+# else
+ sll t0, $r_s0, 24
+ srl t1, $r_s0, 24
+ srl t2, $r_s0, 8
+ or t0, t0, t1
+ andi t2, t2, 0xff00
+ andi t1, $r_s0, 0xff00
+ or t0, t0, t2
+ sll t1, t1, 8
+ jr $r_ra
+ or $r_A, t0, t1
+# endif
+#else
+ jr $r_ra
+ move $r_A, $r_s0
+#endif
+
+ END(bpf_slow_path_word)
+
+NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
+ bpf_slow_path_common(2)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
+ jr $r_ra
+ wsbh $r_A, $r_s0
+# else
+ sll t0, $r_s0, 8
+ andi t1, $r_s0, 0xff00
+ andi t0, t0, 0xff00
+ srl t1, t1, 8
+ jr $r_ra
+ or $r_A, t0, t1
+# endif
+#else
+ jr $r_ra
+ move $r_A, $r_s0
+#endif
+
+ END(bpf_slow_path_half)
+
+NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp)
+ bpf_slow_path_common(1)
+ jr $r_ra
+ move $r_A, $r_s0
+
+ END(bpf_slow_path_byte)
+
+/*
+ * Negative entry points
+ */
+ .macro bpf_is_end_of_data
+ li t0, SKF_LL_OFF
+ /* Reading link layer data? */
+ slt t1, offset, t0
+ bgtz t1, fault
+ /* Be careful what follows in DS. */
+ .endm
+/*
+ * call skb_copy_bits:
+ * (prototype in linux/filter.h)
+ *
+ * void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb,
+ * int k, unsigned int size)
+ *
+ * see above (bpf_slow_path_common) for ABI restrictions
+ */
+#define bpf_negative_common(SIZE) \
+ PTR_ADDIU $r_sp, $r_sp, -(6 * SZREG); \
+ PTR_LA t0, bpf_internal_load_pointer_neg_helper; \
+ PTR_S $r_ra, (5 * SZREG)($r_sp); \
+ jalr t0; \
+ li a2, SIZE; \
+ PTR_L $r_ra, (5 * SZREG)($r_sp); \
+ /* Check return pointer */ \
+ beqz v0, fault; \
+ PTR_ADDIU $r_sp, $r_sp, 6 * SZREG; \
+ /* Preserve our pointer */ \
+ move $r_s0, v0; \
+ /* Set return value */ \
+ move $r_ret, zero; \
+
+bpf_slow_path_word_neg:
+ bpf_is_end_of_data
+NESTED(sk_load_word_negative, (6 * SZREG), $r_sp)
+ bpf_negative_common(4)
+ jr $r_ra
+ lw $r_A, 0($r_s0)
+ END(sk_load_word_negative)
+
+bpf_slow_path_half_neg:
+ bpf_is_end_of_data
+NESTED(sk_load_half_negative, (6 * SZREG), $r_sp)
+ bpf_negative_common(2)
+ jr $r_ra
+ lhu $r_A, 0($r_s0)
+ END(sk_load_half_negative)
+
+bpf_slow_path_byte_neg:
+ bpf_is_end_of_data
+NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp)
+ bpf_negative_common(1)
+ jr $r_ra
+ lbu $r_A, 0($r_s0)
+ END(sk_load_byte_negative)
+
+fault:
+ jr $r_ra
+ addiu $r_ret, zero, 1
diff --git a/kernel/arch/mips/netlogic/common/irq.c b/kernel/arch/mips/netlogic/common/irq.c
index 5f5d18b0e..3660dc67d 100644
--- a/kernel/arch/mips/netlogic/common/irq.c
+++ b/kernel/arch/mips/netlogic/common/irq.c
@@ -87,7 +87,7 @@ struct nlm_pic_irq {
static void xlp_pic_enable(struct irq_data *d)
{
unsigned long flags;
- struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+ struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
BUG_ON(!pd);
spin_lock_irqsave(&pd->node->piclock, flags);
@@ -97,7 +97,7 @@ static void xlp_pic_enable(struct irq_data *d)
static void xlp_pic_disable(struct irq_data *d)
{
- struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+ struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
unsigned long flags;
BUG_ON(!pd);
@@ -108,7 +108,7 @@ static void xlp_pic_disable(struct irq_data *d)
static void xlp_pic_mask_ack(struct irq_data *d)
{
- struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+ struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
clear_c0_eimr(pd->picirq);
ack_c0_eirr(pd->picirq);
@@ -116,7 +116,7 @@ static void xlp_pic_mask_ack(struct irq_data *d)
static void xlp_pic_unmask(struct irq_data *d)
{
- struct nlm_pic_irq *pd = irq_data_get_irq_handler_data(d);
+ struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
BUG_ON(!pd);
@@ -193,7 +193,7 @@ void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
pic_data->picirq = picirq;
pic_data->node = nlm_get_node(node);
irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
- irq_set_handler_data(xirq, pic_data);
+ irq_set_chip_data(xirq, pic_data);
}
void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
@@ -202,7 +202,7 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
int xirq;
xirq = nlm_irq_to_xirq(node, irq);
- pic_data = irq_get_handler_data(xirq);
+ pic_data = irq_get_chip_data(xirq);
if (WARN_ON(!pic_data))
return;
pic_data->extra_ack = xack;
diff --git a/kernel/arch/mips/netlogic/common/nlm-dma.c b/kernel/arch/mips/netlogic/common/nlm-dma.c
index f3d4ae87a..3758715d4 100644
--- a/kernel/arch/mips/netlogic/common/nlm-dma.c
+++ b/kernel/arch/mips/netlogic/common/nlm-dma.c
@@ -47,11 +47,6 @@ static char *nlm_swiotlb;
static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
- void *ret;
-
- if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
- return ret;
-
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
@@ -69,11 +64,6 @@ static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
static void nlm_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
{
- int order = get_order(size);
-
- if (dma_release_from_coherent(dev, order, vaddr))
- return;
-
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/kernel/arch/mips/netlogic/common/smp.c b/kernel/arch/mips/netlogic/common/smp.c
index dc3e327fb..10d86d548 100644
--- a/kernel/arch/mips/netlogic/common/smp.c
+++ b/kernel/arch/mips/netlogic/common/smp.c
@@ -82,17 +82,19 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
}
/* IRQ_IPI_SMP_FUNCTION Handler */
-void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
+void nlm_smp_function_ipi_handler(struct irq_desc *desc)
{
+ unsigned int irq = irq_desc_get_irq(desc);
clear_c0_eimr(irq);
ack_c0_eirr(irq);
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
set_c0_eimr(irq);
}
/* IRQ_IPI_SMP_RESCHEDULE handler */
-void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
+void nlm_smp_resched_ipi_handler(struct irq_desc *desc)
{
+ unsigned int irq = irq_desc_get_irq(desc);
clear_c0_eimr(irq);
ack_c0_eirr(irq);
scheduler_ipi();
diff --git a/kernel/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/kernel/arch/mips/netlogic/xlp/ahci-init-xlp2.c
index 7b066a44e..c11b9c7dc 100644
--- a/kernel/arch/mips/netlogic/xlp/ahci-init-xlp2.c
+++ b/kernel/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -152,7 +152,7 @@ static const u8 sata_phy_config1[] = {
0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
};
-/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */
+/* SATA PHY config for register block 2 0x8065 .. 0x80A4 */
static const u8 sata_phy_config2[] = {
0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
diff --git a/kernel/arch/mips/netlogic/xlp/dt.c b/kernel/arch/mips/netlogic/xlp/dt.c
index a625bdb6d..856a6e6d2 100644
--- a/kernel/arch/mips/netlogic/xlp/dt.c
+++ b/kernel/arch/mips/netlogic/xlp/dt.c
@@ -87,7 +87,6 @@ void __init *xlp_dt_init(void *fdtp)
void __init xlp_early_init_devtree(void)
{
__dt_setup_arch(xlp_fdt_blob);
- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
}
void __init device_tree_init(void)
diff --git a/kernel/arch/mips/netlogic/xlp/nlm_hal.c b/kernel/arch/mips/netlogic/xlp/nlm_hal.c
index a8f4144a0..80ec92974 100644
--- a/kernel/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/kernel/arch/mips/netlogic/xlp/nlm_hal.c
@@ -91,6 +91,8 @@ static int xlp9xx_irq_to_irt(int irq)
return 134;
case PIC_SATA_IRQ:
return 143;
+ case PIC_NAND_IRQ:
+ return 151;
case PIC_SPI_IRQ:
return 152;
case PIC_MMC_IRQ:
diff --git a/kernel/arch/mips/netlogic/xlr/platform-flash.c b/kernel/arch/mips/netlogic/xlr/platform-flash.c
index 6d3c727e0..f03131fec 100644
--- a/kernel/arch/mips/netlogic/xlr/platform-flash.c
+++ b/kernel/arch/mips/netlogic/xlr/platform-flash.c
@@ -78,8 +78,6 @@ static struct platform_device xlr_nor_dev = {
.resource = xlr_nor_res,
};
-const char *xlr_part_probes[] = { "cmdlinepart", NULL };
-
/*
* Use "gen_nand" driver for NAND flash
*
@@ -111,7 +109,6 @@ struct platform_nand_data xlr_nand_data = {
.nr_partitions = ARRAY_SIZE(xlr_nand_parts),
.chip_delay = 50,
.partitions = xlr_nand_parts,
- .part_probe_types = xlr_part_probes,
},
.ctrl = {
.cmd_ctrl = xlr_nand_ctrl,
diff --git a/kernel/arch/mips/oprofile/common.c b/kernel/arch/mips/oprofile/common.c
index 81f58958c..3c9ec3ddc 100644
--- a/kernel/arch/mips/oprofile/common.c
+++ b/kernel/arch/mips/oprofile/common.c
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_INTERAPTIV:
case CPU_PROAPTIV:
case CPU_P5600:
+ case CPU_I6400:
case CPU_M5150:
case CPU_LOONGSON1:
case CPU_SB1:
diff --git a/kernel/arch/mips/oprofile/op_model_mipsxx.c b/kernel/arch/mips/oprofile/op_model_mipsxx.c
index 6a6e2cc55..8f988a61b 100644
--- a/kernel/arch/mips/oprofile/op_model_mipsxx.c
+++ b/kernel/arch/mips/oprofile/op_model_mipsxx.c
@@ -392,6 +392,10 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/P5600";
break;
+ case CPU_I6400:
+ op_model_mipsxx_ops.cpu_type = "mips/I6400";
+ break;
+
case CPU_M5150:
op_model_mipsxx_ops.cpu_type = "mips/M5150";
break;
diff --git a/kernel/arch/mips/paravirt/paravirt-smp.c b/kernel/arch/mips/paravirt/paravirt-smp.c
index 42181c710..f8d3e081b 100644
--- a/kernel/arch/mips/paravirt/paravirt-smp.c
+++ b/kernel/arch/mips/paravirt/paravirt-smp.c
@@ -114,7 +114,7 @@ static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/kernel/arch/mips/pci/fixup-cobalt.c b/kernel/arch/mips/pci/fixup-cobalt.c
index a138e8ee5..b3ab59318 100644
--- a/kernel/arch/mips/pci/fixup-cobalt.c
+++ b/kernel/arch/mips/pci/fixup-cobalt.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/pci.h>
#include <asm/io.h>
#include <asm/gt64120.h>
diff --git a/kernel/arch/mips/pci/msi-octeon.c b/kernel/arch/mips/pci/msi-octeon.c
index cffaaf4aa..2a5bb849b 100644
--- a/kernel/arch/mips/pci/msi-octeon.c
+++ b/kernel/arch/mips/pci/msi-octeon.c
@@ -200,7 +200,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
- list_for_each_entry(entry, &dev->msi_list, list) {
+ for_each_pci_msi_entry(entry, dev) {
ret = arch_setup_msi_irq(dev, entry);
if (ret < 0)
return ret;
diff --git a/kernel/arch/mips/pci/msi-xlp.c b/kernel/arch/mips/pci/msi-xlp.c
index 3407495fc..bb14335f8 100644
--- a/kernel/arch/mips/pci/msi-xlp.c
+++ b/kernel/arch/mips/pci/msi-xlp.c
@@ -131,7 +131,7 @@ struct xlp_msi_data {
*/
static void xlp_msi_enable(struct irq_data *d)
{
- struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
unsigned long flags;
int vec;
@@ -148,7 +148,7 @@ static void xlp_msi_enable(struct irq_data *d)
static void xlp_msi_disable(struct irq_data *d)
{
- struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
unsigned long flags;
int vec;
@@ -165,7 +165,7 @@ static void xlp_msi_disable(struct irq_data *d)
static void xlp_msi_mask_ack(struct irq_data *d)
{
- struct xlp_msi_data *md = irq_data_get_irq_handler_data(d);
+ struct xlp_msi_data *md = irq_data_get_irq_chip_data(d);
int link, vec;
link = nlm_irq_msilink(d->irq);
@@ -211,7 +211,7 @@ static void xlp_msix_mask_ack(struct irq_data *d)
msixvec = nlm_irq_msixvec(d->irq);
link = nlm_irq_msixlink(msixvec);
pci_msi_mask_irq(d);
- md = irq_data_get_irq_handler_data(d);
+ md = irq_data_get_irq_chip_data(d);
/* Ack MSI on bridge */
if (cpu_is_xlp9xx()) {
@@ -302,7 +302,7 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
/* 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);
+ md = irq_get_chip_data(xirq);
msiaddr = MSI_LINK_ADDR(node, link);
spin_lock_irqsave(&md->msi_lock, flags);
@@ -409,7 +409,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
/* 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);
+ md = irq_get_chip_data(xirq);
msixaddr = MSIX_LINK_ADDR(node, link);
spin_lock_irqsave(&md->msi_lock, flags);
@@ -485,7 +485,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
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);
+ irq_set_chip_data(i, md);
}
for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
@@ -508,7 +508,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
/* 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);
+ irq_set_chip_data(irq, md);
}
}
@@ -520,7 +520,7 @@ void nlm_dispatch_msi(int node, int lirq)
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);
+ md = irq_get_chip_data(irqbase);
if (cpu_is_xlp9xx())
status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
md->msi_enabled_mask;
@@ -550,7 +550,7 @@ void nlm_dispatch_msix(int node, int lirq)
link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
- md = irq_get_handler_data(irqbase);
+ md = irq_get_chip_data(irqbase);
if (cpu_is_xlp9xx())
status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
else
diff --git a/kernel/arch/mips/pci/ops-emma2rh.c b/kernel/arch/mips/pci/ops-emma2rh.c
index 710aef5c0..2dc97c456 100644
--- a/kernel/arch/mips/pci/ops-emma2rh.c
+++ b/kernel/arch/mips/pci/ops-emma2rh.c
@@ -25,7 +25,6 @@
#include <linux/types.h>
#include <asm/addrspace.h>
-#include <asm/debug.h>
#include <asm/emma/emma2rh.h>
@@ -40,10 +39,9 @@
static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num)
{
/* check if the bus is top-level */
- if (bus->parent != NULL) {
+ if (bus->parent != NULL)
*bus_num = bus->number;
- db_assert(bus_num != NULL);
- } else
+ else
*bus_num = 0;
if (*bus_num == 0) {
diff --git a/kernel/arch/mips/pci/ops-mace.c b/kernel/arch/mips/pci/ops-mace.c
index 6b5821feb..951d8070f 100644
--- a/kernel/arch/mips/pci/ops-mace.c
+++ b/kernel/arch/mips/pci/ops-mace.c
@@ -8,7 +8,6 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/types.h>
-#include <asm/pci.h>
#include <asm/ip32/mace.h>
#if 0
diff --git a/kernel/arch/mips/pci/pci-ar2315.c b/kernel/arch/mips/pci/pci-ar2315.c
index 07a18228e..b4fa6413c 100644
--- a/kernel/arch/mips/pci/pci-ar2315.c
+++ b/kernel/arch/mips/pci/pci-ar2315.c
@@ -318,9 +318,9 @@ static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc)
return 0;
}
-static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar2315_pci_irq_handler(struct irq_desc *desc)
{
- struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq);
+ struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc);
u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
ar2315_pci_reg_read(apc, AR2315_PCI_IMR);
unsigned pci_irq = 0;
@@ -384,8 +384,8 @@ static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc)
apc->irq_ext = irq_create_mapping(apc->domain, AR2315_PCI_IRQ_EXT);
- irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler);
- irq_set_handler_data(apc->irq, apc);
+ irq_set_chained_handler_and_data(apc->irq, ar2315_pci_irq_handler,
+ apc);
/* Clear any pending Abort or external Interrupts
* and enable interrupt processing */
diff --git a/kernel/arch/mips/pci/pci-ar71xx.c b/kernel/arch/mips/pci/pci-ar71xx.c
index 9e62ad31d..7db963dee 100644
--- a/kernel/arch/mips/pci/pci-ar71xx.c
+++ b/kernel/arch/mips/pci/pci-ar71xx.c
@@ -226,13 +226,13 @@ static struct pci_ops ar71xx_pci_ops = {
.write = ar71xx_pci_write_config,
};
-static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ar71xx_pci_irq_handler(struct irq_desc *desc)
{
struct ar71xx_pci_controller *apc;
void __iomem *base = ath79_reset_base;
u32 pending;
- apc = irq_get_handler_data(irq);
+ apc = irq_desc_get_handler_data(desc);
pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
@@ -312,29 +312,19 @@ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
irq_set_chip_data(i, apc);
}
- irq_set_handler_data(apc->irq, apc);
- irq_set_chained_handler(apc->irq, ar71xx_pci_irq_handler);
+ irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+ apc);
}
static void ar71xx_pci_reset(void)
{
- void __iomem *ddr_base = ath79_ddr_base;
-
ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
mdelay(100);
ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
mdelay(100);
- __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0);
- __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1);
- __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2);
- __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3);
- __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4);
- __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5);
- __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6);
- __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7);
-
+ ath79_ddr_set_pci_windows();
mdelay(100);
}
diff --git a/kernel/arch/mips/pci/pci-ar724x.c b/kernel/arch/mips/pci/pci-ar724x.c
index a1b7d2a1b..2013dad70 100644
--- a/kernel/arch/mips/pci/pci-ar724x.c
+++ b/kernel/arch/mips/pci/pci-ar724x.c
@@ -225,13 +225,13 @@ static struct pci_ops ar724x_pci_ops = {
.write = ar724x_pci_write,
};
-static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ar724x_pci_irq_handler(struct irq_desc *desc)
{
struct ar724x_pci_controller *apc;
void __iomem *base;
u32 pending;
- apc = irq_get_handler_data(irq);
+ apc = irq_desc_get_handler_data(desc);
base = apc->ctrl_base;
pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
@@ -321,8 +321,8 @@ static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
irq_set_chip_data(i, apc);
}
- irq_set_handler_data(apc->irq, apc);
- irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler);
+ irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
+ apc);
}
static int ar724x_pci_probe(struct platform_device *pdev)
diff --git a/kernel/arch/mips/pci/pci-lantiq.c b/kernel/arch/mips/pci/pci-lantiq.c
index 8b117e638..6a15dbd08 100644
--- a/kernel/arch/mips/pci/pci-lantiq.c
+++ b/kernel/arch/mips/pci/pci-lantiq.c
@@ -20,8 +20,6 @@
#include <linux/of_irq.h>
#include <linux/of_pci.h>
-#include <asm/pci.h>
-#include <asm/gpio.h>
#include <asm/addrspace.h>
#include <lantiq_soc.h>
diff --git a/kernel/arch/mips/pci/pci-rt2880.c b/kernel/arch/mips/pci/pci-rt2880.c
index 8a9780226..a245cad43 100644
--- a/kernel/arch/mips/pci/pci-rt2880.c
+++ b/kernel/arch/mips/pci/pci-rt2880.c
@@ -11,6 +11,7 @@
* by the Free Software Foundation.
*/
+#include <linux/delay.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/io.h>
@@ -220,7 +221,6 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static int rt288x_pci_probe(struct platform_device *pdev)
{
void __iomem *io_map_base;
- int i;
rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE);
@@ -232,8 +232,7 @@ static int rt288x_pci_probe(struct platform_device *pdev)
ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1;
rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR);
- for (i = 0; i < 0xfffff; i++)
- ;
+ udelay(1);
rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL);
rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR);
diff --git a/kernel/arch/mips/pci/pci-rt3883.c b/kernel/arch/mips/pci/pci-rt3883.c
index ec9be8ca4..53a42b070 100644
--- a/kernel/arch/mips/pci/pci-rt3883.c
+++ b/kernel/arch/mips/pci/pci-rt3883.c
@@ -129,12 +129,12 @@ static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA);
}
-static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void rt3883_pci_irq_handler(struct irq_desc *desc)
{
struct rt3883_pci_controller *rpc;
u32 pending;
- rpc = irq_get_handler_data(irq);
+ rpc = irq_desc_get_handler_data(desc);
pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) &
rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
@@ -145,7 +145,7 @@ static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
}
while (pending) {
- unsigned bit = __ffs(pending);
+ unsigned irq, bit = __ffs(pending);
irq = irq_find_mapping(rpc->irq_domain, bit);
generic_handle_irq(irq);
@@ -225,8 +225,7 @@ static int rt3883_pci_irq_init(struct device *dev,
return -ENODEV;
}
- irq_set_handler_data(irq, rpc);
- irq_set_chained_handler(irq, rt3883_pci_irq_handler);
+ irq_set_chained_handler_and_data(irq, rt3883_pci_irq_handler, rpc);
return 0;
}
@@ -433,8 +432,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
/* find the interrupt controller child node */
for_each_child_of_node(np, child) {
- if (of_get_property(child, "interrupt-controller", NULL) &&
- of_node_get(child)) {
+ if (of_get_property(child, "interrupt-controller", NULL)) {
rpc->intc_of_node = child;
break;
}
@@ -450,8 +448,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
/* find the PCI host bridge child node */
for_each_child_of_node(np, child) {
if (child->type &&
- of_node_cmp(child->type, "pci") == 0 &&
- of_node_get(child)) {
+ of_node_cmp(child->type, "pci") == 0) {
rpc->pci_controller.of_node = child;
break;
}
diff --git a/kernel/arch/mips/pistachio/Kconfig b/kernel/arch/mips/pistachio/Kconfig
new file mode 100644
index 000000000..97731ea94
--- /dev/null
+++ b/kernel/arch/mips/pistachio/Kconfig
@@ -0,0 +1,13 @@
+config PISTACHIO_GPTIMER_CLKSRC
+ bool "Enable General Purpose Timer based clocksource"
+ depends on MACH_PISTACHIO
+ select CLKSRC_PISTACHIO
+ select MIPS_EXTERNAL_TIMER
+ help
+ This option enables a clocksource driver based on a Pistachio
+ SoC General Purpose external timer.
+
+ If you want to enable the CPUFreq, you need to enable
+ this option.
+
+ If you don't want to enable CPUFreq, you can leave this disabled.
diff --git a/kernel/arch/mips/pistachio/init.c b/kernel/arch/mips/pistachio/init.c
index d2dc83652..96ba2cc9a 100644
--- a/kernel/arch/mips/pistachio/init.c
+++ b/kernel/arch/mips/pistachio/init.c
@@ -58,18 +58,23 @@ void __init plat_mem_setup(void)
panic("Device-tree not present");
__dt_setup_arch((void *)fw_arg1);
- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
plat_setup_iocoherency();
}
-#define DEFAULT_CPC_BASE_ADDR 0x1bde0000
+#define DEFAULT_CPC_BASE_ADDR 0x1bde0000
+#define DEFAULT_CDMM_BASE_ADDR 0x1bdd0000
phys_addr_t mips_cpc_default_phys_base(void)
{
return DEFAULT_CPC_BASE_ADDR;
}
+phys_addr_t mips_cdmm_phys_base(void)
+{
+ return DEFAULT_CDMM_BASE_ADDR;
+}
+
static void __init mips_nmi_setup(void)
{
void *base;
diff --git a/kernel/arch/mips/pistachio/time.c b/kernel/arch/mips/pistachio/time.c
index ab73f6f40..1022201b2 100644
--- a/kernel/arch/mips/pistachio/time.c
+++ b/kernel/arch/mips/pistachio/time.c
@@ -28,13 +28,18 @@ int get_c0_perfcount_int(void)
}
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+int get_c0_fdc_int(void)
+{
+ return gic_get_c0_fdc_int();
+}
+
void __init plat_time_init(void)
{
struct device_node *np;
struct clk *clk;
of_clk_init(NULL);
- clocksource_of_init();
+ clocksource_probe();
np = of_get_cpu_node(0, NULL);
if (!np) {
diff --git a/kernel/arch/mips/pmcs-msp71xx/msp_irq_cic.c b/kernel/arch/mips/pmcs-msp71xx/msp_irq_cic.c
index 1207ec4df..8b9cf6463 100644
--- a/kernel/arch/mips/pmcs-msp71xx/msp_irq_cic.c
+++ b/kernel/arch/mips/pmcs-msp71xx/msp_irq_cic.c
@@ -88,7 +88,8 @@ static void unmask_cic_irq(struct irq_data *d)
* Make sure we have IRQ affinity. It may have changed while
* we were processing the IRQ.
*/
- if (!cpumask_test_cpu(smp_processor_id(), d->affinity))
+ if (!cpumask_test_cpu(smp_processor_id(),
+ irq_data_get_affinity_mask(d)))
return;
#endif
diff --git a/kernel/arch/mips/pmcs-msp71xx/msp_setup.c b/kernel/arch/mips/pmcs-msp71xx/msp_setup.c
index 4f925e06c..9d293b3e9 100644
--- a/kernel/arch/mips/pmcs-msp71xx/msp_setup.c
+++ b/kernel/arch/mips/pmcs-msp71xx/msp_setup.c
@@ -10,6 +10,8 @@
* option) any later version.
*/
+#include <linux/delay.h>
+
#include <asm/bootinfo.h>
#include <asm/cacheflush.h>
#include <asm/idle.h>
@@ -37,7 +39,6 @@ extern void msp_serial_setup(void);
void msp7120_reset(void)
{
void *start, *end, *iptr;
- register int i;
/* Diasble all interrupts */
local_irq_disable();
@@ -77,7 +78,7 @@ void msp7120_reset(void)
*/
/* Wait a bit for the DDRC to settle */
- for (i = 0; i < 100000000; i++);
+ mdelay(125);
#if defined(CONFIG_PMC_MSP7120_GW)
/*
diff --git a/kernel/arch/mips/pmcs-msp71xx/msp_smp.c b/kernel/arch/mips/pmcs-msp71xx/msp_smp.c
index 10170580a..ffa0f7101 100644
--- a/kernel/arch/mips/pmcs-msp71xx/msp_smp.c
+++ b/kernel/arch/mips/pmcs-msp71xx/msp_smp.c
@@ -44,7 +44,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/kernel/arch/mips/ralink/cevt-rt3352.c b/kernel/arch/mips/ralink/cevt-rt3352.c
index 24bf057a3..e46f91f97 100644
--- a/kernel/arch/mips/ralink/cevt-rt3352.c
+++ b/kernel/arch/mips/ralink/cevt-rt3352.c
@@ -36,8 +36,8 @@ struct systick_device {
int freq_scale;
};
-static void systick_set_clock_mode(enum clock_event_mode mode,
- struct clock_event_device *evt);
+static int systick_set_oneshot(struct clock_event_device *evt);
+static int systick_shutdown(struct clock_event_device *evt);
static int systick_next_event(unsigned long delta,
struct clock_event_device *evt)
@@ -48,7 +48,7 @@ static int systick_next_event(unsigned long delta,
sdev = container_of(evt, struct systick_device, dev);
count = ioread32(sdev->membase + SYSTICK_COUNT);
count = (count + delta) % SYSTICK_FREQ;
- iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
+ iowrite32(count, sdev->membase + SYSTICK_COMPARE);
return 0;
}
@@ -73,11 +73,12 @@ static struct systick_device systick = {
* cevt-r4k uses 300, make sure systick
* gets used if available
*/
- .rating = 310,
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = systick_next_event,
- .set_mode = systick_set_clock_mode,
- .event_handler = systick_event_handler,
+ .rating = 310,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = systick_next_event,
+ .set_state_shutdown = systick_shutdown,
+ .set_state_oneshot = systick_set_oneshot,
+ .event_handler = systick_event_handler,
},
};
@@ -87,33 +88,33 @@ static struct irqaction systick_irqaction = {
.dev_id = &systick.dev,
};
-static void systick_set_clock_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int systick_shutdown(struct clock_event_device *evt)
{
struct systick_device *sdev;
sdev = container_of(evt, struct systick_device, dev);
- switch (mode) {
- case CLOCK_EVT_MODE_ONESHOT:
- if (!sdev->irq_requested)
- setup_irq(systick.dev.irq, &systick_irqaction);
- sdev->irq_requested = 1;
- iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
- systick.membase + SYSTICK_CONFIG);
- break;
-
- case CLOCK_EVT_MODE_SHUTDOWN:
- if (sdev->irq_requested)
- free_irq(systick.dev.irq, &systick_irqaction);
- sdev->irq_requested = 0;
- iowrite32(0, systick.membase + SYSTICK_CONFIG);
- break;
-
- default:
- pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name);
- break;
- }
+ if (sdev->irq_requested)
+ free_irq(systick.dev.irq, &systick_irqaction);
+ sdev->irq_requested = 0;
+ iowrite32(0, systick.membase + SYSTICK_CONFIG);
+
+ return 0;
+}
+
+static int systick_set_oneshot(struct clock_event_device *evt)
+{
+ struct systick_device *sdev;
+
+ sdev = container_of(evt, struct systick_device, dev);
+
+ if (!sdev->irq_requested)
+ setup_irq(systick.dev.irq, &systick_irqaction);
+ sdev->irq_requested = 1;
+ iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
+ systick.membase + SYSTICK_CONFIG);
+
+ return 0;
}
static void __init ralink_systick_init(struct device_node *np)
diff --git a/kernel/arch/mips/ralink/clk.c b/kernel/arch/mips/ralink/clk.c
index feb5a9bf9..25c4a6177 100644
--- a/kernel/arch/mips/ralink/clk.c
+++ b/kernel/arch/mips/ralink/clk.c
@@ -75,5 +75,5 @@ void __init plat_time_init(void)
pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
mips_hpt_frequency = clk_get_rate(clk) / 2;
clk_put(clk);
- clocksource_of_init();
+ clocksource_probe();
}
diff --git a/kernel/arch/mips/ralink/early_printk.c b/kernel/arch/mips/ralink/early_printk.c
index 255d695ec..3c59ffe5f 100644
--- a/kernel/arch/mips/ralink/early_printk.c
+++ b/kernel/arch/mips/ralink/early_printk.c
@@ -25,11 +25,13 @@
#define MT7628_CHIP_NAME1 0x20203832
#define UART_REG_TX 0x04
+#define UART_REG_LCR 0x0c
#define UART_REG_LSR 0x14
#define UART_REG_LSR_RT2880 0x1c
static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE);
static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE);
+static int init_complete;
static inline void uart_w32(u32 val, unsigned reg)
{
@@ -47,8 +49,32 @@ static inline int soc_is_mt7628(void)
(__raw_readl(chipid_membase) == MT7628_CHIP_NAME1);
}
+static void find_uart_base(void)
+{
+ int i;
+
+ if (!soc_is_mt7628())
+ return;
+
+ for (i = 0; i < 3; i++) {
+ u32 reg = uart_r32(UART_REG_LCR + (0x100 * i));
+
+ if (!reg)
+ continue;
+
+ uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE +
+ (0x100 * i));
+ break;
+ }
+}
+
void prom_putchar(unsigned char ch)
{
+ if (!init_complete) {
+ find_uart_base();
+ init_complete = 1;
+ }
+
if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) {
uart_w32(ch, UART_TX);
while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
diff --git a/kernel/arch/mips/ralink/irq.c b/kernel/arch/mips/ralink/irq.c
index 199ace4ca..4cf77f358 100644
--- a/kernel/arch/mips/ralink/irq.c
+++ b/kernel/arch/mips/ralink/irq.c
@@ -96,12 +96,12 @@ unsigned int get_c0_compare_int(void)
return CP0_LEGACY_COMPARE_IRQ;
}
-static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ralink_intc_irq_handler(struct irq_desc *desc)
{
u32 pending = rt_intc_r32(INTC_REG_STATUS0);
if (pending) {
- struct irq_domain *domain = irq_get_handler_data(irq);
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
} else {
spurious_interrupt();
@@ -185,8 +185,7 @@ static int __init intc_of_init(struct device_node *node,
rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
- irq_set_chained_handler(irq, ralink_intc_irq_handler);
- irq_set_handler_data(irq, domain);
+ irq_set_chained_handler_and_data(irq, ralink_intc_irq_handler, domain);
/* tell the kernel which irq is used for performance monitoring */
rt_perfcount_irq = irq_create_mapping(domain, 9);
diff --git a/kernel/arch/mips/ralink/mt7620.c b/kernel/arch/mips/ralink/mt7620.c
index 2ea5ff6dc..dfb04fced 100644
--- a/kernel/arch/mips/ralink/mt7620.c
+++ b/kernel/arch/mips/ralink/mt7620.c
@@ -37,8 +37,17 @@
#define PMU1_CFG 0x8C
#define DIG_SW_SEL BIT(25)
-/* is this a MT7620 or a MT7628 */
-enum mt762x_soc_type mt762x_soc;
+/* clock scaling */
+#define CLKCFG_FDIV_MASK 0x1f00
+#define CLKCFG_FDIV_USB_VAL 0x0300
+#define CLKCFG_FFRAC_MASK 0x001f
+#define CLKCFG_FFRAC_USB_VAL 0x0003
+
+/* EFUSE bits */
+#define EFUSE_MT7688 0x100000
+
+/* DRAM type bit */
+#define DRAM_TYPE_MT7628_MASK 0x1
/* does the board have sdram or ddram */
static int dram_type;
@@ -227,6 +236,12 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
{ 0 }
};
+static inline int is_mt76x8(void)
+{
+ return ralink_soc == MT762X_SOC_MT7628AN ||
+ ralink_soc == MT762X_SOC_MT7688;
+}
+
static __init u32
mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
{
@@ -381,7 +396,7 @@ void __init ralink_clk_init(void)
#define RINT(x) ((x) / 1000000)
#define RFRAC(x) (((x) / 1000) % 1000)
- if (mt762x_soc == MT762X_SOC_MT7628AN) {
+ if (is_mt76x8()) {
if (xtal_rate == MHZ(40))
cpu_rate = MHZ(580);
else
@@ -423,6 +438,20 @@ void __init ralink_clk_init(void)
ralink_clk_add("10000b00.spi", sys_rate);
ralink_clk_add("10000c00.uartlite", periph_rate);
ralink_clk_add("10180000.wmac", xtal_rate);
+
+ if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) {
+ /*
+ * When the CPU goes into sleep mode, the BUS clock will be
+ * too low for USB to function properly. Adjust the busses
+ * fractional divider to fix this
+ */
+ u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
+
+ val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
+ val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
+
+ rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG);
+ }
}
void __init ralink_of_remap(void)
@@ -499,20 +528,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) {
if (bga) {
- mt762x_soc = MT762X_SOC_MT7620A;
+ ralink_soc = MT762X_SOC_MT7620A;
name = "MT7620A";
soc_info->compatible = "ralink,mt7620a-soc";
} else {
- mt762x_soc = MT762X_SOC_MT7620N;
+ ralink_soc = MT762X_SOC_MT7620N;
name = "MT7620N";
soc_info->compatible = "ralink,mt7620n-soc";
-#ifdef CONFIG_PCI
- panic("mt7620n is only supported for non pci kernels");
-#endif
}
} else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) {
- mt762x_soc = MT762X_SOC_MT7628AN;
- name = "MT7628AN";
+ u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG);
+
+ if (efuse & EFUSE_MT7688) {
+ ralink_soc = MT762X_SOC_MT7688;
+ name = "MT7688";
+ } else {
+ ralink_soc = MT762X_SOC_MT7628AN;
+ name = "MT7628AN";
+ }
soc_info->compatible = "ralink,mt7628an-soc";
} else {
panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
@@ -525,10 +558,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
(rev & CHIP_REV_ECO_MASK));
cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
- dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
+ if (is_mt76x8())
+ dram_type = cfg0 & DRAM_TYPE_MT7628_MASK;
+ else
+ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) &
+ SYSCFG0_DRAM_TYPE_MASK;
soc_info->mem_base = MT7620_DRAM_BASE;
- if (mt762x_soc == MT762X_SOC_MT7628AN)
+ if (is_mt76x8())
mt7628_dram_init(soc_info);
else
mt7620_dram_init(soc_info);
@@ -541,7 +578,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
pr_info("Digital PMU set to %s control\n",
(pmu1 & DIG_SW_SEL) ? ("sw") : ("hw"));
- if (mt762x_soc == MT762X_SOC_MT7628AN)
+ if (is_mt76x8())
rt2880_pinmux_data = mt7628an_pinmux_data;
else
rt2880_pinmux_data = mt7620a_pinmux_data;
diff --git a/kernel/arch/mips/ralink/of.c b/kernel/arch/mips/ralink/of.c
index 0d30dcd63..f9eda5d8f 100644
--- a/kernel/arch/mips/ralink/of.c
+++ b/kernel/arch/mips/ralink/of.c
@@ -74,8 +74,6 @@ void __init plat_mem_setup(void)
*/
__dt_setup_arch(__dtb_start);
- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-
of_scan_flat_dt(early_init_dt_find_memory, NULL);
if (memory_dtb)
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
diff --git a/kernel/arch/mips/ralink/prom.c b/kernel/arch/mips/ralink/prom.c
index 09419f67d..39a9142f7 100644
--- a/kernel/arch/mips/ralink/prom.c
+++ b/kernel/arch/mips/ralink/prom.c
@@ -15,11 +15,16 @@
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
+#include <asm/mach-ralink/ralink_regs.h>
+
#include "common.h"
struct ralink_soc_info soc_info;
struct rt2880_pmx_group *rt2880_pinmux_data = NULL;
+enum ralink_soc_type ralink_soc;
+EXPORT_SYMBOL_GPL(ralink_soc);
+
const char *get_system_type(void)
{
return soc_info.sys_type;
diff --git a/kernel/arch/mips/ralink/reset.c b/kernel/arch/mips/ralink/reset.c
index 55c7ec59d..ee117c4bc 100644
--- a/kernel/arch/mips/ralink/reset.c
+++ b/kernel/arch/mips/ralink/reset.c
@@ -11,6 +11,7 @@
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/delay.h>
#include <linux/reset-controller.h>
#include <asm/reboot.h>
@@ -18,8 +19,10 @@
#include <asm/mach-ralink/ralink_regs.h>
/* Reset Control */
-#define SYSC_REG_RESET_CTRL 0x034
-#define RSTCTL_RESET_SYSTEM BIT(0)
+#define SYSC_REG_RESET_CTRL 0x034
+
+#define RSTCTL_RESET_PCI BIT(26)
+#define RSTCTL_RESET_SYSTEM BIT(0)
static int ralink_assert_device(struct reset_controller_dev *rcdev,
unsigned long id)
@@ -83,6 +86,11 @@ void ralink_rst_init(void)
static void ralink_restart(char *command)
{
+ if (IS_ENABLED(CONFIG_PCI)) {
+ rt_sysc_m32(0, RSTCTL_RESET_PCI, SYSC_REG_RESET_CTRL);
+ mdelay(50);
+ }
+
local_irq_disable();
rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
unreachable();
@@ -98,7 +106,6 @@ static int __init mips_reboot_setup(void)
{
_machine_restart = ralink_restart;
_machine_halt = ralink_halt;
- pm_power_off = ralink_halt;
return 0;
}
diff --git a/kernel/arch/mips/ralink/rt288x.c b/kernel/arch/mips/ralink/rt288x.c
index 738cec865..844f5cd55 100644
--- a/kernel/arch/mips/ralink/rt288x.c
+++ b/kernel/arch/mips/ralink/rt288x.c
@@ -119,4 +119,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
rt2880_pinmux_data = rt2880_pinmux_data_act;
+ ralink_soc == RT2880_SOC;
}
diff --git a/kernel/arch/mips/ralink/rt305x.c b/kernel/arch/mips/ralink/rt305x.c
index c40776ab6..9e4572592 100644
--- a/kernel/arch/mips/ralink/rt305x.c
+++ b/kernel/arch/mips/ralink/rt305x.c
@@ -21,8 +21,6 @@
#include "common.h"
-enum rt305x_soc_type rt305x_soc;
-
static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) };
static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) };
static struct rt2880_pmx_func uartf_func[] = {
@@ -201,6 +199,7 @@ void __init ralink_clk_init(void)
}
ralink_clk_add("cpu", cpu_rate);
+ ralink_clk_add("sys", sys_rate);
ralink_clk_add("10000b00.spi", sys_rate);
ralink_clk_add("10000100.timer", wdt_rate);
ralink_clk_add("10000120.watchdog", wdt_rate);
@@ -235,24 +234,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
icache_sets = (read_c0_config1() >> 22) & 7;
if (icache_sets == 1) {
- rt305x_soc = RT305X_SOC_RT3050;
+ ralink_soc = RT305X_SOC_RT3050;
name = "RT3050";
soc_info->compatible = "ralink,rt3050-soc";
} else {
- rt305x_soc = RT305X_SOC_RT3052;
+ ralink_soc = RT305X_SOC_RT3052;
name = "RT3052";
soc_info->compatible = "ralink,rt3052-soc";
}
} else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) {
- rt305x_soc = RT305X_SOC_RT3350;
+ ralink_soc = RT305X_SOC_RT3350;
name = "RT3350";
soc_info->compatible = "ralink,rt3350-soc";
} else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) {
- rt305x_soc = RT305X_SOC_RT3352;
+ ralink_soc = RT305X_SOC_RT3352;
name = "RT3352";
soc_info->compatible = "ralink,rt3352-soc";
} else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) {
- rt305x_soc = RT305X_SOC_RT5350;
+ ralink_soc = RT305X_SOC_RT5350;
name = "RT5350";
soc_info->compatible = "ralink,rt5350-soc";
} else {
diff --git a/kernel/arch/mips/ralink/rt3883.c b/kernel/arch/mips/ralink/rt3883.c
index 86a535c77..582995aaa 100644
--- a/kernel/arch/mips/ralink/rt3883.c
+++ b/kernel/arch/mips/ralink/rt3883.c
@@ -153,4 +153,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
soc_info->mem_size_max = RT3883_MEM_SIZE_MAX;
rt2880_pinmux_data = rt3883_pinmux_data;
+
+ ralink_soc == RT3883_SOC;
}
diff --git a/kernel/arch/mips/rb532/devices.c b/kernel/arch/mips/rb532/devices.c
index e31e8cdcb..9bd7a2de0 100644
--- a/kernel/arch/mips/rb532/devices.c
+++ b/kernel/arch/mips/rb532/devices.c
@@ -23,6 +23,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/serial_8250.h>
diff --git a/kernel/arch/mips/rb532/gpio.c b/kernel/arch/mips/rb532/gpio.c
index 5aa3df853..650d5d39f 100644
--- a/kernel/arch/mips/rb532/gpio.c
+++ b/kernel/arch/mips/rb532/gpio.c
@@ -140,6 +140,11 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
+static int rb532_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ return 8 + 4 * 32 + gpio;
+}
+
static struct rb532_gpio_chip rb532_gpio_chip[] = {
[0] = {
.chip = {
@@ -148,6 +153,7 @@ static struct rb532_gpio_chip rb532_gpio_chip[] = {
.direction_output = rb532_gpio_direction_output,
.get = rb532_gpio_get,
.set = rb532_gpio_set,
+ .to_irq = rb532_gpio_to_irq,
.base = 0,
.ngpio = 32,
},
diff --git a/kernel/arch/mips/sgi-ip27/Makefile b/kernel/arch/mips/sgi-ip27/Makefile
index da8f6816d..ab4affa62 100644
--- a/kernel/arch/mips/sgi-ip27/Makefile
+++ b/kernel/arch/mips/sgi-ip27/Makefile
@@ -2,9 +2,9 @@
# Makefile for the IP27 specific kernel interface routines under Linux.
#
-obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \
- ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o ip27-hubio.o \
- ip27-xtalk.o
+obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \
+ ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o \
+ ip27-hubio.o ip27-xtalk.o
obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o
obj-$(CONFIG_PCI) += ip27-irq-pci.o
diff --git a/kernel/arch/mips/sgi-ip27/ip27-irq.c b/kernel/arch/mips/sgi-ip27/ip27-irq.c
index 3fbaef97a..16ec4e12d 100644
--- a/kernel/arch/mips/sgi-ip27/ip27-irq.c
+++ b/kernel/arch/mips/sgi-ip27/ip27-irq.c
@@ -107,10 +107,14 @@ static void ip27_do_irq_mask0(void)
scheduler_ipi();
} else if (pend0 & (1UL << CPU_CALL_A_IRQ)) {
LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
- smp_call_function_interrupt();
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
} else if (pend0 & (1UL << CPU_CALL_B_IRQ)) {
LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
- smp_call_function_interrupt();
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
} else
#endif
{
diff --git a/kernel/arch/mips/sgi-ip27/ip27-irqno.c b/kernel/arch/mips/sgi-ip27/ip27-irqno.c
new file mode 100644
index 000000000..957ab58e1
--- /dev/null
+++ b/kernel/arch/mips/sgi-ip27/ip27-irqno.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+
+#include <asm/barrier.h>
+
+static DECLARE_BITMAP(irq_map, NR_IRQS);
+
+int allocate_irqno(void)
+{
+ int irq;
+
+again:
+ irq = find_first_zero_bit(irq_map, NR_IRQS);
+
+ if (irq >= NR_IRQS)
+ return -ENOSPC;
+
+ if (test_and_set_bit(irq, irq_map))
+ goto again;
+
+ return irq;
+}
+
+/*
+ * Allocate the 16 legacy interrupts for i8259 devices. This happens early
+ * in the kernel initialization so treating allocation failure as BUG() is
+ * ok.
+ */
+void __init alloc_legacy_irqno(void)
+{
+ int i;
+
+ for (i = 0; i <= 16; i++)
+ BUG_ON(test_and_set_bit(i, irq_map));
+}
+
+void free_irqno(unsigned int irq)
+{
+ smp_mb__before_atomic();
+ clear_bit(irq, irq_map);
+ smp_mb__after_atomic();
+}
diff --git a/kernel/arch/mips/sgi-ip27/ip27-timer.c b/kernel/arch/mips/sgi-ip27/ip27-timer.c
index a6d10f607..42d6cb9f9 100644
--- a/kernel/arch/mips/sgi-ip27/ip27-timer.c
+++ b/kernel/arch/mips/sgi-ip27/ip27-timer.c
@@ -64,12 +64,6 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
}
-static void rt_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- /* Nothing to do ... */
-}
-
unsigned int rt_timer_irq;
static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent);
@@ -124,7 +118,6 @@ void hub_rt_clock_event_init(void)
cd->irq = irq;
cd->cpumask = cpumask_of(cpu);
cd->set_next_event = rt_next_event;
- cd->set_mode = rt_set_mode;
clockevents_register_device(cd);
}
diff --git a/kernel/arch/mips/sibyte/Kconfig b/kernel/arch/mips/sibyte/Kconfig
index 5fbd3605d..cb9a095f5 100644
--- a/kernel/arch/mips/sibyte/Kconfig
+++ b/kernel/arch/mips/sibyte/Kconfig
@@ -3,7 +3,7 @@ config SIBYTE_SB1250
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
@@ -13,7 +13,7 @@ config SIBYTE_BCM1120
bool
select CEVT_SB1250
select CSRC_SB1250
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
@@ -23,7 +23,7 @@ config SIBYTE_BCM1125
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
@@ -33,7 +33,7 @@ config SIBYTE_BCM1125H
select CEVT_SB1250
select CSRC_SB1250
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_BCM112X
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
@@ -43,7 +43,7 @@ config SIBYTE_BCM112X
bool
select CEVT_SB1250
select CSRC_SB1250
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
@@ -52,7 +52,7 @@ config SIBYTE_BCM1x80
select CEVT_BCM1480
select CSRC_BCM1480
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SYS_SUPPORTS_SMP
@@ -62,7 +62,7 @@ config SIBYTE_BCM1x55
select CEVT_BCM1480
select CSRC_BCM1480
select HW_HAS_PCI
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
select SYS_SUPPORTS_SMP
@@ -70,7 +70,7 @@ config SIBYTE_BCM1x55
config SIBYTE_SB1xxx_SOC
bool
select DMA_COHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
@@ -81,11 +81,6 @@ choice
prompt "SiByte SOC Stepping"
depends on SIBYTE_SB1xxx_SOC
-config CPU_SB1_PASS_1
- bool "1250 Pass1"
- depends on SIBYTE_SB1250
- select CPU_HAS_PREFETCH
-
config CPU_SB1_PASS_2_1250
bool "1250 An"
depends on SIBYTE_SB1250
diff --git a/kernel/arch/mips/sibyte/bcm1480/smp.c b/kernel/arch/mips/sibyte/bcm1480/smp.c
index af7d44edd..4c71aea25 100644
--- a/kernel/arch/mips/sibyte/bcm1480/smp.c
+++ b/kernel/arch/mips/sibyte/bcm1480/smp.c
@@ -29,8 +29,6 @@
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/bcm1480_int.h>
-extern void smp_call_function_interrupt(void);
-
/*
* These are routines for dealing with the bcm1480 smp capabilities
* independent of board/firmware
@@ -184,6 +182,9 @@ void bcm1480_mailbox_interrupt(void)
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
}
diff --git a/kernel/arch/mips/sibyte/common/bus_watcher.c b/kernel/arch/mips/sibyte/common/bus_watcher.c
index 5581844c9..a4e55999e 100644
--- a/kernel/arch/mips/sibyte/common/bus_watcher.c
+++ b/kernel/arch/mips/sibyte/common/bus_watcher.c
@@ -81,10 +81,7 @@ void check_bus_watcher(void)
{
u32 status, l2_err, memio_err;
-#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
- /* Destructive read, clears register and interrupt */
- status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
-#elif defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
+#if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
/* Use non-destructive register */
status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG));
#elif defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
@@ -253,4 +250,4 @@ int __init sibyte_bus_watcher(void)
return 0;
}
-__initcall(sibyte_bus_watcher);
+device_initcall(sibyte_bus_watcher);
diff --git a/kernel/arch/mips/sibyte/sb1250/setup.c b/kernel/arch/mips/sibyte/sb1250/setup.c
index 3c02b2a77..9d3c24efd 100644
--- a/kernel/arch/mips/sibyte/sb1250/setup.c
+++ b/kernel/arch/mips/sibyte/sb1250/setup.c
@@ -202,12 +202,10 @@ void __init sb1250_setup(void)
switch (war_pass) {
case K_SYS_REVISION_BCM1250_PASS1:
-#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
"and the kernel doesn't have the proper "
"workarounds compiled in. @@@@\n");
bad_config = 1;
-#endif
break;
case K_SYS_REVISION_BCM1250_PASS2:
/* Pass 2 - easiest as default for now - so many numbers */
diff --git a/kernel/arch/mips/sibyte/sb1250/smp.c b/kernel/arch/mips/sibyte/sb1250/smp.c
index c0c4b3f88..1cf66f5ff 100644
--- a/kernel/arch/mips/sibyte/sb1250/smp.c
+++ b/kernel/arch/mips/sibyte/sb1250/smp.c
@@ -172,6 +172,9 @@ void sb1250_mailbox_interrupt(void)
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
}
diff --git a/kernel/arch/mips/sni/reset.c b/kernel/arch/mips/sni/reset.c
index 244f94276..6afa34346 100644
--- a/kernel/arch/mips/sni/reset.c
+++ b/kernel/arch/mips/sni/reset.c
@@ -3,6 +3,8 @@
*
* Reset a SNI machine.
*/
+#include <linux/delay.h>
+
#include <asm/io.h>
#include <asm/reboot.h>
#include <asm/sni.h>
@@ -24,7 +26,7 @@ static inline void kb_wait(void)
/* XXX This ends up at the ARC firmware prompt ... */
void sni_machine_restart(char *command)
{
- int i, j;
+ int i;
/* This does a normal via the keyboard controller like a PC.
We can do that easier ... */
@@ -32,9 +34,9 @@ void sni_machine_restart(char *command)
for (;;) {
for (i = 0; i < 100; i++) {
kb_wait();
- for (j = 0; j < 100000 ; j++)
- /* nothing */;
+ udelay(50);
outb_p(0xfe, 0x64); /* pulse reset low */
+ udelay(50);
}
}
}
diff --git a/kernel/arch/mips/sni/time.c b/kernel/arch/mips/sni/time.c
index cf8ec568b..fb4b3520c 100644
--- a/kernel/arch/mips/sni/time.c
+++ b/kernel/arch/mips/sni/time.c
@@ -14,44 +14,33 @@
#define SNI_COUNTER2_DIV 64
#define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
-static void a20r_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int a20r_set_periodic(struct clock_event_device *evt)
{
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
- wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV;
- wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
- wmb();
-
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
- wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV;
- wmb();
- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
- wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
+ wmb();
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- break;
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV;
+ wmb();
+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
+ wmb();
+ return 0;
}
static struct clock_event_device a20r_clockevent_device = {
- .name = "a20r-timer",
- .features = CLOCK_EVT_FEAT_PERIODIC,
+ .name = "a20r-timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
- .rating = 300,
- .irq = SNI_A20R_IRQ_TIMER,
- .set_mode = a20r_set_mode,
+ .rating = 300,
+ .irq = SNI_A20R_IRQ_TIMER,
+ .set_state_periodic = a20r_set_periodic,
};
static irqreturn_t a20r_interrupt(int irq, void *dev_id)
diff --git a/kernel/arch/mips/txx9/Kconfig b/kernel/arch/mips/txx9/Kconfig
index 6d40bc783..8c337d60f 100644
--- a/kernel/arch/mips/txx9/Kconfig
+++ b/kernel/arch/mips/txx9/Kconfig
@@ -8,7 +8,7 @@ config MACH_TX49XX
select MACH_TXX9
select CEVT_R4K
select CSRC_R4K
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select SYS_HAS_CPU_TX49XX
select SYS_SUPPORTS_64BIT_KERNEL
diff --git a/kernel/arch/mips/txx9/generic/setup.c b/kernel/arch/mips/txx9/generic/setup.c
index 2791b8641..9d9962ab7 100644
--- a/kernel/arch/mips/txx9/generic/setup.c
+++ b/kernel/arch/mips/txx9/generic/setup.c
@@ -117,22 +117,6 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
-/* GPIO support */
-
-#ifdef CONFIG_GPIOLIB
-int gpio_to_irq(unsigned gpio)
-{
- return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_to_irq);
-
-int irq_to_gpio(unsigned irq)
-{
- return -EINVAL;
-}
-EXPORT_SYMBOL(irq_to_gpio);
-#endif
-
#define BOARD_VEC(board) extern struct txx9_board_vec board;
#include <asm/txx9/boards.h>
#undef BOARD_VEC
diff --git a/kernel/arch/mips/txx9/generic/spi_eeprom.c b/kernel/arch/mips/txx9/generic/spi_eeprom.c
index 3dbad99d5..d833dd2c9 100644
--- a/kernel/arch/mips/txx9/generic/spi_eeprom.c
+++ b/kernel/arch/mips/txx9/generic/spi_eeprom.c
@@ -80,7 +80,6 @@ static int __init early_seeprom_probe(struct spi_device *spi)
static struct spi_driver early_seeprom_driver __initdata = {
.driver = {
.name = "at25",
- .owner = THIS_MODULE,
},
.probe = early_seeprom_probe,
};
diff --git a/kernel/arch/mips/vdso/.gitignore b/kernel/arch/mips/vdso/.gitignore
new file mode 100644
index 000000000..5286a7d73
--- /dev/null
+++ b/kernel/arch/mips/vdso/.gitignore
@@ -0,0 +1,4 @@
+*.so*
+vdso-*image.c
+genvdso
+vdso*.lds
diff --git a/kernel/arch/mips/vdso/Makefile b/kernel/arch/mips/vdso/Makefile
new file mode 100644
index 000000000..14568900f
--- /dev/null
+++ b/kernel/arch/mips/vdso/Makefile
@@ -0,0 +1,160 @@
+# Objects to go into the VDSO.
+obj-vdso-y := elf.o gettimeofday.o sigreturn.o
+
+# Common compiler flags between ABIs.
+ccflags-vdso := \
+ $(filter -I%,$(KBUILD_CFLAGS)) \
+ $(filter -E%,$(KBUILD_CFLAGS)) \
+ $(filter -march=%,$(KBUILD_CFLAGS))
+cflags-vdso := $(ccflags-vdso) \
+ $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
+ -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+ $(call cc-option, -fno-stack-protector)
+aflags-vdso := $(ccflags-vdso) \
+ $(filter -I%,$(KBUILD_CFLAGS)) \
+ $(filter -E%,$(KBUILD_CFLAGS)) \
+ -D__ASSEMBLY__ -Wa,-gdwarf-2
+
+#
+# For the pre-R6 code in arch/mips/vdso/vdso.h for locating
+# the base address of VDSO, the linker will emit a R_MIPS_PC32
+# relocation in binutils > 2.25 but it will fail with older versions
+# because that relocation is not supported for that symbol. As a result
+# of which we are forced to disable the VDSO symbols when building
+# with < 2.25 binutils on pre-R6 kernels. For more references on why we
+# can't use other methods to get the base address of VDSO please refer to
+# the comments on that file.
+#
+ifndef CONFIG_CPU_MIPSR6
+ ifeq ($(call ld-ifversion, -lt, 22500000, y),y)
+ $(warning MIPS VDSO requires binutils >= 2.25)
+ obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
+ ccflags-vdso += -DDISABLE_MIPS_VDSO
+ endif
+endif
+
+# VDSO linker flags.
+VDSO_LDFLAGS := \
+ -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
+ -nostdlib -shared \
+ $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+ $(call cc-ldoption, -Wl$(comma)--build-id)
+
+GCOV_PROFILE := n
+
+#
+# Shared build commands.
+#
+
+quiet_cmd_vdsold = VDSO $@
+ cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
+ -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
+
+hostprogs-y := genvdso
+
+quiet_cmd_genvdso = GENVDSO $@
+define cmd_genvdso
+ cp $< $(<:%.dbg=%) && \
+ $(OBJCOPY) -S $< $(<:%.dbg=%) && \
+ $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
+endef
+
+#
+# Build native VDSO.
+#
+
+native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
+
+targets += $(obj-vdso-y)
+targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
+
+obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
+
+$(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi)
+$(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
+
+$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
+
+$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+ $(call if_changed,vdsold)
+
+$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
+ $(call if_changed,genvdso)
+
+obj-y += vdso-image.o
+
+#
+# Build O32 VDSO.
+#
+
+# Define these outside the ifdef to ensure they are picked up by clean.
+targets += $(obj-vdso-y:%.o=%-o32.o)
+targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
+
+ifdef CONFIG_MIPS32_O32
+
+obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o)
+
+$(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32
+$(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32
+
+$(obj)/%-o32.o: $(src)/%.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+$(obj)/%-o32.o: $(src)/%.c FORCE
+ $(call cmd,force_checksrc)
+ $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
+ $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
+ $(call if_changed,vdsold)
+
+$(obj)/vdso-o32-image.c: VDSO_NAME := o32
+$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
+ $(call if_changed,genvdso)
+
+obj-y += vdso-o32-image.o
+
+endif
+
+#
+# Build N32 VDSO.
+#
+
+targets += $(obj-vdso-y:%.o=%-n32.o)
+targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
+
+ifdef CONFIG_MIPS32_N32
+
+obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o)
+
+$(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32
+$(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32
+
+$(obj)/%-n32.o: $(src)/%.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+$(obj)/%-n32.o: $(src)/%.c FORCE
+ $(call cmd,force_checksrc)
+ $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
+ $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
+ $(call if_changed,vdsold)
+
+$(obj)/vdso-n32-image.c: VDSO_NAME := n32
+$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
+ $(call if_changed,genvdso)
+
+obj-y += vdso-n32-image.o
+
+endif
+
+# FIXME: Need install rule for debug.
+# Needs to deal with dependency for generation of dbg by cmd_genvdso...
diff --git a/kernel/arch/mips/vdso/elf.S b/kernel/arch/mips/vdso/elf.S
new file mode 100644
index 000000000..be37bbb1f
--- /dev/null
+++ b/kernel/arch/mips/vdso/elf.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/elfnote.h>
+#include <linux/version.h>
+
+ELFNOTE_START(Linux, 0, "a")
+ .long LINUX_VERSION_CODE
+ELFNOTE_END
+
+/*
+ * The .MIPS.abiflags section must be defined with the FP ABI flags set
+ * to 'any' to be able to link with both old and new libraries.
+ * Newer toolchains are capable of automatically generating this, but we want
+ * to work with older toolchains as well. Therefore, we define the contents of
+ * this section here (under different names), and then genvdso will patch
+ * it to have the correct name and type.
+ *
+ * We base the .MIPS.abiflags section on preprocessor definitions rather than
+ * CONFIG_* because we need to match the particular ABI we are building the
+ * VDSO for.
+ *
+ * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
+ * for the .MIPS.abiflags section description.
+ */
+
+ .section .mips_abiflags, "a"
+ .align 3
+__mips_abiflags:
+ .hword 0 /* version */
+ .byte __mips /* isa_level */
+
+ /* isa_rev */
+#ifdef __mips_isa_rev
+ .byte __mips_isa_rev
+#else
+ .byte 0
+#endif
+
+ /* gpr_size */
+#ifdef __mips64
+ .byte 2 /* AFL_REG_64 */
+#else
+ .byte 1 /* AFL_REG_32 */
+#endif
+
+ /* cpr1_size */
+#if (defined(__mips_isa_rev) && __mips_isa_rev >= 6) || defined(__mips64)
+ .byte 2 /* AFL_REG_64 */
+#else
+ .byte 1 /* AFL_REG_32 */
+#endif
+
+ .byte 0 /* cpr2_size (AFL_REG_NONE) */
+ .byte 0 /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */
+ .word 0 /* isa_ext */
+ .word 0 /* ases */
+ .word 0 /* flags1 */
+ .word 0 /* flags2 */
diff --git a/kernel/arch/mips/vdso/genvdso.c b/kernel/arch/mips/vdso/genvdso.c
new file mode 100644
index 000000000..530a36f46
--- /dev/null
+++ b/kernel/arch/mips/vdso/genvdso.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * This tool is used to generate the real VDSO images from the raw image. It
+ * first patches up the MIPS ABI flags and GNU attributes sections defined in
+ * elf.S to have the correct name and type. It then generates a C source file
+ * to be compiled into the kernel containing the VDSO image data and a
+ * mips_vdso_image struct for it, including symbol offsets extracted from the
+ * image.
+ *
+ * We need to be passed both a stripped and unstripped VDSO image. The stripped
+ * image is compiled into the kernel, but we must also patch up the unstripped
+ * image's ABI flags sections so that it can be installed and used for
+ * debugging.
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <byteswap.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Define these in case the system elf.h is not new enough to have them. */
+#ifndef SHT_GNU_ATTRIBUTES
+# define SHT_GNU_ATTRIBUTES 0x6ffffff5
+#endif
+#ifndef SHT_MIPS_ABIFLAGS
+# define SHT_MIPS_ABIFLAGS 0x7000002a
+#endif
+
+enum {
+ ABI_O32 = (1 << 0),
+ ABI_N32 = (1 << 1),
+ ABI_N64 = (1 << 2),
+
+ ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64,
+};
+
+/* Symbols the kernel requires offsets for. */
+static struct {
+ const char *name;
+ const char *offset_name;
+ unsigned int abis;
+} vdso_symbols[] = {
+ { "__vdso_sigreturn", "off_sigreturn", ABI_O32 },
+ { "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL },
+ {}
+};
+
+static const char *program_name;
+static const char *vdso_name;
+static unsigned char elf_class;
+static unsigned int elf_abi;
+static bool need_swap;
+static FILE *out_file;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define HOST_ORDER ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define HOST_ORDER ELFDATA2MSB
+#endif
+
+#define BUILD_SWAP(bits) \
+ static uint##bits##_t swap_uint##bits(uint##bits##_t val) \
+ { \
+ return need_swap ? bswap_##bits(val) : val; \
+ }
+
+BUILD_SWAP(16)
+BUILD_SWAP(32)
+BUILD_SWAP(64)
+
+#define __FUNC(name, bits) name##bits
+#define _FUNC(name, bits) __FUNC(name, bits)
+#define FUNC(name) _FUNC(name, ELF_BITS)
+
+#define __ELF(x, bits) Elf##bits##_##x
+#define _ELF(x, bits) __ELF(x, bits)
+#define ELF(x) _ELF(x, ELF_BITS)
+
+/*
+ * Include genvdso.h twice with ELF_BITS defined differently to get functions
+ * for both ELF32 and ELF64.
+ */
+
+#define ELF_BITS 64
+#include "genvdso.h"
+#undef ELF_BITS
+
+#define ELF_BITS 32
+#include "genvdso.h"
+#undef ELF_BITS
+
+static void *map_vdso(const char *path, size_t *_size)
+{
+ int fd;
+ struct stat stat;
+ void *addr;
+ const Elf32_Ehdr *ehdr;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+ path, strerror(errno));
+ return NULL;
+ }
+
+ if (fstat(fd, &stat) != 0) {
+ fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name,
+ path, strerror(errno));
+ return NULL;
+ }
+
+ addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ if (addr == MAP_FAILED) {
+ fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name,
+ path, strerror(errno));
+ return NULL;
+ }
+
+ /* ELF32/64 header formats are the same for the bits we're checking. */
+ ehdr = addr;
+
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+ fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name,
+ path);
+ return NULL;
+ }
+
+ elf_class = ehdr->e_ident[EI_CLASS];
+ switch (elf_class) {
+ case ELFCLASS32:
+ case ELFCLASS64:
+ break;
+ default:
+ fprintf(stderr, "%s: '%s' has invalid ELF class\n",
+ program_name, path);
+ return NULL;
+ }
+
+ switch (ehdr->e_ident[EI_DATA]) {
+ case ELFDATA2LSB:
+ case ELFDATA2MSB:
+ need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER;
+ break;
+ default:
+ fprintf(stderr, "%s: '%s' has invalid ELF data order\n",
+ program_name, path);
+ return NULL;
+ }
+
+ if (swap_uint16(ehdr->e_machine) != EM_MIPS) {
+ fprintf(stderr,
+ "%s: '%s' has invalid ELF machine (expected EM_MIPS)\n",
+ program_name, path);
+ return NULL;
+ } else if (swap_uint16(ehdr->e_type) != ET_DYN) {
+ fprintf(stderr,
+ "%s: '%s' has invalid ELF type (expected ET_DYN)\n",
+ program_name, path);
+ return NULL;
+ }
+
+ *_size = stat.st_size;
+ return addr;
+}
+
+static bool patch_vdso(const char *path, void *vdso)
+{
+ if (elf_class == ELFCLASS64)
+ return patch_vdso64(path, vdso);
+ else
+ return patch_vdso32(path, vdso);
+}
+
+static bool get_symbols(const char *path, void *vdso)
+{
+ if (elf_class == ELFCLASS64)
+ return get_symbols64(path, vdso);
+ else
+ return get_symbols32(path, vdso);
+}
+
+int main(int argc, char **argv)
+{
+ const char *dbg_vdso_path, *vdso_path, *out_path;
+ void *dbg_vdso, *vdso;
+ size_t dbg_vdso_size, vdso_size, i;
+
+ program_name = argv[0];
+
+ if (argc < 4 || argc > 5) {
+ fprintf(stderr,
+ "Usage: %s <debug VDSO> <stripped VDSO> <output file> [<name>]\n",
+ program_name);
+ return EXIT_FAILURE;
+ }
+
+ dbg_vdso_path = argv[1];
+ vdso_path = argv[2];
+ out_path = argv[3];
+ vdso_name = (argc > 4) ? argv[4] : "";
+
+ dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size);
+ if (!dbg_vdso)
+ return EXIT_FAILURE;
+
+ vdso = map_vdso(vdso_path, &vdso_size);
+ if (!vdso)
+ return EXIT_FAILURE;
+
+ /* Patch both the VDSOs' ABI flags sections. */
+ if (!patch_vdso(dbg_vdso_path, dbg_vdso))
+ return EXIT_FAILURE;
+ if (!patch_vdso(vdso_path, vdso))
+ return EXIT_FAILURE;
+
+ if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) {
+ fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+ dbg_vdso_path, strerror(errno));
+ return EXIT_FAILURE;
+ } else if (msync(vdso, vdso_size, MS_SYNC) != 0) {
+ fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+ vdso_path, strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ out_file = fopen(out_path, "w");
+ if (!out_file) {
+ fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+ out_path, strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ fprintf(out_file, "/* Automatically generated - do not edit */\n");
+ fprintf(out_file, "#include <linux/linkage.h>\n");
+ fprintf(out_file, "#include <linux/mm.h>\n");
+ fprintf(out_file, "#include <asm/vdso.h>\n");
+
+ /* Write out the stripped VDSO data. */
+ fprintf(out_file,
+ "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
+ vdso_size);
+ for (i = 0; i < vdso_size; i++) {
+ if (!(i % 10))
+ fprintf(out_file, "\n\t");
+ fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]);
+ }
+ fprintf(out_file, "\n};\n");
+
+ /* Preallocate a page array. */
+ fprintf(out_file,
+ "static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n",
+ vdso_size);
+
+ fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
+ (vdso_name[0]) ? "_" : "", vdso_name);
+ fprintf(out_file, "\t.data = vdso_data,\n");
+ fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
+ fprintf(out_file, "\t.mapping = {\n");
+ fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
+ fprintf(out_file, "\t\t.pages = vdso_pages,\n");
+ fprintf(out_file, "\t},\n");
+
+ /* Calculate and write symbol offsets to <output file> */
+ if (!get_symbols(dbg_vdso_path, dbg_vdso)) {
+ unlink(out_path);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(out_file, "};\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/kernel/arch/mips/vdso/genvdso.h b/kernel/arch/mips/vdso/genvdso.h
new file mode 100644
index 000000000..943347270
--- /dev/null
+++ b/kernel/arch/mips/vdso/genvdso.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+static inline bool FUNC(patch_vdso)(const char *path, void *vdso)
+{
+ const ELF(Ehdr) *ehdr = vdso;
+ void *shdrs;
+ ELF(Shdr) *shdr;
+ char *shstrtab, *name;
+ uint16_t sh_count, sh_entsize, i;
+ unsigned int local_gotno, symtabno, gotsym;
+ ELF(Dyn) *dyn = NULL;
+
+ shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+ sh_count = swap_uint16(ehdr->e_shnum);
+ sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+ shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx));
+ shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+ for (i = 0; i < sh_count; i++) {
+ shdr = shdrs + (i * sh_entsize);
+ name = shstrtab + swap_uint32(shdr->sh_name);
+
+ /*
+ * Ensure there are no relocation sections - ld.so does not
+ * relocate the VDSO so if there are relocations things will
+ * break.
+ */
+ switch (swap_uint32(shdr->sh_type)) {
+ case SHT_REL:
+ case SHT_RELA:
+ fprintf(stderr,
+ "%s: '%s' contains relocation sections\n",
+ program_name, path);
+ return false;
+ case SHT_DYNAMIC:
+ dyn = vdso + FUNC(swap_uint)(shdr->sh_offset);
+ break;
+ }
+
+ /* Check for existing sections. */
+ if (strcmp(name, ".MIPS.abiflags") == 0) {
+ fprintf(stderr,
+ "%s: '%s' already contains a '.MIPS.abiflags' section\n",
+ program_name, path);
+ return false;
+ }
+
+ if (strcmp(name, ".mips_abiflags") == 0) {
+ strcpy(name, ".MIPS.abiflags");
+ shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS);
+ shdr->sh_entsize = shdr->sh_size;
+ }
+ }
+
+ /*
+ * Ensure the GOT has no entries other than the standard 2, for the same
+ * reason we check that there's no relocation sections above.
+ * The standard two entries are:
+ * - Lazy resolver
+ * - Module pointer
+ */
+ if (dyn) {
+ local_gotno = symtabno = gotsym = 0;
+
+ while (FUNC(swap_uint)(dyn->d_tag) != DT_NULL) {
+ switch (FUNC(swap_uint)(dyn->d_tag)) {
+ /*
+ * This member holds the number of local GOT entries.
+ */
+ case DT_MIPS_LOCAL_GOTNO:
+ local_gotno = FUNC(swap_uint)(dyn->d_un.d_val);
+ break;
+ /*
+ * This member holds the number of entries in the
+ * .dynsym section.
+ */
+ case DT_MIPS_SYMTABNO:
+ symtabno = FUNC(swap_uint)(dyn->d_un.d_val);
+ break;
+ /*
+ * This member holds the index of the first dynamic
+ * symbol table entry that corresponds to an entry in
+ * the GOT.
+ */
+ case DT_MIPS_GOTSYM:
+ gotsym = FUNC(swap_uint)(dyn->d_un.d_val);
+ break;
+ }
+
+ dyn++;
+ }
+
+ if (local_gotno > 2 || symtabno - gotsym) {
+ fprintf(stderr,
+ "%s: '%s' contains unexpected GOT entries\n",
+ program_name, path);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static inline bool FUNC(get_symbols)(const char *path, void *vdso)
+{
+ const ELF(Ehdr) *ehdr = vdso;
+ void *shdrs, *symtab;
+ ELF(Shdr) *shdr;
+ const ELF(Sym) *sym;
+ char *strtab, *name;
+ uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j;
+ uint64_t offset;
+ uint32_t flags;
+
+ shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+ sh_count = swap_uint16(ehdr->e_shnum);
+ sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+ for (i = 0; i < sh_count; i++) {
+ shdr = shdrs + (i * sh_entsize);
+
+ if (swap_uint32(shdr->sh_type) == SHT_SYMTAB)
+ break;
+ }
+
+ if (i == sh_count) {
+ fprintf(stderr, "%s: '%s' has no symbol table\n", program_name,
+ path);
+ return false;
+ }
+
+ /* Get flags */
+ flags = swap_uint32(ehdr->e_flags);
+ if (elf_class == ELFCLASS64)
+ elf_abi = ABI_N64;
+ else if (flags & EF_MIPS_ABI2)
+ elf_abi = ABI_N32;
+ else
+ elf_abi = ABI_O32;
+
+ /* Get symbol table. */
+ symtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+ st_entsize = FUNC(swap_uint)(shdr->sh_entsize);
+ st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize;
+
+ /* Get string table. */
+ shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize);
+ strtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+ /* Write offsets for symbols needed by the kernel. */
+ for (i = 0; vdso_symbols[i].name; i++) {
+ if (!(vdso_symbols[i].abis & elf_abi))
+ continue;
+
+ for (j = 0; j < st_count; j++) {
+ sym = symtab + (j * st_entsize);
+ name = strtab + swap_uint32(sym->st_name);
+
+ if (!strcmp(name, vdso_symbols[i].name)) {
+ offset = FUNC(swap_uint)(sym->st_value);
+
+ fprintf(out_file,
+ "\t.%s = 0x%" PRIx64 ",\n",
+ vdso_symbols[i].offset_name, offset);
+ break;
+ }
+ }
+
+ if (j == st_count) {
+ fprintf(stderr,
+ "%s: '%s' is missing required symbol '%s'\n",
+ program_name, path, vdso_symbols[i].name);
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/kernel/arch/mips/vdso/gettimeofday.c b/kernel/arch/mips/vdso/gettimeofday.c
new file mode 100644
index 000000000..ce89c9e29
--- /dev/null
+++ b/kernel/arch/mips/vdso/gettimeofday.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/compiler.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/time.h>
+
+#include <asm/clocksource.h>
+#include <asm/io.h>
+#include <asm/mips-cm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+static __always_inline int do_realtime_coarse(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ ts->tv_sec = data->xtime_sec;
+ ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ return 0;
+}
+
+static __always_inline int do_monotonic_coarse(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u32 to_mono_sec;
+ u32 to_mono_nsec;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ ts->tv_sec = data->xtime_sec;
+ ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+
+ to_mono_sec = data->wall_to_mono_sec;
+ to_mono_nsec = data->wall_to_mono_nsec;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_sec += to_mono_sec;
+ timespec_add_ns(ts, to_mono_nsec);
+
+ return 0;
+}
+
+#ifdef CONFIG_CSRC_R4K
+
+static __always_inline u64 read_r4k_count(void)
+{
+ unsigned int count;
+
+ __asm__ __volatile__(
+ " .set push\n"
+ " .set mips32r2\n"
+ " rdhwr %0, $2\n"
+ " .set pop\n"
+ : "=r" (count));
+
+ return count;
+}
+
+#endif
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static __always_inline u64 read_gic_count(const union mips_vdso_data *data)
+{
+ void __iomem *gic = get_gic(data);
+ u32 hi, hi2, lo;
+
+ do {
+ hi = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+ lo = __raw_readl(gic + GIC_UMV_SH_COUNTER_31_00_OFS);
+ hi2 = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+ } while (hi2 != hi);
+
+ return (((u64)hi) << 32) + lo;
+}
+
+#endif
+
+static __always_inline u64 get_ns(const union mips_vdso_data *data)
+{
+ u64 cycle_now, delta, nsec;
+
+ switch (data->clock_mode) {
+#ifdef CONFIG_CSRC_R4K
+ case VDSO_CLOCK_R4K:
+ cycle_now = read_r4k_count();
+ break;
+#endif
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+ case VDSO_CLOCK_GIC:
+ cycle_now = read_gic_count(data);
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ delta = (cycle_now - data->cs_cycle_last) & data->cs_mask;
+
+ nsec = (delta * data->cs_mult) + data->xtime_nsec;
+ nsec >>= data->cs_shift;
+
+ return nsec;
+}
+
+static __always_inline int do_realtime(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u64 ns;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ if (data->clock_mode == VDSO_CLOCK_NONE)
+ return -ENOSYS;
+
+ ts->tv_sec = data->xtime_sec;
+ ns = get_ns(data);
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, ns);
+
+ return 0;
+}
+
+static __always_inline int do_monotonic(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u64 ns;
+ u32 to_mono_sec;
+ u32 to_mono_nsec;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ if (data->clock_mode == VDSO_CLOCK_NONE)
+ return -ENOSYS;
+
+ ts->tv_sec = data->xtime_sec;
+ ns = get_ns(data);
+
+ to_mono_sec = data->wall_to_mono_sec;
+ to_mono_nsec = data->wall_to_mono_nsec;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_sec += to_mono_sec;
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, ns + to_mono_nsec);
+
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ const union mips_vdso_data *data = get_vdso_data();
+ struct timespec ts;
+ int ret;
+
+ ret = do_realtime(&ts, data);
+ if (ret)
+ return ret;
+
+ if (tv) {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+
+ if (tz) {
+ tz->tz_minuteswest = data->tz_minuteswest;
+ tz->tz_dsttime = data->tz_dsttime;
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+ const union mips_vdso_data *data = get_vdso_data();
+ int ret;
+
+ switch (clkid) {
+ case CLOCK_REALTIME_COARSE:
+ ret = do_realtime_coarse(ts, data);
+ break;
+ case CLOCK_MONOTONIC_COARSE:
+ ret = do_monotonic_coarse(ts, data);
+ break;
+ case CLOCK_REALTIME:
+ ret = do_realtime(ts, data);
+ break;
+ case CLOCK_MONOTONIC:
+ ret = do_monotonic(ts, data);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ /* If we return -ENOSYS libc should fall back to a syscall. */
+ return ret;
+}
diff --git a/kernel/arch/mips/vdso/sigreturn.S b/kernel/arch/mips/vdso/sigreturn.S
new file mode 100644
index 000000000..715bf5993
--- /dev/null
+++ b/kernel/arch/mips/vdso/sigreturn.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <uapi/asm/unistd.h>
+
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+ .section .text
+ .cfi_sections .debug_frame
+
+LEAF(__vdso_rt_sigreturn)
+ .cfi_startproc
+ .frame sp, 0, ra
+ .mask 0x00000000, 0
+ .fmask 0x00000000, 0
+ .cfi_signal_frame
+
+ li v0, __NR_rt_sigreturn
+ syscall
+
+ .cfi_endproc
+ END(__vdso_rt_sigreturn)
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+LEAF(__vdso_sigreturn)
+ .cfi_startproc
+ .frame sp, 0, ra
+ .mask 0x00000000, 0
+ .fmask 0x00000000, 0
+ .cfi_signal_frame
+
+ li v0, __NR_sigreturn
+ syscall
+
+ .cfi_endproc
+ END(__vdso_sigreturn)
+
+#endif
diff --git a/kernel/arch/mips/vdso/vdso.h b/kernel/arch/mips/vdso/vdso.h
new file mode 100644
index 000000000..cfb1be441
--- /dev/null
+++ b/kernel/arch/mips/vdso/vdso.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
+
+/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
+#undef CONFIG_64BIT
+#define CONFIG_32BIT 1
+#ifndef __ASSEMBLY__
+#include <asm-generic/atomic64.h>
+#endif
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <asm/asm.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+static inline unsigned long get_vdso_base(void)
+{
+ unsigned long addr;
+
+ /*
+ * We can't use cpu_has_mips_r6 since it needs the cpu_data[]
+ * kernel symbol.
+ */
+#ifdef CONFIG_CPU_MIPSR6
+ /*
+ * lapc <symbol> is an alias to addiupc reg, <symbol> - .
+ *
+ * We can't use addiupc because there is no label-label
+ * support for the addiupc reloc
+ */
+ __asm__("lapc %0, _start \n"
+ : "=r" (addr) : :);
+#else
+ /*
+ * Get the base load address of the VDSO. We have to avoid generating
+ * relocations and references to the GOT because ld.so does not peform
+ * relocations on the VDSO. We use the current offset from the VDSO base
+ * and perform a PC-relative branch which gives the absolute address in
+ * ra, and take the difference. The assembler chokes on
+ * "li %0, _start - .", so embed the offset as a word and branch over
+ * it.
+ *
+ */
+
+ __asm__(
+ " .set push \n"
+ " .set noreorder \n"
+ " bal 1f \n"
+ " nop \n"
+ " .word _start - . \n"
+ "1: lw %0, 0($31) \n"
+ " " STR(PTR_ADDU) " %0, $31, %0 \n"
+ " .set pop \n"
+ : "=r" (addr)
+ :
+ : "$31");
+#endif /* CONFIG_CPU_MIPSR6 */
+
+ return addr;
+}
+
+static inline const union mips_vdso_data *get_vdso_data(void)
+{
+ return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE);
+}
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static inline void __iomem *get_gic(const union mips_vdso_data *data)
+{
+ return (void __iomem *)data - PAGE_SIZE;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+#endif /* __ASSEMBLY__ */
diff --git a/kernel/arch/mips/vdso/vdso.lds.S b/kernel/arch/mips/vdso/vdso.lds.S
new file mode 100644
index 000000000..8df7dd53e
--- /dev/null
+++ b/kernel/arch/mips/vdso/vdso.lds.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
+#elif _MIPS_SIM == _MIPS_SIM_NABI32
+OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips")
+#else
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips")
+#endif
+
+OUTPUT_ARCH(mips)
+
+SECTIONS
+{
+ PROVIDE(_start = .);
+ . = SIZEOF_HEADERS;
+
+ /*
+ * In order to retain compatibility with older toolchains we provide the
+ * ABI flags section ourself. Newer assemblers will automatically
+ * generate .MIPS.abiflags sections so we discard such input sections,
+ * and then manually define our own section here. genvdso will patch
+ * this section to have the correct name/type.
+ */
+ .mips_abiflags : { *(.mips_abiflags) } :text :abiflags
+
+ .reginfo : { *(.reginfo) } :text :reginfo
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+ .text : { *(.text*) } :text
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ .rodata : { *(.rodata*) } :text
+
+ _end = .;
+ PROVIDE(end = .);
+
+ /DISCARD/ : {
+ *(.MIPS.abiflags)
+ *(.gnu.attributes)
+ *(.note.GNU-stack)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
+}
+
+PHDRS
+{
+ /*
+ * Provide a PT_MIPS_ABIFLAGS header to assign the ABI flags section
+ * to. We can specify the header type directly here so no modification
+ * is needed later on.
+ */
+ abiflags 0x70000003;
+
+ /*
+ * The ABI flags header must exist directly after the PT_INTERP header,
+ * so we must explicitly place the PT_MIPS_REGINFO header after it to
+ * stop the linker putting one in at the start.
+ */
+ reginfo 0x70000000;
+
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
+}
+
+VERSION
+{
+ LINUX_2.6 {
+#ifndef DISABLE_MIPS_VDSO
+ global:
+ __vdso_clock_gettime;
+ __vdso_gettimeofday;
+#endif
+ local: *;
+ };
+}
diff --git a/kernel/arch/mips/vr41xx/Kconfig b/kernel/arch/mips/vr41xx/Kconfig
index c1be6b37f..74927b4d4 100644
--- a/kernel/arch/mips/vr41xx/Kconfig
+++ b/kernel/arch/mips/vr41xx/Kconfig
@@ -8,7 +8,7 @@ config CASIO_E55
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ISA
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -18,7 +18,7 @@ config IBM_WORKPAD
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select ISA
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -28,7 +28,7 @@ config TANBAC_TB022X
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select HW_HAS_PCI
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -44,7 +44,7 @@ config VICTOR_MPC30X
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select HW_HAS_PCI
select PCI_VR41XX
select SYS_SUPPORTS_32BIT_KERNEL
@@ -55,7 +55,7 @@ config ZAO_CAPCELLA
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
- select IRQ_CPU
+ select IRQ_MIPS_CPU
select HW_HAS_PCI
select PCI_VR41XX
select SYS_SUPPORTS_32BIT_KERNEL
diff --git a/kernel/arch/mips/xilfpga/Kconfig b/kernel/arch/mips/xilfpga/Kconfig
new file mode 100644
index 000000000..42a030a0e
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/Kconfig
@@ -0,0 +1,9 @@
+choice
+ prompt "Machine type"
+ depends on MACH_XILFPGA
+ default XILFPGA_NEXYS4DDR
+
+config XILFPGA_NEXYS4DDR
+ bool "Nexys4DDR by Digilent"
+
+endchoice
diff --git a/kernel/arch/mips/xilfpga/Makefile b/kernel/arch/mips/xilfpga/Makefile
new file mode 100644
index 000000000..a4deec6fa
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilfpga
+#
+
+obj-y += init.o
+obj-y += intc.o
+obj-y += time.o
diff --git a/kernel/arch/mips/xilfpga/Platform b/kernel/arch/mips/xilfpga/Platform
new file mode 100644
index 000000000..ed375afe3
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/Platform
@@ -0,0 +1,3 @@
+platform-$(CONFIG_MACH_XILFPGA) += xilfpga/
+cflags-$(CONFIG_MACH_XILFPGA) += -I$(srctree)/arch/mips/include/asm/mach-xilfpga
+load-$(CONFIG_MACH_XILFPGA) += 0xffffffff80100000
diff --git a/kernel/arch/mips/xilfpga/init.c b/kernel/arch/mips/xilfpga/init.c
new file mode 100644
index 000000000..ce2aee216
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/init.c
@@ -0,0 +1,57 @@
+/*
+ * Xilfpga platform setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/prom.h>
+
+#define XILFPGA_UART_BASE 0xb0401000
+
+const char *get_system_type(void)
+{
+ return "MIPSfpga";
+}
+
+void __init plat_mem_setup(void)
+{
+ __dt_setup_arch(__dtb_start);
+ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+}
+
+void __init prom_init(void)
+{
+ setup_8250_early_printk_port(XILFPGA_UART_BASE, 2, 50000);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init device_tree_init(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ unflatten_and_copy_device_tree();
+}
+
+static int __init plat_of_setup(void)
+{
+ if (!of_have_populated_dt())
+ panic("Device tree not present");
+
+ if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
+ panic("Failed to populate DT");
+
+ return 0;
+}
+arch_initcall(plat_of_setup);
diff --git a/kernel/arch/mips/xilfpga/intc.c b/kernel/arch/mips/xilfpga/intc.c
new file mode 100644
index 000000000..c4d1a716b
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/intc.c
@@ -0,0 +1,25 @@
+/*
+ * Xilfpga interrupt controller setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <asm/irq_cpu.h>
+
+static struct of_device_id of_irq_ids[] __initdata = {
+ { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+ {},
+};
+
+void __init arch_init_irq(void)
+{
+ of_irq_init(of_irq_ids);
+}
diff --git a/kernel/arch/mips/xilfpga/time.c b/kernel/arch/mips/xilfpga/time.c
new file mode 100644
index 000000000..cbb3fca7b
--- /dev/null
+++ b/kernel/arch/mips/xilfpga/time.c
@@ -0,0 +1,41 @@
+/*
+ * Xilfpga clocksource/timer setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/of.h>
+
+#include <asm/time.h>
+
+void __init plat_time_init(void)
+{
+ struct device_node *np;
+ struct clk *clk;
+
+ of_clk_init(NULL);
+ clocksource_probe();
+
+ np = of_get_cpu_node(0, NULL);
+ if (!np) {
+ pr_err("Failed to get CPU node\n");
+ return;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+ return;
+ }
+
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+ clk_put(clk);
+}